特定の位置をシークした後にエンコードし、最初のフレームをキーフレームにしたいのですが、使用したコマンドは次のとおりです。
ffmpeg -ss 300 -i howimet.mp4 -acodec libfaac -ar 48000 -ab 128k -ac 2 -vcodec libx264 -vf "scale=480:270" -f mpegts -force_key_frames 300 -t 120 howimet2.ts
-force_key_frames は、キーフレームを作成する位置を探すように設定されています。私は次のスクリプトを使用します(ここ)最初のフレームがキーフレームであるかどうかを確認する
ffprobe -show_frames -v quiet howimet2.ts | awk -F= ' /pict_type=/ { if (index($2, "I")) { i=1; } else { i=0; } }
/pkt_pts_time/ { if (i && ($2 >= 0)) print $2; }
' | head -n 1
結果は、最初のキーフレームが 0 秒目に配置されていないことを示しています。
私のコマンドは正しくないようです。何が足りないのでしょうか?
答え1
ビデオをエンコードする場合、最初のフレームもっているキーフレームになります。これは完全にエンコードされた最初のフレームであり、後続のフレームではフレーム間予測に使用されます。また、コード化されたビデオ シーケンスの先頭には、デコーダーに更新を指示する H.264 アクセス ユニットがあります。
したがって、何をしているかに関係なく、ビットストリームをコピーする場合を除き、ビデオを再エンコードすることになり、最初のフレームはキーフレームである必要があります。
さて、何らかの理由で、ストリームの開始時間にオフセットがあります。つまり、すべてのプレゼンテーション タイムスタンプもこのオフセットに従ってシフトされます。出力の先頭を調べるとffprobe -show_frames
、フレーム 0 は確かにキーフレームですが、PTS が異なることがわかります。
これを補正するには、すべての PTS から開始時間を減算します。
答え2
前述のように、ビデオの最初のフレームは I フレームである必要があります。問題はエンコード (またはコピー) ではなくデコードから生じます。入力の前に -ss があると不正確になるため、ffmpeg は目的の場所に到達するために最善を尽くします。ffmpeg はその場所を通過したため、最初のタイムスタンプがゼロではないことが通知されます。
-i の後に 2 番目の -ss を試すことをお勧めします。-ss 299 -i input -ss 1 のように入力します。
これは、目的の場所まで移動し、処理の前に 1 秒間デコードすることを示しています。これで PT の問題が解決するかどうかはわかりませんが、正しい方向に進むことを願っています。
指摘しておきますが、force_key_frames コマンドはあなたが考えているような動作をしていないと思います。もし何か動作をしているとしたら、おそらく 300 秒ごとに出力にキー フレームを追加するように指示しているだけでしょうが、これは単なる推測です。つまり、出力の最初のフレームだけがキー フレーム (t=120) になります。
答え3
「-g」でGOPサイズを設定する
正確さを示すために、1秒のセグメントを示します
ffmpeg -i in.mkv -g 30 -hls_time 1 -hls_list_size 0 index.m3u8
m3u8 は次のようになります:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:1.001000,
index0.ts
#EXTINF:1.001000,
index1.ts
#EXTINF:1.001000,
index2.ts
#EXTINF:1.001000,
index3.ts
#EXTINF:1.001000,
index4.ts
#EXTINF:1.001000,
index5.ts
#EXTINF:1.001000,
index6.ts
#EXTINF:1.001000,
index7.ts
#EXTINF:1.001000,
index8.ts
#EXTINF:1.001000,
index9.ts
#EXTINF:1.001000,
index10.ts
#EXTINF:1.001000,
index11.ts
#EXTINF:1.001000,
index12.ts
#EXTINF:1.001000,
index13.ts
#EXTINF:1.001000,
....