参考にさせていただいた記事
この記事を参考にさせていただきました。
https://qiita.com/merarli/items/1b7819adbae7fad3c9b4
やったこと
YouTube動画の編集手法の一つである「ジャンプカット」の自動化に取り組みました。
Jupyter Notebookで作ってみました。OSはMacです。
FFmpegで無音時間を検出し、動画を切り出します。
こんな感じでできます。⇒ https://youtu.be/i2fFIWyXGXo
コード
import subprocess
import os
def mk_movieList(movie_folder):
files = os.listdir(movie_folder)
files = [x for x in files if x[-4:] == '.mp4'] ### x[-4]'後ろ4文字目以降'
files = [x for x in files if x[0] != '.']
return files
def mk_starts_ends(wk_dir, movie):
os.chdir(wk_dir)
output = subprocess.run(["ffmpeg", "-i", movie, "-af", "silencedetect=noise=-33dB:d=0.6", "-f", "null", "-"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(output)
s = str(output)
lines = s.split('\\n')
time_list =[]
for line in lines:
if "silencedetect" in line:
words = line.split(" ")
for i in range(len(words)):
if "silence_start" in words[i]:
time_list.append(float(words[i+1]))
if "silence_end" in words[i]:
time_list.append(float(words[i+1]))
print(time_list)
starts_ends = list(zip(*[iter(time_list)]*2))
return starts_ends
def mk_jumpcut(wk_dir, movie, starts_ends):
os.chdir(wk_dir)
for i in range(len(starts_ends)-1):
movie_name = movie.split(".")
splitfile = "./JumpCut/" + movie_name[0] + "_" + str(i) + ".mp4"
print(splitfile)
output = subprocess.run(["ffmpeg", "-i", movie, "-ss", str(starts_ends[i][1]), "-t", str(starts_ends[i+1][0]-starts_ends[i][1]), splitfile], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
movie_folder = "ここに素材動画が入っているフォルダの場所を記載してください。"
os.chdir(movie_folder)
wk_dir = os.path.abspath(".")
try:
os.mkdir("JumpCut")
except:
pass
movie_list = mk_movieList(movie_folder)
for movie in movie_list:
print(movie)
starts_ends = mk_starts_ends(wk_dir, movie)
print(starts_ends)
mk_jumpcut(wk_dir, movie, starts_ends)
こんな感じになります。
コード上の「movie_folder」で指定したフォルダの中に、更にJumpCutというフォルダができて...
こんな感じに動画が分割されます。これをまとめて、動画編集ソフトにブチ込んで再生すると
ジャンプカット動画が完成してます!!!!
重要なところ
output = subprocess.run(["ffmpeg", "-i", movie, "-af", "silencedetect=noise=-33dB:d=0.6", "-f", "null", "-"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
この行が無音時間を検出するコマンドをsubprocessで回しています。
「silencedetect=noise=-33dB:d=0.6」で無音状態の判定基準を決めています。
-33dBの音量が0.6秒続くと無音であると判定されるみたいです。
ここのパラメータは、動画ごとに調整が結構必要ですね。
ここで、返っていた結果をテキスト処理して、[無音開始時間,無音終了時間]のリストを作り、それをmk_jumpcutに渡して、動画を切り出しています。
一番良い感じの使い道
無音状態の判定基準を緩くして、長回しの動画で音声がある部分を切り取りたいときとか、
粗編集的に使うのが便利そうです。
完成版のジャンプカットを完全に自動化するには、パラメータの調整が必要になってきます。