時間セグメントの切り取り

時間セグメントの切り取り

私は切断と接合について読んだことがあります連結しかし、私にとってはこれでは十分ではありません。

マークされたビデオ部分を切り取り、再エンコードせずに 1 つのビデオ ファイルに結合したいと思います。 切り取りと結合 (メモリ内) を 1 回で行うことはありますか?

カットまたは結合するビデオ部分の数に理論上の制限はありません。オーディオは同期している必要があります。

ビデオ: H.264+AAC

編集:

回答から、ビデオの再エンコードがまだ必要であることがわかりました。

ビデオ ファイルの途中からビデオ クリップを切り取る作業は、複数のステップで実行される場合があることを明確にしておきたいと思います。ビデオを 1 回で処理すると、I/O アクティビティが節約されてパフォーマンスが向上すると考えていました。ただし、それ自体が目的ではありません。

答え1

あなたの質問は、私が正しく理解していれば、4 つの主要な部分から構成されます。

  • 映画から時間セグメントを切り取る方法
  • 複数のセグメントを結合する方法
  • 映画をトランスコードせずに上記の操作を行う方法(品質を損なわない)
  • 上記をスピードの面で効率的に行う方法

時間セグメントの切り取り

-ssオプションを使用してセグメントの開始点にスキップし、 を使用してセグメントの継続時間を設定するか、-tを使用して終了点を設定することで、セグメントをカットできます。-to

# skip 30 seconds, then copy the next 60 seconds
ffmpeg -ss 30 -t 60 full-movie.mp4 segment.mp4

ffmpegのドキュメントのセクションを参照してください5.4 メインオプション-ssおよびオプションを入力ファイルの前に置くか、出力ファイルの前に置くかの違いについて-t。これを試してみると、この違いが自分のケースに関係していることがわかるかもしれません。

重要な注意: 上記の例では、ビデオがトランスコードされます。トランスコードせずにこれを行う可能性については、以下で説明します。

複数のセグメントを結合する

ムービーの結合には主に3つの方法があり、そのうち2つはここで最もよく説明されています。ffmpeg wiki 記事、そして3つ目は連結デマルチプレクサすべてのセグメントが A/V エンコーディング仕様とコンテナ形式に関して同一である場合、おそらくconcat:プロトコルが最も簡単な方法であることがわかります。

# merge the segments
ffmpeg -i "concat:seg1.mp4|seg2.mp4|seg3.mp4" final.mp4

重要なのは、この結合は、カットと同様に、再び映画をトランスコードすることであり、ここではトランスコードのトランスコードがあり、ビデオの品質が低下する可能性があるので、本当にこのトランスコーディングをできるだけ避けたいです!

トランスコードなしでのカットと結合

前のセクションの例でトランスコードが必要なのは、各ファイルと結果の各セグメントがスタンドアロン ムービーであり、ムービーの再生時間やその他のメタデータなど、フル ムービーを開いたときに期待されるすべての情報を提供できるようにパックされているためです。ただし、これらをスタンドアロン ムービーとして再生するのではなく、これらのセグメントをより大きなビデオ ストリームの一部にしたいのです。したがって、ffmpeg にボックス化されたムービーを提供する代わりに、入力ファイルをリアルタイム ストリーミング コンテナーに再パッケージ化 (再多重化) し、この時点では必要のないヘッダー情報は忘れた方がよいでしょう。H.264 の場合、ストリーミング多重化形式は MPEG-TS と呼ばれ、トランスコードせずにストリームを再多重化する方法は次のとおりです。

# re-muxing the whole movie (see a better option in next example)
ffmpeg -i full-movie.mp4 -c:v copy -c:a copy -bsf:v h264_mp4toannexb full-movies-as-ts.ts

さて、すでにやっているのなら、この機会を利用して必要な部分だけを切り取ってもいいでしょう。

# skip 30 seconds and re-mux a 60 seconds segment
ffmpeg -ss 30 -t 60 -i full-movie.mp4 -c:v copy -c:a copy -bsf:v h264_mp4toannexb segment.ts

TS セグメントを結合するときに、mp4 コンテナーに再多重化することもできます。

# merge the segments and re-mux them as mp4
ffmpeg -i "concat:seg1.ts|seg2.ts|seg3.ts" -c:v copy -c:a copy -movflags empty_moov -flags global_header -bsf:v dump_extra edited-final.mp4

これで、映画をトランスコードすることなく、元の品質を維持したまま、すべてが完了しました。ただし、いつものように、注意点があります...

警告: カットはキーフレーム境界でのみ実行できます。説明: H.264 は圧縮フレームをパケットに編成します。各パケットは最初のフレームの完全かつ圧縮された画像で始まり、その後に後続のフレームの差分が続くため、各パケットに必要なストレージが減少します。私たちの目的にとって、各パケットはその期間のすべてのフレームの密封された zip のようなものです。つまり、すべてか、まったくないかのどちらかです。パケットの一部だけが必要な場合は、それを解凍して再度 zip で圧縮する、つまりトランスコードする必要があります。したがって、上記の方法は、ムービーをカットする各位置にキーフレームがある場合にのみ該当します。たとえば、5 秒ごとにキーフレームがある場合は、5 秒ごとにのみカットできます。

では、問題は、特に映画のどこにキーフレームがあるか分からない場合、カットポイントの制限を受け入れることができるかどうかです。そして、それが私が上で読んだ理由です。5.4 メインオプション-s入力の前か出力の前に指定することについて-t。入力の前に指定すると、ffmpeg は要求を実行するために近くのキーフレームを見つけます。これは、カットを実行したい場所の「ほぼ」近くになります。カットの正確さを気にしないのであれば、それで結構です。

しかし、カットをその正確な位置にする必要がある場合は、他に選択肢はなく、探しているフレームを正確に特定するために映画をデコードする必要があります。まあ、少なくともいくつかの良いニュース: トランスコードと再トランスコードの代わりに、1 回のトランスコードで実行できます。これにより、状況がいくらか改善されます。

# skip PRECISELY 30 seconds and transcode a 60 seconds TS segment
ffmpeg -i full-movie.mp4 -ss 30 -t 60 -bsf:v h264_mp4toannexb segment.ts

結果のセグメントは TS 形式になるため、セグメントを結合するときに別のトランスコードは必要ありません。

スピード

の中にマージに関するffmpeg wiki記事パイプを介してプロセス全体を実行する方法について説明されており、これにより中間ファイルが不要になり、プロセス全体が高速化されます。しないでください。それはあなたを連れて行きますより長いですすべてをメモリ内で実行すると時間がかかるのは、実行時間が長くなるからではなく、全体を完了する方法を考えている間に中間結果がないため、プロセス全体を何度も実行することになるからです。パイプ理論は良いものですが、あなたの場合は、各ステップを理解して完璧にすることから始める必要があります。すべてが機能して適切な結果を得るには、さらに微調整とチューニングが必要であることがわかります。プロセス全体を習得し、自動化された大量編集用のスクリプトを作成したい場合は、パイピングの概念を再検討できます。

上記がお役に立てば幸いです。

関連情報