#概要
ゲーム実況みたいな長尺の動画って編集するの大変です。
例
https://youtu.be/2aBizw3AqR0
ゲーム実況の場合、凄い雑に言うと、音が大きい所ってそこそこ目立つシーンだと思います。
ので、音量を元に自動で動画編集できたら良いな、と思ってやってみました。
#準備
私が調べた限り、プログラムで手軽に動画編集するのは、以下が一番簡単そうでした。
MoviePy
https://zulko.github.io/moviepy/
#実装
import numpy as np
import matplotlib.pyplot as plt
from moviepy.editor import *
name = '2019-04-03 23-51-38.mp4' # 入力動画
size = 1000000000 # 音量読込
threshold = 0.4 # 音量閾値(0~1)
plot = False # 波形表示切替
length = 0.5 # カット基点からの前後長
# 動画を開いて閾値取得
video = VideoFileClip(name, audio_buffersize=size)
buffer = video.audio.reader.buffer
threshold = buffer.max() * threshold
# 各値表示
print('duration : ' + str(video.duration))
print('audio_fps : ' + str(video.audio.fps))
print('max : ' + str(buffer.max()))
print('mean : ' + str(buffer.mean()))
print('threshold : ' + str(threshold))
if plot:
# 波形表示
plt.plot(buffer)
plt.show()
clips = {}
count = 0
index = 0
while True:
# 有効シーン有無確認
where = np.where(buffer[index:] > threshold)
if len(where[0]) < 1:
break
# 有効シーン位置出しと次出し設定
where = where[0][0] + index
print('where : ' + str(where))
index = int(video.audio.fps * length + where)
# カット編集
anchor = where / video.audio.fps
clips[count] = video.subclip(anchor - length, anchor + length)
count += 1
# 繋げて出力
videos = [clips[i] for i in range(count)]
result = concatenate(videos)
result.write_videofile("result.mp4")
sizeに頭の悪い値が入ってますがテキトウです。
変更しそうなのはname, threshold, length辺りだと思います。
thresholdの値が大きければ、より大きい音の所を抽出します。
lengthは前後長なので2倍の時間がトリミングされます。(0.5なら1秒)
#結果
途中ダブったりしてますが、まぁ、概ね良いので無視してます。 だいたい笑いと叫びが取れます。欲しいわけじゃないですが、舌打ちとか咳払いも目立ちますね。© Unity Technologies Japan/UCL pic.twitter.com/wjyEWZKn5F
— 120/偽葵/青ユニ (@120byte) 2019年5月17日
#参考
https://githubja.com/zulko/moviepy
https://stackoverflow.com/questions/28758474/how-to-concatenate-videos-in-moviepy