FFmpeg ile belirli bir zaman damgasından önce en yakın ana karenin zaman damgasını nasıl alabilirim?


18

Hızlı ve doğru bir FFmpeg arama komutu istiyorum. Bulduğum bu .

Çözüm -sshem girdi (hızlı arama) hem de çıktı (doğru arama) için başvurmamızdır. Ancak: Girdi arayışı doğru değilse, arayış konumunun doğru olduğundan nasıl emin olabiliriz?


Örneğin: 00:03:00 aramak istersek, komut şuna benzer:

ffmpeg -ss 00:02:30 -i <INPUT> ... -ss 00:00:30 <OUTPUT>

İlk -ssbaşka bir yerde etmeye çalışacak değil 00:02:30, demek 00:02:31. Ve aramaya ikinci uygulandıktan sonra, nihai sonuç olacağını 00:03:01- değil ne istediğimizi. Bu doğru mu?

İlk nereye -ssgidiyor? En yakın ana kareyi arıyor mu 00:02:30?

Eğer öyleyse, işte benim düşüncem - eğer yanılıyorsam beni düzeltin: ilk arayıştan sonra, sonucun zaman damgasını alırız (bu örnekte:) 00:02:31, o zaman bu durumda ikinci arayışı uygun zamanla uygularız 00:00:29.

Soru: İlk arama sonucunun zaman damgasını nasıl alırız?

Yanıtlar:


18

Başlığınızın sorusunu tam anlamıyla cevaplamak için: ile I-karelerinin bir listesini alabilirsiniz

ffprobe -select_streams v -show_frames <INPUT> 

Ekleyerek bunu gerekli çıktıyla sınırlandırabilirsiniz -show_entries frame=pkt_pts_time,pict_type.

Hangi karenin en yakın (belirli bir zaman damgasına) en yakın olduğunu görmek için, önce ana karelerin tüm zaman damgalarını bulmanız gerekir, örneğin awk.

İlk olarak, aramak istediğiniz zamanı tanımlayın, örneğin, 150: e eşit olan 2: 30m.

ffprobe -select_streams v -show_frames -show_entries frame=pkt_pts_time,pict_type -v quiet in.mp4 | 
awk -F= ' 
  /pict_type=/ { if (index($2, "I")) { i=1; } else { i=0; } } 
  /pkt_pts_time/ { if (i && ($2 >= 150)) print $2; }  
' | head -n 1

Örneğin, bu geri dönecektir 150.400000.


Kullanırken bu Not -ssönce -i, ffmpeg kare bulacaktır önceki o noktaya aramaya ulaşıncaya kadar noktasını aramaya, daha sonra atama negatif aşağıdaki tüm karelere değerleri PTS. Bir oynatıcının kodu çözülmeli ancak negatif PTS'ye sahip kareler gösterilmemelidir ve video doğru bir şekilde başlamalıdır.

Bazı oyuncular buna tam olarak saygı göstermez ve siyah video veya çöp görüntüler. Bu durumda, yukarıdaki komut dosyası, arama noktasından sonra ana karenin PTS'sini bulmak ve bunu ana kareden aramaya başlamak için kullanabilir. Ancak bu doğru olmayacaktır.

Arama yaparken süper hassas olmak istiyorsanız ve birçok oynatıcıyla uyumluluğu koruyorsanız, videoyu muhtemelen herhangi bir noktada kesebileceğiniz ve daha sonra yeniden kodlayabileceğiniz kayıpsız, sadece içi biçime dönüştürmelisiniz. Ama bu hızlı olmayacak.


1
teşekkürler, ben bir video editörü yapmıyorum, ama aralığın 0,5 saniyeden daha az olması gereken hassas video arama yapmak istiyorum.
jackode

1
Muhtemelen PTS ile uğraşabilirsiniz ffprobe. Aksi takdirde, herhangi bir ara format, örneğin görsel olarak kayıpsız ve sadece çerçeve içi olan ProRes 422, DNxHD yapacaktır. Ya da HuffYUV gibi bir şey kullanıyorsunuz. Ama sonra elbette "hızlı" yönü tekrar kaybedersiniz.
slhck

komut için hangi ffprobe sürümünü kullandınız, çünkü benim dediUnrecognized option 'select_streams'
jackode

