0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ffmpegでLGPLビルドだと「libx264 / libx265」が使えなくて困った話

Posted at

⚠️ 注意

本記事に掲載している内容は、個人が学習・検証目的のものです。

業務情報、社外秘情報、特定の企業・組織に関する内容は一切含まれていません。
利用は自己責任でお願いします。

概要

ffmpegでLGPL版に差し替えたことで libx264 / libx265 が使えなくなり、切り出し(=再エンコード)が失敗してしまった場合の対処法を記載します

image.png

今回のcase

case1(動画の切り出しを想定)

    cmd = [
        ffmpeg_cmd,
        "-y",
        "-ss", f"{start_sec:.3f}",
        "-to", f"{end_sec:.3f}",
        "-fflags", "+genpts",
        "-i", in_p,
        "-avoid_negative_ts", "make_zero",
        "-map", "0:v:0", 
        "-c:v", "libx264",
        "-preset", "fast",
        "-pix_fmt", "yuv420p",
        "-movflags", "+faststart",
        out_p,
    ]

case2(動画切り出し進捗バー用を想定)

        args = [
            "-y",
            "-ss", f"{start_sec:.3f}",
            "-to", f"{end_sec:.3f}",
            "-fflags", "+genpts",
            "-i", input_path,
            "-avoid_negative_ts", "make_zero",
            "-map", "0:v:0",
            "-c:v", "libx264",  
            "-preset", "fast",
            "-pix_fmt", "yuv420p",
            "-movflags", "+faststart",
            "-progress", "pipe:1",
            "-nostats",
            output_path,
        ]

方針1:「再エンコードなし(stream copy)」にする

H.264/AAC の mp4 を切り出すだけなら、基本これでOKです。
(めちゃ速い・劣化なし)

-c copy:再エンコードしない
-avoid_negative_ts make_zero:開始時刻ズレ対策
※ ただし GOP(キーフレーム)境界の関係で、開始が数フレームずれることがあります

case1(動画の切り出しを想定)

    cmd = [
        ffmpeg_cmd,
        "-y",
        "-ss", f"{start_sec:.3f}",
        "-to", f"{end_sec:.3f}",
        "-fflags", "+genpts",
        "-i", in_p,
        "-avoid_negative_ts", "make_zero",
        "-map", "0:v:0",
        "-c:v", "copy",
        "-movflags", "+faststart",
        out_p,
    ]

case2(動画切り出し進捗バー用を想定)

        args = [
            "-y",
            "-ss", f"{start_sec:.3f}",
            "-to", f"{end_sec:.3f}",
            "-fflags", "+genpts",
            "-i", input_path,
            "-avoid_negative_ts", "make_zero",
            "-map", "0:v:0",
            "-c:v", "copy",    
            "-movflags", "+faststart",
            "-progress", "pipe:1",
            "-nostats",
            output_path,
        ]

結論(最大どのくらいズレる?)
▶ 最大で「1 GOP(キーフレーム間隔)」分ズレます
= 0.5 秒 ~ 数秒が理論上の最大です。

ただし 現実的にはもっと小さいことがほとんどです。
もう少し正確に言うと
-c copy(再エンコードなし)の切り出しは:

開始位置:
👉 指定時刻 より前の直近キーフレーム まで戻る
終了位置:
👉 指定時刻 以降の次のキーフレーム まで進むことがある

つまり:
[ 前のキーフレーム ]----指定start----(理想)
実際は 👇
[ 前のキーフレーム ]←ここから始まる

ちょっと前から始まって、ちょっと後で終わるイメージ


ズレ量を決める要因
1)GOPサイズ(キーフレーム間隔)

動画の種類 GOPの目安 最大ズレ
スマホ動画 0.5〜1秒 ~1秒
一般MP4 1〜2秒 ~2秒
長尺圧縮動画 2〜5秒 ~5秒
極端な圧縮 10秒以上 まれ

2)フレームレート
30fps / 60fps → 体感ズレは小さく見える
低fps → ズレが目立ちやすい


参考:ズレを最小化するコマンド小技 これを使うと copyでもズレが小さくなりやすいです:
-ss を -i の後ろに置く
ただし速度は落ちます

