##なぜやるのか
・作成中の単語帳アプリの音声を楽に処理できるようにするため
・欲しい機能要件を満たすソフトが見つからなかったため。
・pythonを使ってみたいため。
##機能要件
・複数データを一度に処理し、無音部分をカットする
・処理と同時に命名規則に従って名前をつける(日本語音声:J_(num).mp3 台灣華語音声:T_(num).mp3)
##作成したプログラム
#初期設定+関数
import glob
import os
import subprocess
import librosa
import datetime
import librosa.display
import shutil
import time
import soundfile as sf
import numpy as np
from matplotlib import pyplot as plt
#xと一致した要素が配列の何番目かを取得
def my_index_multi(l, x):
return [i for i, _x in enumerate(l) if _x == x]
#フォルダの中身削除
def remove_dir(dirname):
shutil.rmtree(dirname)
os.mkdir(dirname)
#ファイルの名前づけ
def fileRename(firstNum):
#変換後のフォルダ削除
shutil.rmtree(DIR_m4a)
remove_dir(DIR_m4a_change)
remove_dir(DIR_wav)
remove_dir(DIR_wav_cut)
remove_dir(DIR_wav_change)
#元データをコピー
shutil.copytree(DIR_m4a_raw, DIR_m4a)
cmd = 'find ' + DIR_m4a +' -name \'.DS_Store\' -type f -ls -delete'
subprocess.run(cmd, shell=True)
xs = []
for root, dir, files in os.walk(DIR_m4a):
for f in files:
path = os.path.join(root, f)
xs.append((os.path.getmtime(path), path))
count = firstNum - 1
for mtime, path in sorted(xs):
count = count + 1
name = os.path.basename(path)
t = datetime.datetime.fromtimestamp(mtime)
os.rename(DIR_m4a + '/' + name,DIR_m4a_change + '/'+ LangName + '_' +'{0:04d}'.format(count) +'.m4a')
#mp4をwavに変換+音声カット
def mp4towav():
#global filename_m4a
filename_m4a = glob.glob(DIR_m4a_change + '/*.m4a')
fileNum = len(glob.glob(DIR_m4a_raw + '/*.m4a'))
#fileNum = sum(os.path.isfile(os.path.join(DIR_m4a_change, name)) for name in os.listdir(DIR_m4a_change))
for num in range(fileNum):
basename_without_ext = os.path.splitext(os.path.basename(filename_m4a[num]))[0]
newname = DIR_wav + '/%s.wav' % basename_without_ext
cmd = 'ffmpeg -i %s -f wav %s' %(filename_m4a[num], newname)
subprocess.run(cmd, shell=True)
#音声をカット
data, samplerate = sf.read(newname)
t = np.arange(0, len(data))/samplerate
b = abs(data) > 0.025 #閾値仮置き→閾値より大きい場合1,小さい場合0
high_num = my_index_multi(b, 1) #閾値を超えたデータを抜き出し
high_num_first = high_num[0]
high_num_last = high_num[-1]#配列の最後を取り出す
data_cut = data[high_num_first:high_num_last]
sf.write(DIR_wav_cut + '/%s.wav' %(basename_without_ext), data_cut, samplerate)
#声変更
#y, sr = librosa.load(DIR_wav_cut + '/%s.wav' %(basename_without_ext), sr=24000) # y is a numpy array of the wav file, sr = sample rate
#y_shifted = librosa.effects.pitch_shift(y, sr, n_steps=2) # shifted by 4 half steps
#soundfile.write(DIR_wav_change + '/%s.wav' %(basename_without_ext), y_shifted, sr)
#言語を選択+実行
def Lang_select(JorT,firstNumber):
if 'J'==JorT:
DIR_lang = 'soundJapanese'
elif 'T'==JorT:
DIR_lang = 'soundTaiwanese'
else:
DIR_lang = '0'
print('error')
global LangName
global DIR_m4a_raw
global DIR_m4a
global DIR_m4a_change
global DIR_wav
global DIR_wav_cut
global DIR_wav_change
LangName = JorT
DIR_m4a_raw = './' + DIR_lang + '/m4a_raw'
DIR_m4a = './' + DIR_lang + '/m4a'
DIR_m4a_change = './' + DIR_lang + '/m4a_change'
DIR_wav = './' + DIR_lang + '/wav'
DIR_wav_cut = './' + DIR_lang + '/wav_cut'
DIR_wav_change = './' + DIR_lang + '/wav_change'
fileRename(firstNumber)
mp4towav()
#実行例
Lang_select('J',1)
##今後やれたらやりたいこと
録音した音声の声質を変えることも一つの目的でしたが、単純なピッチシフトでは機械的な音声になってしまい断念しました、、、
自然な感じで音声を変換するのは難しいんでしょうかね、、、
##参考URL
python for文を初心者向けに解説!for文基礎はこれで完璧
https://udemy.benesse.co.jp/development/python-work/python-for.html
m4aをmp3に変換
https://bettamodoki.hatenadiary.jp/entry/20100621/1277140383
動画の無音部分を自動でカットする
https://nantekottai.com/2020/06/14/video-cut-silence/
Pythonのリストの要素のインデックス(何番目か)を取得
https://note.nkmk.me/python-list-index/
Pythonでリストの最後(一番後ろ)の値を取得する方法
https://qiita.com/komeiy/items/971ead35d33c25923222
ファイルの更新日時でソートする
https://qiita.com/norioc/items/e5272e00f358ef692cc4