FFmpeg ile bir video crossfade yapmanın etkili bir yolu nedir?


11

İki video içeriği arasında çapraz açıklama yapmak FFmpeg'de oldukça karmaşıktır. Ses için olduğu gibi bir “crossfade” filtresi yoktur.

Bunu yapmanın etkili bir yolu nedir?


Güzel kendi kendine cevaplanan soru!
JakeGould

Bu cevabın çok daha fazla oy alması gerekiyor ... Mark, ses için de solma eklediyseniz seni sonsuza kadar seveceğim ...
Merc

Nasıl yapılacağını anladığımda ekleyeceğim. Bence ses crossfade çok basit, bunun için basit bir filtre olduğuna inanıyoruz.
Mark Gerolimatos

[0:a][1:a] acrossfade=d=1 [audio]Filtreye ve sonra -map "[audio]" komuta ekledim ve işe yaradı. İsterseniz, bir test yapın ve cevabı güncelleyin!
Merc

Yanıtlar:


17

TL; DR versiyonu:

Bu örnek, her iki video klibin de aynı çözünürlük, kare hızı vb. Olduğunu varsayarak yalnızca video gerçekleştirir. Bu, fadeoutclip ve fadeinclip arasında 1 saniyelik bir solma oluşturur. Fadeoutclip'in 10 saniye uzunluğunu varsayalım. Bunun netlik için biçimlendirildiğine dikkat edin: gerçekten bir kod satırı.

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>

Tam versiyon:

İşte bunun ne hakkında olduğuna dair bir açıklama:

Giriş Özellikleri ... açık

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

Bir Oluşturma filter_complex: Zaten filtre kompleksleri anlama varsayarak:

-filter_complex

İlk olarak, trim filtresini kullanarak iki akışı iki parçaya ayırırız : içerik ve çapraz solma bölümü. Solma içeriği ve solma bölümüne ayrılırken solma girişi solma bölümüne ve içeriğine kesilir. Toplam dört bölüm.

Açık konuşmak gerekirse, biz olmadığını Not sahip sadece iki video klipleri zamanlarda dışarı ve solmaya solmaya belirtmek OLABİLİR: dışarı çapraz solmaya bölümleri kırmak için. Ancak, bunu yaparak:

Bu dört bölümün her biri şunları belirtir: başlangıç ​​zamanı (saniye), bitiş zamanı (saniye) ve her video alt klipsini 0 saniyede başlatan gizemli setpts=PTS-STARTPTSfiltre . Onları yeniden birleştirirken bu çok önemli olacaktır.

Belirticilerin gereksiz olduğunu s=0ve bunların setptsfiltresinin de gereksiz olduğunu unutmayın s=0. Bununla birlikte, her ikisi de filtre kompleksini bozmadan başlangıç ​​zamanının 0'dan değişmesine izin vermek için yedek olarak belirtilir. Ayrıca, ikinci içerik klibi sonuna kadar çalışır, bu nedenle e=parça (end =) belirtilmez.

    [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];

Ardından, solmaya ve solmaya belirtiyoruz: Önce her iki solmaya bölüme bir piksel biçimi belirterek biryuva420p alfa (saydamlık) kanalı ekliyoruz . Alfa kanalı sağlayan herhangi bir formatı kullanabilirsiniz.

Bu filtrede Sonra karartmak için birini belirtin ve tek solmaya subcomplex.alpha=1 Videonun kendisi, sadece şeffaflık miktarı olacak "solma" karartmak olmaz demektir. stbaşlangıç, dsüre anlamına gelir.

    [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];

Bu nedir ? : fifoFiltre , filtre kompleksinde kullanılabilir arabellek alanı olmasını sağlar. Şaşırtıcı, bu varsayılan DEĞİLDİR. Bunu yapmazsanız, yukarıdaki sahnenin çıktısı aşağıdaki kaplama filtresini aşarsa crossfade başarısız olabilir. Evet, şu an ne düşündüğünü biliyorum. Gerçekten bir FFMPEG hatasıdır .

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

Şimdi, iki solma bölümün üzerine bindirme: İki çapraz-ifade bölümünün aynı boyutta olduğundan emin olarak , kaplama filtresinin aldığı oldukça kötü seçenekler hakkında endişelenmemiz gerekmiyor(ve bu yüzden burada yok sayıyoruz):

    [fadeoutfifo][fadeinfifo]overlay[crossfade];

Son olarak, concat filtreyi kullanarak üç segmentimizi sıralıyoruz .

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

Ve şimdi, çıkış pedini video kaynağınız olarak eşleyin.

Piksel formatını NORMAL OLARAK KULLANMADIĞINIZA (tipik olarak yuv420p) ayarlamayı UNUTMAYIN çünkü crossfade bölümü bunu yuv420çıkış kanalında ayarlayacaktır ! (belirtmediğimiz gibi, bindirme argümanlarını kullanabilirsiniz) Tabii ki, eğer İSTİYORSANIZ yuv420, o zaman sorun yok :-)

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

Daha sonra sesi daha sonra yeniden birleştirebilirsiniz (bu soru ve cevap kapsamının dışında)


1
En son ffmpeg, olması gerekiyor trim=start=0:end=9, (yerine trim=st=0:e=9,..
Merc

Ama cidden, bu şimdiye kadar gördüğüm FFMPEG'in en iyi yanıtı ve şimdiye kadarki en net ffmpeg açıklaması olmalı.
Merc

Adamım, bu kafama gidecek :-) Sahne için teşekkürler !!!!
Mark Gerolimatos

Telaşa gerek yok. Lütfen cevabı özellikle = trim = start = 0 ile güncelleyin, çünkü şu anda en son ffmpeg ile çalışmaz
Merc

En son ffmpeg sürümü bana şu hatayı veriyor: Filter setpts has an unconnected outputkomut dosyası için. Zaten başlangıç ​​ve bitiş için trim parametrelerini değiştirdim.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.