web-dev-qa-db-ja.com

FFmpegでビデオクロスフェードを行う効率的な方法は何ですか?

FFmpegでは、2つのビデオコンテンツ間でクロスフェードを実行することは実際には非常に複雑です。オーディオのような「クロスフェード」フィルターはありません。

それを行うための効率的な方法は何ですか?

11

TL; DRバージョン:

この例では、両方のビデオクリップが同じ解像度、フレームレートなどであると想定して、ビデオのみを実行します。これにより、fadeoutclipとfadeinclipの間に1秒のフェードが作成されます。フェードアウトクリップの長さが10秒であると想定します。これはわかりやすくするためにフォーマットされていることに注意してください。実際には1行のコードです。

ffmpeg -i fadeoutclip.mp4 -i fadeinclip.mp4 -an \
-filter_complex "\
    [0:v]trim=start=0:end=9,setpts=PTS-STARTPTS[firstclip]; \
    [1:v]trim=start=1,setpts=PTS-STARTPTS[secondclip]; \
    [0:v]trim=start=9:end=10,setpts=PTS-STARTPTS[fadeoutsrc]; \
    [1:v]trim=start=0:end=1,setpts=PTS-STARTPTS[fadeinsrc]; \
    [fadeinsrc]format=pix_fmts=yuva420p, \
                fade=t=in:st=0:d=1:alpha=1[fadein]; \
    [fadeoutsrc]format=pix_fmts=yuva420p, \
                fade=t=out:st=0:d=1:alpha=1[fadeout]; \
    [fadein]fifo[fadeinfifo]; \
    [fadeout]fifo[fadeoutfifo]; \
    [fadeoutfifo][fadeinfifo]overlay[crossfade]; \
    [firstclip][crossfade][secondclip]concat=n=3[output] \
    " \
-map "[output]" <add in encoding part here>

フルバージョン:

これがすべてについての説明です:

入力仕様...明らか

ffmpeg -i fadeoutclip.mp4 -i fadeinclip.mp4 -an

filter_complexの作成:フィルターコンプレックスをすでに理解していると仮定:

-filter_complex

最初に、コンテンツとクロスフェードセクションを使用して、2つのストリームをそれぞれ2つの部分に分割します トリムフィルター。フェードアウトはコンテンツとフェードセクションに分割され、フェードインはフェードセクションとコンテンツに分割されます。合計4つのセクション。

厳密に言えば、クロスフェードセクションを分割するためにhaveを使用しないことに注意してください。2つのビデオクリップのフェードアウト時間とフェードイン時間を指定するだけで済みます。ただし、これを行うことにより、次のことが可能になります。

  • GUIビデオエディタで通常使用される方法に従ってください
  • overlayフィルターの使用法の苛立たしい複雑さを避けてください
  • ソリューションが可能な限り一般的であることを確認します(つまり、再利用可能なコード)
  • 必要に応じてクロスフェードセクションを前処理および後処理できるようにします(ここでは実行されません)

これらの4つのセクションのそれぞれは、次を指定します:開始時間(秒)、終了時間(秒)、および不思議な setpts=PTS-STARTPTS filter 、これは本質的にそれぞれを作成しますビデオサブクリップは0秒から始まります。これは、それらを再合成するときに不可欠です。

s=0指定子は冗長であり、s=0指定子のsetptsフィルターも冗長であることに注意してください。ただし、両方とも冗長に指定されているため、フィルターの複合体を壊すことなく、開始時刻を0から変更できます。また、2番目のコンテンツクリップは最後まで実行されるため、e=部分(end =)は指定されていません。

    [0:v]trim=s=0:e=9,setpts=PTS-STARTPTS[firstclip];
    [1:v]trim=s=1,setpts=PTS-STARTPTS[secondclip];
    [0:v]trim=s=9:e=10,setpts=PTS-STARTPTS[fadeoutsrc];
    [1:v]trim=s=0:e=1,setpts=PTS-STARTPTS[fadeinsrc];

次に、フェードインとフェードアウトを指定します。まず、両方のフェードセクションにアルファ(透明度)チャネルを追加します yuva420pのピクセル形式を指定します 。実際には、アルファチャネルを提供する任意の形式を使用できます。

次に、このフィルターサブコンプレックスでは、フェードアウトするものとフェードインするものを指定します。alpha=1は、ビデオ自体が暗くならず、透明度だけが「フェード」することを意味します。 stは開始を意味し、dは期間を意味します。

    [fadeinsrc]format=pix_fmts=yuva420p,      
                fade=t=in:st=0:d=1:alpha=1[fadein];
    [fadeoutsrc]format=pix_fmts=yuva420p,
                fade=t=out:st=0:d=1:alpha=1[fadeout];

これは何ですか?:fifoフィルター フィルターコンプレックスで使用可能なバッファースペースがあることを確認します。驚くべきことに、これはデフォルトではありません。これを行わないと、上のステージの出力が下のオーバーレイフィルターをオーバーランすると、クロスフェードが失敗する可能性があります。ええ、あなたが今何を考えているか知っています。 これは確かにFFMPEGのバグです

    [fadein]fifo[fadeinfifo];
    [fadeout]fifo[fadeoutfifo];

ここで、2つのフェードセクションをオーバーレイします:2つのクロスフェードセクションが同じサイズであることを確認することで、心配する必要はありません- オーバーレイフィルターが取るかなり厄介なオプション (したがって、ここではそれらを無視します):

    [fadeoutfifo][fadeinfifo]overlay[crossfade];

最後に、3つのセグメントを並べます 連結フィルターを使用

    [firstclip][crossfade][secondclip]concat=n=3[output]

そして今、あなたのビデオソースとして出力パッドをマップします。

忘れないでくださいピクセルフォーマットを通常使用するもの(通常はyuv420p)に設定します。これは、クロスフェードセクションで出力チャネルでyuv420に設定されるためです。 !! (指定しなかったので、オーバーレイ引数を使用できます) もちろん、yuv420が必要な場合は、問題ありません:-)

-map "[output]" <add your normal encoding part here>

その後、後でオーディオを再結合できます(このQ&Aの範囲外)

17