1

私はlibavの上に構築された作業プログラムを持っています(またはffmpeg - ここでは専門知識が役に立ちます)。

h264 ビデオ / AAC オーディオでエンコードされた mp4 ビデオを取得し、それを MPEG TS に再多重化し、X 秒のチャンクにセグメント化します。これは、次の ffmpeg コマンドに似ています。

ffmpeg -y -i video.mp4 -c:a copy -bsf:a aac_adtstoasc -c:v copy -bsf:v h264_mp4toannexb -flags -global_header -map 0 -f segment -segment_time 10 -segment_list playlist.m3u8 -segment_format mpegts chunk_%03d.ts

コマンドラインを使用しない理由は、セグメントのサブセットのみを生成したいからです。したがって、ビデオが 8 秒から 12 秒の 10 セグメントになる場合 (キーフレームのためにセグメントが正確に望ましい長さになることはありません)、後でセグメント 3 から 7 を生成したいと思うかもしれません。

私のプログラムの完全なコードは、ここにあります。

ソースファイルからすべてのフレームをav_read_frame読み取り、remux (bitfilter プロセスを含む) して出力ファイルに書き込みます。最後の出力からの所要時間が目的のセグメントの長さに近づくか、それを超えると、出力ファイルをフラッシュして閉じ、次のセグメントを開いて続行します。

コードを変更してav_seek_frame、最初のセグメントの最後まで実行し、そこから開始しようとしました (また、2 番目と 3 番目のセグメントの最後から開始しようとしました)。新しいセグメントは同じ長さ (秒とポイント単位) ですが、完全なランスルーからの同等のセグメントとはサイズが異なります (数キロバイト以内) - 開始セグメント (2 番目、3 番目、またはその他のいずれか) も以前の同等のセグメントよりも 2 パケット少ない。

av_seek_frameそのフレームまで手動でループを実行したかのように、完全に一致すると思いましたがav_read_frame、そうではないようです。

私が望むもの:

  • ファイル内の特定の (近似ではない) ポイントにファイル内を「早送り」する方法。
  • その時点から先に書き込み、出力をフルランが提供する出力と完全に同一にする (同じサイズ、同じ長さ、まったく同じバイト)。
4

2 に答える 2

1

通常、シークは正確ではなく、ファイル インデックスにリストされているポイント (通常はビデオ キーフレーム) に移動するだけです。AVSEEK_FLAG_BACKWARDフラグを使用してシークし、指定したポイントの前をシークしてから、そこから読み取り + 破棄することができます。

あるいは、フレーム精度のシークを備えた libav 関数の高レベルのラッパーを提供すると思われるFFMS2を確認することもできます。

于 2013-06-20T05:27:14.883 に答える
0

私は次のことを行うことでそれを機能させることができました:

  • 実際のキーフレームが見つかる少し前 (1000 dts) までシークします。
  • av_read_frameキーフレームに到達するまでループで呼び出します。
  • セグメントごとにヘッダーとトレーラーを書き込む( avformat_write_headerav_write_trailer)

最終結果は、セグメントが開始されようとしていることがわかっている特定のタイムスタンプで開始し、それらのセグメントを作成できることです (そして、任意のセグメントで停止しますが、それは些細なことです)。結果のセグメントは、完全なランスルーで作成されたものと同じです。

于 2013-06-20T12:40:08.793 に答える