![見出し画像](https://assets.st-note.com/production/uploads/images/137879934/rectangle_large_type_2_3a9845e5bf3b6a7b1fb624fbd78356e4.jpeg?width=1200)
【Python】読み上げソフトの音声ファイル名をセリフにする
今回は読み上げソフト(voisona)で出力した音声ファイルの名前がトラック名?で扱いにくいので、一括で変更できるツールをPythonで書いた話です。
注意
このソフトウェアを使用したことによって生じたすべての障害・損害・不具 合等に関しては 一切の責任を負いません。各自の責任においてご使用ください。
もし冗長な部分等ありましたらコメント等で教えていただけると嬉しいです。
Rustでも書いてみました_24/07/16
概要
解決したいこと
最近ai音声読み上げソフトのvoisonaというツールを使っているのですが、音声ファイルを出力すると、自動で振られた番号が各文書のファイル名になってしまい、動画編集ツールなどで使おうとした際に、内容の確認に時間がかかる。というか面倒。
目標・道筋
ただ、voisonaは音声のセリフの入ったテキストファイルを同名で出力出来るので、それを参照してファイル名を変更できるのでは、と。
ちなみにセリフ内にあるスラッシュ記号などは削除したり、20文字に削ったりするので、セリフそのままというわけではなく、あくまで内容が判別できる程度です。
github
相変わらずコミットとか汚いですが…
import
今回はそこまで使いません。
import os
import re
import glob
osとフォルダのリストが欲しいため、globを追加。
def read_lines_textfile(file_name):
引数にファイル名を受け取って、同名のテキストファイルの内容の内、20文字を取得する関数です。
例えば、hoge.wavファイルからhogeというファイル名をこの関数に渡すと、hoge.txtの内容(text1参照)から20文字(text2参照)を切り出し、str型でreturnします。
# text1
今回は、M3 MacBook Proを購入したので、レビューしていこうと思います。
# text2
今回は、M3 MacBook Proを購
data_file = open(f"{file_name}.txt", 'r', encoding='utf-8')
data_fileにopen関数でファイル内容を代入します。open関数の引数は(ファイルパス, モード, 文字コード)の順で指定します。
今回はf"{file_name}.txt"で台詞の入ったテキストファイルのパスを、モードはopne関数の操作モードです。'r'は読み込みモードの指定です。encoding引数は文字コードを指定できます。今回はutf-8です。macでは使わなくても実行できますが、windowsでは指定しないとエラーを吐きます。
data = re.sub(r'[\\/:*?"<>|]+', '', data_file.read())
これはwindowsでファイル名に使っちゃいけない文字の削除です。data_file.read()を使って、ファイルの内容を読み込んでいます。
re.subについては以下参考。
data_file = data-file.replace("\n", "")
改行キーの削除。テキストファイルの改行キーを文字列として読み込んだ結果、パスと誤認する問題を回避。
data_file = data_file[0:20]
あんまり長いと見にくいので、20文字に抑えます。
return data_file
完成した文字列を返します。
この関数は後で呼び出すので頭の隅にでも。
while True:
いつも通り、プログラム全体の繰り返し用。
詳細は後述しますが、if文でbreakします。
print("フォルダのパスを…さい。")
フォルダパスの入力の要求。
folder_path = input()
フォルダパスの入力。
wav_files = glob.glob(f"{folder_path}/*.wav")
先ほどのフォルダ内にあるwavファイルのリストを、wav_filesというリスト型の変数に代入します。
*は正規表現で「直前のパターンが0回以上繰り返されること」を表すようです。このため、拡張子がwavのもののみリストにできます。
count = 0
count変数は最後のログで使用します。ファイルを操作した回数分インクリメント(厳密には+=)をして、操作回数をカウントします。
renamed_files_path = os.path.join(folder_path, "renamed_files", "")
フォルダを作る用のパスです。指定されたフォルダの中に「renamed_files」というフォルダを作ります。
通常はパスは「f"{folder_path}/renamed_files"」のようにstr型のテキストで指定すればいいのですが、これだとwindowsで使った際にエラーになります。これは、macやlinux(unix系)ではパスの区切りにスラッシュ(/)を使っているのに対して、windowsではパスの区切りにバックスラッシュ(\ or ¥)*を使っているため発生します。
今回はwindowsでもmacでも使えるようにするため、パスの区切り文字を直接書かないでパスを作成できる「os.path.join」を使用します。これは(多分)カンマで区切られた文字列をカンマの位置でパスを作ります。
例えば、以下のコードはmacでは"hoge/fuga/piyo.txt"、winでは"hoge\fuga\piyo.txt"と返します。
import os
print(os.path.join("hoge", "fuga", "piyo.txt"))
*: バックスラッシュは国によって当てられいる文字が異なるため、日本では¥マークとなる。そのためエクスプローラーのパス表示欄には¥マークがいっぱいある。ちなみに\文字の扱いに困ってないのは米国くらいとかなんとか…
os.makedirs(renamed_files_path, exist_ok=True)
入力されたフォルダ内に、os.makedirsでrenamed_filesというフォルダを作ります。exist_ok=Trueはフォルダが存在するかどうか確かめて存在しなかったら作る、ということが出来ます。
ここで作ったフォルダは名称変更後の音声ファイルを入れます。
for file in wav_files:
wav_filesはwavファイルのリストが入っているので、その分だけfor文で繰り返します。
fileにはwav_files内のリストの項目(wavのパス)が入っていきます。
file_name = file.replace(".wav", "")
ファイルの名前を取得するために、拡張子「.wav」をreplaceで削除します。
lines = read_lines_textfile(file_name)
linesに先ほどの関数で、テキストファイルの内容を取得します。関数の説明はもうしたので詳細は省きますが、テキストファイルのパスを渡すことで、テキストファイルの内容の20文字目までをlinesに代入します。
これで音声ファイルの変更後の名前が完成しました。
いつかインデックスの番号も振りたい。ただファイルの読み込み順だから一旦ソートしないと危ないけど元のファイルに順番の情報がないから、ソートの方法が思いつかない…
voice_file_path = os.path.join(renamed_files_path, f"{lines}.wav")
既にlines変数に完成した名称が代入されていますが、まだ親フォルダのパスがないので、ここで追加します。
先ほどのos.path.joinでパスを作成します。renamed_filesは先ほど作成した、保存先の「renamed_files」フォルダのパスです。それに.wavを追加して音声ファイルのパスの完成です。
os.rename(file, voice_file_path)
os.renameでファイル名を変更します。os.rename(変更前, 変更後)の順で使用します。今回for文のfile変数はいじっていないので、変更前のパスが残っています。それを変更前として、先ほどまで作っていた変更後のパス「voice_file_path」を使います。
count += 1
カウント変数のインクリメント(?)。
print(f"{count}個のファイルの名称を変更しました。")
成功確認の意味も含めてログ(?)を出します。
いつか失敗した場合などの処理も実装したい…
print("もう一度使用しますか?(y/n)")…
繰り返すかどうかの確認。y以外を入力すればbreakします。yを入力すればwhile Trueまで戻ります。
print("もう一度使用しますか?(y/n)")
if input() != "y":
break
まとめ
というか感想。
今回ベースというか名称変更の機能自体は簡単でしたが、windowsにも対応するとした際のパス問題や文字コード系のエラーが多いように感じました。
それとnoteに書くときに一行ずつ確認していると、バグになりそうな箇所に気付けていいかも知れません。ラバーダック・デバッグ。
テスト
一応以下のテキストファイルを用いたテストで、ちゃんと/などを削除して正しい操作ができるかテストしました。
hoge_hoge_hoge
slash_/slash_/slash
backslash_\backslash_\backslash
結果
Mac
renamed_files % ls
backslash_backslash_.wav slash_slash_slash.wav
hoge_hoge_hoge.wav
Windows
PS E:*************************\Test_files\renamed_files> dir
ディレクトリ: E:***********************\Test_files\renamed_files
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2024/04/20 8:56 0 backslash_backslash_.wav
-a---- 2024/04/20 8:56 0 hoge_hoge_hoge.wav
-a---- 2024/04/20 8:56 0 slash_slash_slash.wav
ディレクトリは***で隠してます。
ちゃんと変換できてますね。