理由は ffmpeg の「-ss の置き場所」で処理方式が変わるからです。
copy のズレが減りやすいのは、その差が効きます。

-ss を「-i の前」に置く場合(高速だけどズレやすい)

ffmpeg -ss 10 -to 20 -i in.mp4 -c copy out.mp4
これは **入力を開く前に“だいたいこの辺”へジャンプ(シーク)**します。
このとき ffmpeg は キーフレーム(Iフレーム)単位でしか正確に飛べないので、

指定時刻の 直前のキーフレーム から始まる

その結果、開始が少し前にずれるという動作になりやすいです。
(その代わりめちゃ速い)

-ss を「-i の後」に置く場合(遅いけどズレが減りやすい)
ffmpeg -i in.mp4 -ss 10 -to 20 -c copy out.mp4
これは まず入力を開いてから、
いったんデコード(読み進め)指定の時刻まで到達したところで出力を開始
という動きになりやすく、結果として

目標時刻に より近い位置から切り出せる

ことが多いです。
(ただし -c copy だと完全にフレーム単位の厳密さは出ません。GOP境界の制約は残ります)


方針2:「LGPLビルドで利用可能なエンコーダ」にする

リスクとして以下が挙げられます
1) 速度が遅い・CPU負荷が高い
-c copy と比べると 数倍〜数十倍時間がかかることがあります。
Core i5 / RAM8GB だと、長尺や高解像度は体感で重くなります。

2) 出力品質(画質劣化)とビットレート増
再エンコードなので、
・多少の画質劣化
・出力サイズが大きくなる/小さくなる
が起きます。

case1(動画の切り出しを想定)

    cmd = [
        ffmpeg_cmd,
        "-y",
        "-ss", f"{start_sec:.3f}",
        "-to", f"{end_sec:.3f}",
        "-fflags", "+genpts",
        "-i", in_p,
        "-avoid_negative_ts", "make_zero",
        "-map", "0:v:0",
        "-c:v", "libopenh264",
        "-pix_fmt", "yuv420p",
        "-movflags", "+faststart",
        out_p,
    ]

case2(動画切り出し進捗バー用を想定)

        args = [
            "-y",
            "-ss", f"{start_sec:.3f}",
            "-to", f"{end_sec:.3f}",
            "-fflags", "+genpts",
            "-i", input_path,
            "-avoid_negative_ts", "make_zero",
            "-map", "0:v:0",
            "-c:v", "libopenh264",  
            "-pix_fmt", "yuv420p",
            "-movflags", "+faststart",
            "-progress", "pipe:1",
            "-nostats",
            output_path,
        ]

どのくらい時間がかかる?

前提条件
CPU:Core i5(第8〜10世代クラス)
メモリ:8GB
OS:Windows
入力:H.264 MP4
出力:H.264(libopenh264)
音声:なし
フィルタ:なし

切り出し長 × 処理時間の目安

切り出し長 体感処理時間 備考
5秒 0.5〜2秒 ほぼ一瞬
10秒 1〜4秒 UI待ち許容
30秒 10~30秒 少し待つ
1分 30~90秒 実時間前後
3分 2~6分 やや重い
5分 4~10分 人によって不満
10分 8~20分 実務では難しい

なぜ libopenh264 は遅いのか
CPUエンコードのみ
x264 のような高度な最適化がない
並列化効率がやや低い
品質あたりのビット効率が控えめ
つまり
👉 **「正確だけど速くはない」**エンコーダです。

速度を左右する主因(重要)
① 解像度
720p:速い
1080p:普通
4K:激遅

② フレームレート
30fps:標準
60fps:約1.5〜2倍遅い

③ 切り出し開始位置
-ss を前に置く → 少し速い
-ss を後に置く → 正確だが遅い

copy / libopenh264 の最終使い分け指針

用途 おすすめ
プレビュー・仮切り -c copy
再解析用動画 -c copy
教育・比較・報告 libopenh264
秒単位が重要 libopenh264

※ちなみに今回は以下を使用しています
ffmpeg-N-122221-g1fcb201ab1-win64-lgpl.zip

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?