2
Yakınız, select_streamsseçenek Ekim 2012'de eklendi . :) Onsuz yapabilirdiniz ama aralarında ses kareleri için de bilgiler elde edersiniz.
slhck

2
Bu ffmpeg satırını, awk tarafından atılan birçok şey yerine yalnızca gerekli 2 alanın çıktısını alması için ekleyebilirsiniz: -show_entries frame = pkt_pts_time, pict_type
Jannes

7

Bu sorunun birkaç yaşında olduğunu anlıyorum, ancak ffprobe'un en son sürümü çerçeveleri atlama yeteneğine sahip . -skip_frame nokeyRapor bilgilerine yalnızca ana karelerde (I-kareler) geçebilirsiniz . Bu size çok zaman kazandırabilir! 2GB 1080p MP4 dosyasında, atlama çerçeveleri olmadan 4 dakika sürerdi. Atlama parametresini eklemek sadece 20 saniye sürer.

Komut:

ffprobe -select_streams v -skip_frame nokey -show_frames -show_entries çerçeve = pkt_pts_time, pict_type D: \ test.mp4

Sonuçlar:

[FRAME]
pkt_pts_time=0.000000
pict_type=I
[/FRAME]
[FRAME]
pkt_pts_time=3.753750
pict_type=I
[/FRAME]
[FRAME]
pkt_pts_time=7.507500
pict_type=I
[/FRAME]
[FRAME]
pkt_pts_time=11.261250
pict_type=I
[/FRAME]
[FRAME]
pkt_pts_time=15.015000
pict_type=I
[/FRAME]

Dolayısıyla sonuçlar sadece ana karelere ilişkin bilgiler içerecektir.


1

Bina slhck cevabı burada ÖNCE meydana yakın kareyi dönecektir bir bash fonksiyonu bulunuyor Nsaniye.

Bu aynı zamanda -read_intervalsffprobe anahtar karenizi yalnızca saniyelerden 25 saniye önce aramaya başlamak için de kullanılır N. Bu hile ve zaman damgası bulunduğunda awk çıkışına sahip olmak işleri büyük ölçüde hızlandırır.

function ffnearest() {
  STIME=$2; export STIME;
  ffprobe -read_intervals $[$STIME-25]% -select_streams v -show_frames -show_entries frame=pkt_pts_time,pict_type -v quiet "$1" |
  awk -F= '
    /pict_type=/ { if (index($2, "I")) { i=1; } else { i=0; } }
    /pkt_pts_time/ { if (i && ($2 <= ENVIRON["STIME"])) print $2; }
    /pkt_pts_time/ { if (i && ($2 > ENVIRON["STIME"])) exit 0; }
  ' | tail -n 1
}

örnek kullanım:

➜ ffnearest input.mkv 30
23.941000

Bu video dosyalarını yeniden kodlamadan kırpmak için kullanın. Yeniden kodlamadan yeni ana kareler ekleyemeyeceğiniz ffnearestiçin, kesmek istemeden önce ana kareyi aramak için kullanıyorum . İşte bir örnek:

ffmpeg  -i input.mkv -ss 00:00:$(echo "$(ffnearest input.mkv 30) - 0.5" | bc)  -c copy -y output.mkv;

Bu örnek için, -ssilk 60 saniyeden daha uzun bir süre arıyorsanız , parametrede geçenlerin biçimini değiştirmeniz gerekebileceğini unutmayın .

(can sıkıcı bir şekilde, ffmpeg'e ana karenin zaman damgasına tam olarak arama yapmasını söylemek, ffmpeg'in çıktıdaki anahtar kareyi dışlamasını sağlar, ancak anahtar karenin gerçek zaman damgasından 0,5 saniye çıkarılması hile yapar. bash için bcondalıklarla ifadeleri değerlendirmek için kullanmanız gerekir , ancak zsh -ss 00:00:$[$(ffnearest input.mkv 28)-0.5]çalışmalarında.)


Bu, çerçevelendikten sonraki kare süresini verecektir.
Ehsan Chavoshi

0

I kareleri hakkında bilgi almak istiyorsanız şunu kullanabilirsiniz:

ffprobe -i input.mp4 -v quiet -select_streams v -show_entries frame=pkt_pts_time,pict_type|grep -B 1 'pict_type=I'
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.