Ffmpegを使用してCentOSWebサーバーでユーザーがアップロードしたビデオを処理しています。各ビデオを標準のサイズとフォーマットに変換してから、各ビデオから30秒のサンプルクリップを抽出する必要があります。抽出コマンドで「-vcodeccopy」フラグを使用して、2回目のエンコードを回避したいと思います。
このコマンドは私の最初の変換で機能します:
ffmpeg -i uploaded.mov -f mp4 -vcodec libx264 -vpre medium -acodec libfaac -r 15 -b 360k -ab 48k -ar 22050 -s 480x320 formatted.mp4
そして、これ時々は抽出のために機能します:
ffmpeg -i formatted.mp4 -vcodec copy -acodec copy -ss 0 -t 30 formatted_sample.mp4
ただし、一部のビデオで抽出コマンドを実行すると、抽出されたサンプルクリップは数秒の空白のビデオで始まります。オーディオはすぐに開始されますが、ビデオは3〜6秒間開始されません。
問題を実証するために、2つのビデオクリップをアップロードし、それらに対して上記のコマンドを実行しました。 Final Cut Expressで最初のクリップを作成し、Webサーバーにアップロードする前にHandbrakeでエンコードしました。
1a) アップロードされたクリップ
1b) 最初のコマンドで変換
比較すると、この2番目のクリップはAppleのWebサイトからのものであり、問題は示されていません。
2a) アップロードされたクリップ
2b) 最初のコマンドで変換
2c) 2番目のコマンドで抽出、問題なし
2つのソースクリップの違いを誰かが理解できますか?もしそうなら、抽出コマンドが実行されたときにクリップがビデオの欠落を回避するように設定されるように、変換コマンドでできることはありますか?
ちなみに、最初はyumからインストールされたffmpeg 0.6.1で問題が発生しましたが、最新のgitバージョンにアップグレードしても問題は解決しません。
キーフレームに関するMattの提案と、ffmpegメーリングリストに投稿されたタイムリーなヒントを組み合わせることで、解決策にたどり着きましたが、それが最善の解決策かどうかはわかりません。
まず、抽出コマンドの-ssオプションと-tオプションを移動して、-iオプションの前に表示されるようにする必要がありました。これにより、抽出は次に早いキーフレームから開始されます。たとえば、-ss 25 -t 15を使用してクリップの0:25から0:40まで抽出するとしますが、10秒ごとにキーフレームがあります。以前は、5秒の空白のビデオから始まる15秒のサンプルを取得していました。これで、0:20から0:40まで実行される20秒のサンプルを取得しますが、空白のビデオはありません。言い換えれば、私は空白のビデオを避けますが、クリップ選択の精度を失います。
これに対処するには、変換コマンドに-gオプションを追加して、キーフレームを再フォーマットする必要がありました。 -g15と-r15を使用して、毎秒キーフレームを作成しました。これにより、最も近い秒単位のサンプル位置を選択できるため、-ss 25 -t 15を使用すると、要求した15秒のクリップが得られます。追加のキーフレームによってクリップ全体が大きくなると思いますが、テストでは約2%しか大きくないため、プロジェクトにとっては良いトレードオフになります。
そこで、上記の2つのコマンドを次のように変更しました。
ffmpeg -i uploaded.mov -f mp4 -vcodec libx264 -vpre medium -acodec libfaac -r 15 -g 15 -b 360k -ab 48k -ar 22050 -s 480x320 formatted.mp4
ffmpeg -ss 0 -t 30 -i formatted.mp4 -vcodec copy -acodec copy formatted_sample.mp4
そして、すべてが順調に見えます。誰かがより効率的な解決策を持っている場合は、投稿してください。選択した回答を変更します。