ffmpeg をウォールタイムではなくビデオ時間でセグメント化する

ffmpeg をウォールタイムではなくビデオ時間でセグメント化する

私はビデオをディスクに記録するシステムを持っていますが、時々システムにエラーが発生します。実際のカメラを使わずに (高価でスペアがない) ラボで記録システムを再現し、エラーの原因となる使用パターンを再現しようとしています。

ffmpeg を使いこなすのに苦労しています。

背景:

次のコマンドを実行すると、接続されたカメラから提供される rtsp:// URL から 1 つのスレッドでビデオが連続的にキャプチャされます。

ffmpeg -i rtsp://192.168.0.10/h264 -c copy -map 0 -f segment -segment_time 900 -segment_format mp4 -segment_atclocktime 1 -strftime 1 /tmp/capture-%s.mp4

これは機能し、期待どおりに 15 分間のビデオ ファイルが生成されます。

問題:

ラボにはカメラも rtsp:// ストリームもありません。その代わりに、実際のシステムからキャプチャ MP4 の 1 つをコピーし、それを ffmpeg への入力として使用しています。次のようになります。

ffmpeg -stream_loop -1 -i capture-1469547000.mp4 -c copy -map 0 -f segment **-{NEED PARAM}** -segment_format mp4 -strftime 1 /tmp/captest-%s.mp4

パラメータ-stream_loop -1は期待どおりの動作を行います。つまり、入力ファイル (期間は 15 分) から読み取り、無限の出力ストリームを生成します。これは、rtsp:// ストリームからの読み取りの妥当な近似値です。

私にはわからないのは、このラボ システムで実際のシステムと同じようにビデオを 15 分間のチャンクに分割するには、どのようなパラメータを使用すればよいかということです。私が期待しているのは、入力ファイルとほぼ同じサイズの出力ファイルのシーケンスです。

試み #1

を使用する-segment_time 900と、a) 15 分のウォール クロック値を使用するか、b) 無視するかのいずれかになります。既存の MP4 からのコピーは rtsp:// ストリームからのコピーよりもはるかに高速であるため、結果として得られるキャプチャ ファイルは元のファイルの多数のコピーになります。

試み #2

私はこのコマンドを使用しました

ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 capture-1469547000.mp4

入力ファイルに 13494 フレームがあることを確認します。

使用は-segment_frames 13494無視されるようで、出力はまったくセグメント化されません。

試み #3

ffmpeg のドキュメントをたくさん読みましたが、必要なものが見つからないか、存在しないようです。

使用しても、-ss *position* -t *duration*出力の連続記録とセグメント化は行われません。

ヘルプのリクエスト

セグメンテーションを a) 機能させ、b) ビデオの長さを 15 分にするには、どのようなパラメータを使用すればよいですか?

起こりうる合併症

例の MP4 のタイムスタンプ (DTS?) は、このエラーが継続的に生成されるという点で「良好」ではありません。

[セグメント @ 0x2abc7c0] 出力ストリーム 0:0 に非単調 DTS があります。以前: 80990160、現在: -74730276972。80990161 に変更します。これにより、出力ファイルに誤ったタイムスタンプが記録される可能性があります。  
DTS 191648787、次:-830336344130 st:0 無効なドロップ  
PTS 191648787、次:-830336344130 無効なドロップ st:0

ただし、結果として得られるビデオ ファイルが実際に再生されたり、そのままの状態である必要はないため、再作成する必要があるセグメンテーションに影響しない限り、これを無視します。

さらに詳しい情報

ffmpeg バージョン:

\# /usr/share/local/bin/ffmpeg -バージョン  
ffmpeg バージョン N-79587-g9f9c833 Copyright (c) 2000-2016 FFmpeg 開発者  
gcc 4.8 (Ubuntu/Linaro 4.8.2-16ubuntu4) でビルド  
設定: --prefix=/home/t/dev/j/third-party/ffmpeg/../build --cross-prefix=/usr/bin/arm-linux-gnueabihf- --cpu=armv7-a --disable-shared --enable-static --enable-gpl --enable-pthreads --enable-nonfree --enable-libx264 --enable-filters --extra-libs=-static --extra-cflags=--static --enable-cross-compile --target-os=linux --disable-inline-asm --arch=armv7 --disable-debug --disable-altivec --disable-sse --disable-armv6 --disable-armv6t2 --disable-mmx --disable-neon --disable-amd3dnow --disable-thumb --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/../build/lib --extra-cflags=-I/home/t/dev/j/third-party/ffmpeg/../build/include --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavcodec --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavdevice --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavfilter --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavformat --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavresample --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavutil --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libswscale --extra-ldflags=-lx264 --extra-ldflags=-lm --extra-ldflags=-ldl --extra-cflags='-fpic -mthumb'  
libavutil 55. 22.101 / 55. 22.101  
libavcodec 57. 38.100 / 57. 38.100  
libavフォーマット 57. 34.103 / 57. 34.103  
libavデバイス 57. 0.101 / 57. 0.101  
libavfilter 6. 44.100 / 6. 44.100  
libswscale 4. 1.100 / 4. 1.100  
libswresample 2. 0.101 / 2. 0.101  
libpostproc 54. 0.100 / 54. 0.100

答え1

segment_time動作するはずです。これは、ウォールクロックではなく、セグメントの継続時間を参照します。

キーフレームの配置が邪魔になっている可能性がありますので、

ffmpeg -fflags +genpts -i capture-1469547000.mp4 -c copy -map 0 -f segment -segment_time 900 -segment_format mp4 -break_non_keyframes 1 -strftime 1 /tmp/capture-%s.mp4

現在、stream_loop オプションの使用に関連するタイムスタンプ生成のバグがあるため、このオプションを削除しました。これがここでも干渉している可能性があります。

非常に長いストリームを処理する必要がある場合は、concat デマルチプレクサーを使用します。

テキストファイルを作成する

file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'

そして、

ffmpeg -f concat -i list.txt -c copy ...

答え2

実用的な解決策があります。

根本的な原因

私が保存したサンプル キャプチャ ファイルは、私が望む目的 (無限の入力ストリーム) には「適切」ではないことが判明しましたが、それ以外は適切なビデオ ファイルです (シークはできませんが、問題なく再生されます)。この問題はタイムスタンプに関連しているようで、セグメント マルチプレクサーの 1 つ以上のバグも関係している可能性があります。

ソリューション

私は走った

ffmpeg -i capture-1469547000.mp4 -c copy captemp.mp4

captemp.mp4代わりに、stream_loop または concat muxer のいずれかを使用して適切なストリームを取得します。

capture-1469547000.mp4 と captemp.mp4 の違いがよくわかりません。AtomicParsley によると、captemp.mp4 は 'elst' アトムが 12 バイト短いようです。

元の設定をもう一度見直して追加しsegment_listてみると、セグメントは正しく生成されていましたが、非常に高速でした。セグメントは、新しいセグメント ファイルを作成するのではなく、既存のセグメント ファイルに追加されていただけです。これは、一部は... のせいです。

strftime の潜在的なバグ

私はフォーマットstrftimeを使用し%sていました。strftime は、ビデオ セグメント内の時間ではなく、ホスト マシンのクロック時間を使用していました。これは、「動作」している場合でも当てはまります。代わりに、セグメント muxer のフォーマットを使用するように切り替えました%d

これはおそらくバグであり、動作しないケースでセグメントが互いに追加されていた理由です。

フラグを使用すると、処理速度が遅くなり、この問題を回避できると確信しています-reが、実際には処理速度を速めたいと考えています。そのため、これを試していません。

関連情報