CSV のタイムスタンプに基づいて FFmpeg でビデオを高速化するにはどうすればよいですか?

CSV のタイムスタンプに基づいて FFmpeg でビデオを高速化するにはどうすればよいですか?

FFmpegでビデオを高速化することに関しては、すでに次のような質問があります。これです

私の質問は、外部 CSV を介して高速化される複数のセクションを指定する方法もあるかどうかです。

私の CSV は次のようになります:

start, end
00:00:03.296, 00:00:14.372,
00:00:16.388, 00:00:33.635,
00:00:33.693, 00:00:39.428,
00:00:39.460, 00:00:50.355,
00:00:50.355, 00:01:17.892,
00:01:17.892, 00:01:19.845,
00:01:19.845, 00:01:47.616,

これらは、10 倍の速度で再生される正確なセクション (1 行に 1 つのセクション、各セクションの開始と終了を定義する 2 つのタイムスタンプ) です。残りは元の再生速度を維持します。

これを実行する方法はありますか?

答え1

各ビデオフレームのPTSタイムスタンプを設定するには、設定複雑なネストされた式でフィルターしますif

以下の回答は、プログラムで必要なより複雑な表現を作成する知識があることを前提とした、単なる「概念実証」です。このソリューションでは、入力ビデオのフレームレートが固定されており、入力フレーム番号から入力タイムスタンプを簡単に計算できることを前提としています。

注:
タイムスタンプを設定してビデオの一部を高速化すると、可変フレームレート (VFR) ビデオが作成されますが、すべてのビデオ プレーヤーで適切に再生されない可能性が
あります。すべてのビデオを 10 倍に高速化し、元のレートの部分で各フレームを 10 回複製して、固定フレームレート ビデオを作成する方がよい場合があります。OpenCV
でフレームを読み取り、OpenCV を使用して書き込む Python スクリプト (または FFmpeg へのパイプ) を使用すると、フレームを複製するのは比較的簡単であることに注意してください。


次の入力ファイル (1fps で 40 フレーム) があると仮定します。

ffmpeg -y -f lavfi -i testsrc=size=192x108:rate=1:duration=40 -c:v libx264 -g 1 input.mp4

入力ビデオのタイムスタンプは次のとおりです。

 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,

範囲 [0, 19] と [30, 39] で速度を測定し、次の出力タイムスタンプを取得するとします。

 0,    1,    2,    3,    4,    5,    6,    7,    8,    9,
10, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9,
11,   12,   13,   14,   15,   16,   17,   18,   19,   20,
21, 21.1, 21.2, 21.3, 21.4, 21.5, 21.6, 21.7, 21.8, 21.9,

次の FFmpeg コマンドを使用できます。

ffmpeg -y -r 100 -i input.mp4 -fps_mode:v passthrough -vf "setpts='(if(lt(N,10), N, if(lt(N,20), ((N-10)/10)+10, if(lt(N,30), 11+(N-20), 21+(N-30)/10))))/TB'" -c:v libx264 -g 1 output.mp4

  • -r 100パケット持続時間を 10 ミリ秒に設定するために使用されます (パケット持続時間が短いほど、タイムスタンプの解像度が高くなります)。
  • -fps_mode:v passthrough- 各入力フレームを入力から出力に渡します (100 fps レートのためフレームが重複することはありません)。
  • -vf "setpts='(if(lt(N,10), N, if(lt(N,20), ((N-10)/10)+10, if(lt(N,30), 11+(N-20), 21+(N-30)/10))))/TB'"-ifタイムスタンプを調整するために式といくつかの計算を使用します。
    ifは、if(条件、true の場合の値、false の場合の値) に適用されます。
    Nは入力フレーム番号で、0 からカウントを開始します。最初の 10 フレーム
    if(lt(N,10), N, ...の PTS を に設定し、時間ベースで秒単位の時間で割ります。N
    /TB
  • -g 1- テスト用に GOP サイズを 1 に設定します (削除します)。これにより、FFprobe を使用するときに PTS がソートされた状態を維持します。

FFprobe を使用して出力タイムスタンプを検証します。
ffprobe -select_streams v:0 -of default=noprint_wrappers=1 -show_entries packet=pts_time output.mp4

出力は予想どおりです:

pts_time=0.000000
pts_time=1.000000
pts_time=2.000000
pts_time=3.000000
pts_time=4.000000
pts_time=5.000000
pts_time=6.000000
pts_time=7.000000
pts_time=8.000000
pts_time=9.000000
pts_time=10.000000
pts_time=10.100000
pts_time=10.190000
pts_time=10.300000
pts_time=10.400000
pts_time=10.500000
pts_time=10.600000
pts_time=10.700000
pts_time=10.800000
pts_time=10.900000
pts_time=11.000000
pts_time=12.000000
pts_time=13.000000
pts_time=14.000000
pts_time=15.000000
pts_time=16.000000
pts_time=17.000000
pts_time=18.000000
pts_time=19.000000
pts_time=20.000000
pts_time=21.000000
pts_time=21.100000
pts_time=21.200000
pts_time=21.300000
pts_time=21.400000
pts_time=21.500000
pts_time=21.600000
pts_time=21.700000
pts_time=21.800000
pts_time=21.900000

出力を示すアニメーション GIF:
ここに画像の説明を入力してください
( を使用して作成ffmpeg -y -i output.mp4 -filter_complex "[0:v]split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -r 1 output.gif)

関連情報