🐈

Google Cloud Storageにアップロードした動画が破損する原因

2024/11/22に公開

結論から書くと、ffmpegの品質設定の問題でした。

経緯

フレームに分解した動画をffmpegで再結合した動画をcloud storageにアップロードしたのですが、クラウド上で動画ファイルが破損していました。
ローカルでは問題なく再生できます。
原因を突き止めるためにまずオリジナルの動画と再結合した動画をアップロードしたところ、オリジナルの動画のみ問題なくアップロードできたという結果に。

原因

ffmpegではフレームから動画にマージする際に-crfというオプションで品質を設定できるのですが、これを0(完全に無劣化)にしていたのが原因でした。
このオプションではデフォルト値が23, crfが18で無劣化に見える品質のようです。

対策

-crfの値を16にしたところ、問題なくアップロードできました。
参考までに、実際に使用した動画を結合するpythonコードを貼っておきます。

def run_ffmpeg(args: List[str]) -> bool:
    commands = [ 'ffmpeg', '-hide_banner', '-loglevel', 'error' ]
    commands.extend(args)
    try:
        subprocess.run(commands, stderr = subprocess.PIPE, check = True)
        return True
    except subprocess.CalledProcessError as exception:
        log.debug(exception.stderr.decode().strip(), __name__.upper())
        return False

def merge_video(frames_dir: str, output_path: str, video_fps: float) -> bool:
    frames_pattern = os.path.join(frames_dir, '%5d' + '.jpg')
    commands = [ '-hwaccel', 'auto', '-r', str(video_fps), '-i', frames_pattern, '-c:v', 'libx264' ]
    commands.extend([ '-crf', '16', '-preset', 'verufast' ])
    commands.extend([ '-pix_fmt', 'yuv420p', '-colorspace', 'bt709', '-y', output_path ])
    return run_ffmpeg(commands)

参考: https://qiita.com/yh1224/items/38d4ef1cf768aa3368d6#h264-品質設定

Discussion