Bir jpg resim dizisini ffmpeg'deki bir videoya kayıpsız olarak nasıl kodlarsınız?


21

Kayıpsız bir videoya dönüştürmek istediğim büyük bir jpgs setine sahibim (ya da en azından, kodlama süresi diğerlerinden daha yüksek olmadığı sürece kayıpsız bir şekilde çok yakın).

Doğal olarak, her bir jpg karesini olduğu gibi (yeniden sıkıştırma olmadan) depolayabilen ve belki de karelerin bazılarını önceki karedeki deltadaki bilgilerle değiştirerek güzel bir sıkıştırma elde edebilecek bazı kodlayıcıların olması gerektiğini düşünürdüm. Benim durumumda, birbirleriyle aynı olan veya aralarında küçük bir fark olan birçok çerçeve dizisi vardır.

Bunu başarabilecek ffmpeg için bazı kodek ve uygun ayarlar var mı?




1
jpegs dizisi uzun zamandır bir kodek oldu. Sanırım h.264'ü kullanmayan dijital kameralar her zaman MJPEG'i kaydediyor ve video kayıt kartlarını kullanıyorlardı.
Peter Cordes

Yanıtlar:


24

Sadece görüntüleri karıştır

Bir video yapmak için JPG resimlerini kolayca kopyalayabilirsiniz:

ffmpeg -framerate 30 -i input%03d.jpg -codec copy output.mkv

İhmal ederseniz -framerate, varsayılan değerin -framerate 25girişe uygulanacağını unutmayın.

Kayıpsız optimizasyon

jpegtranHer karede kayıpsız optimizasyon yapmak için kullanabilirsiniz ; bu , önemli dosya boyutu tasarrufu sağlayabilir:

mkdir outputdir
for f in *.jpg; do jpegtran -optimize -copy none -perfect -v "$f" > "outputdir/$f"; done

Şimdi ffmpegyukarıda gösterildiği gibi yavaşlayın .

Gerçekten kayıpsız olduğunu kontrol

Framehash muxer'i sonuç gerçekten kayıpsız olmasını sağlamak için her çerçevenin benzersiz karma karşılaştırmak için kullanılabilir:

$ ffmpeg -i input%03d.jpg -f framehash -
stream_index, packet_dts, packet_pts, packet_duration, packet_size, hash
0,          0,          0,        1,   460800, 29bcc2db3726c7dfec1826c5740f603f
0,          1,          1,        1,   460800, b5fdc23d93cbd043dc2b9290dc8378f0
0,          2,          2,        1,   460800, ee0709942f24b458fd2380d134dcb59d
...

$ ffmpeg -i output.mkv -map 0:v -f framehash -
stream_index, packet_dts, packet_pts, packet_duration, packet_size, hash
0,          0,          0,        1,   460800, 29bcc2db3726c7dfec1826c5740f603f
0,          1,          1,        1,   460800, b5fdc23d93cbd043dc2b9290dc8378f0
0,          2,          2,        1,   460800, ee0709942f24b458fd2380d134dcb59d
...

Yukarıdaki örneklerde, girdi ve çıktı için her bir ilişkili çerçeve aynı kareyi paylaşır ve karelerin aynı olmasını ve çıktının kayıpsız olmasını sağlar.

Ayrıca bakınız


Lütfen iki framemd5komutun sadece karmaları listelemenin ötesinde ne başarması gerektiğini açıklayabilir misiniz ? Aynı kareler tanımlandığında nasıl ek sıkıştırma elde edeceğim?
GJ.

1
Karma kareler yalnızca karelerin tek tek görüntülerle aynı olduğunu göstermek için dahil edilmiştir, bu nedenle "her bir jpg karesini olduğu gibi (yeniden sıkıştırma olmadan) kaydetme gereksiniminizi gerçekleştirin."
llogan

Bir VFR MJPEG.mkv ile sona ermek için, yinelenen kareleri bırakmak için denenmemiş bir fikir ile kendi bir cevap gönderdi. MJPEG ile zamansal artıklıktan yararlanmayı düşünebilmemin tek yolu VFR. : P
Peter Cordes

SSIM, doğruluğu karşılaştırmanın daha hızlı bir yolu olabilir.
Gyan,

11

Bu, çerçevelerin diğer çerçevelerden gelen bilgileri kullanacağı kayıpsız bir H.264 videosu çıkarır

ffmpeg -f image2 -r 30 -i %09d.jpg -vcodec libx264 -profile:v high444 -refs 16 -crf 0 -preset ultrafast a.mp4

Seçeneklerin açıklaması:

  • -f image2 - ffmpeg'e bir grup görüntü seçmesini söyler
  • -r 30 - ffmpeg'e saniyede 30 karede (veya görüntüde) kodlamasını söyler (bunu istediğiniz kare hızına değiştirin)
  • -i %09d.jpg- ffmpeg'e 000000000.jpg ile 999999999.jpg arasındaki resimleri girdi olarak kullanmasını söyler. Değişim 9içinde %09d.jpgresim dizisinin isimleri kaç sıfıra. Örneğin, dosya adlarınız örneğin img0001.jpg ise, bu img% 04d.jpg olarak ifade edilir.
  • -vcodec libx264 - ffmpeg'e H.264 uyumlu bir dosyaya çıktı vermesini söyler
  • -profile:v high444 - libx264'e High 4: 4: 4 Predictive Lossless profilini kullanıp kayıpsız kodlamaya izin vermesini söyler
  • -refs 16 - libx264'e arabellekte 16 görüntü saklanmasını söyler, böylece videodaki diğer görüntüler tarafından referans alınabilir
  • -crf 0 - libx264'e kayıpsız kodlama yapmalarını söyler
  • -preset ultrafast - libx264'e çıktı dosyası boyutuna göre kodlama hızına öncelik vermesini söyler
  • a.mp4- ffmpeg'e çıktıyı a.mp4 adlı bir MP4 dosyasına kaydetmesini söyler. Bunu kullanmak istediğiniz dosya adı ve formatıyla değiştirin.

3
Birkaç not: -f image2burada gereksiz. Görüntü dosyası demuxer kullanmalıdır -framerateyerine -r. libx264 otomatik olarak -profilekayıpsız için uygun olanı seçecek ve -presetbaşa çıkacaktır -refs.
llogan

-refs 5MOST'ta, içeriğinizin birbirleriyle ayrılan özdeş görüntüleri olmadığını bilmediğiniz sürece, x264'ün kopyalanmadan önce referansı kaybetmesine neden olabilir. Daha yüksek ultrafast(kayıpsız için gerekli bit hızlarında yüksek işlemci maliyet) CAVLC'den üzerinde Cabac en ~% 10 kazanç dışında kayıpsız modunda biraz farklı marka. Ciddi, bazı canlı-aksiyon 720x480p60 (deinterlace çıkışı), superfast28TR oldu, slower27 GB'lik oldu. Kodlama zamanı önemli değil ancak kod çözme zamanı önemliyse, CABAC'den kaçındığınızdan emin olun. Belki bile -tune fastdecode. Ilımlı ref sayısı zarar görmemelidir.
Peter Cordes

Ve yazmak için bir işlemciniz varsa -preset placebo, yüzde fazladan birkaç kesir bile deneyebilirsiniz .
DrYak

Ayrıca, h265'in eksiksiz olması için kendi kayıpsız modu da vardır. -vcodec libx265 -x265-params lossless=1eşdeğer seçenektir. (Ama benim deneyimimde (= Powerpoint slayt gösterisi sunumlarının kaydedilmesi), mutlaka daha iyi değil ve h264'ten çok daha yavaş olması gerekir) Gelecek yılın AOMedia's AV1 / IETF'in NETVC1 / Xipi'nin Daala / için ne olursa olsun yeniden ayarlanması ... 'kayıpsız modu
DrYak

5

Bir oluşturabilir aviserisi olarak animasyon pnggörüntüleri ( png olan kayıpsız böylece jpeg => pngdönüşüm resimlerinizi bozmamalıdır):

Resimleriniz bir adlandırılmışsa img_0001.jpg

ffmpeg -r 25 -start_number 1 -f image2 -i "img_%04d.jpg" -vcodec png video.avi

buradaki "25", sonuçtaki videoda istediğiniz kare hızıdır. -start_number1 ise gerekli değildir, ancak ilk video numaranız 1 değilse faydalıdır.

En mjpegyüksek kalitede komut satırı ile kodlamak istiyorsanız :

ffmpeg -r 25 -start_number 1 -f image2 -i "img_%04d.jpg" -vcodec mjpeg -qscale 1 video.avi

Ve olayın güzelliği, videoyu bir seriye dönüşte resimlere dönüştürebilmeniz:

ffmpeg -i video.avi "img_series_%04d.png"
ffmpeg -i video.avi "img_series_%04d.jpg"

vb...


Bu, gerçekten talep edenlerin ihtiyaçlarını karşılamıyor. Yalnızca görüntü değiştiğinde çerçevenin kayıtsız bir şekilde güncellenebileceği bir yol arıyor. Bu, aynı görüntünün bir kereden fazla kullanılabileceği anlamına gelir. Ayrıca jpeg, maksimum kalitede bile jpeg sıkıştırması kullandığına inandığım için kayıpsız değildir.
AJ Henderson

Aslında sanırım biraz sıkıştırmaya istekliydi, ancak aynı karenin uzun dizileri üzerinde nasıl yapacağını bilmiyorum. Değişken kare hızı sunum formatının hala gerekli olduğunu düşünüyorum, ancak ffmpeg'in destekleyip desteklemediğinden emin değilim.
AJ Henderson

CorePNG ayrıca P kareleri oluşturabilir. Genellikle jpeg kayıpsız bir sıkıştırma değildir ve mjpeg'nin P kareleri oluşturabileceğinden şüpheliyim. Soruyu istendiği gibi cevaplamamaya katılıyorum, ancak ffmpeg ile kayıpsız bir videoya sahip olmak için bir çözüm veriyorum.
Olivier S

4

LordNeckbeard'in cevabını genişletmek için, evet, JPEG verisini MJPEG video akışına kopyalamanız yeterli. MJPEG bugünün standartlarına göre çok verimsiz bir kodlayıcı olsa da, çıkış görüntülerinin tam dizisinin en küçük temsili olacaktır. (zamansal artıklık yok ve hatta herhangi bir tahminde bulunma.

Girişinizdeki kopya görüntülerden yararlanmak için değişken kare hızda MJPEG video yapabilirsiniz.

ffmpeg -framerate 30 -i input%03d.jpg -vf mpdecimate -codec copy output.mkv  # doesn't work.

Hrm, bu işe yaramayacak, çünkü mpdecimate sıkıştırılmış veriler üzerinde çalışmayacak ve ffmpeg'in kod çözmesine izin vermeyiz ve sonra görüntü verilerini kayıp ve CPU maliyeti olmadan yeniden jpeglememize izin veremeyiz.

Belki de yinelenen jpg kaynak dosyalarını bu sıra numarasına sahip boş dosyalarla değiştirirseniz, ya da başka bir şey?

Bu soru henüz yeni olmadığı için, birileri nasıl yapılacağını sormadığı sürece, nasıl yapılacağını bulmak için zaman almayacağım. Ancak, MJPEG bir mkv kabına girebildiğinden, tekrarlanan çerçeveler için jpeg verilerini çoğaltan bir dosyaya sahip olamayacağından eminim, fakat bunun yerine yinelenen dizilerin kodunu çözene kadar bir çıktı çerçevesine sahip değiliz. üzerinde.

Ah işte bir fikir:

ffmpeg -framerate blah -input blah -vf mpdecimate -f mkvtimestamp_v2 mpdecimate.timestamps

Sonra mpdecimate öğesinin bırakmak istediği karelerin tüm jpeg'lerini kaldırın (veya bir kenara bırakın) (muhtemelen bazı günlüğe kaydetme seçeneklerine sahip olabilir mi? Or -vf showinfo ve bunu ayrıştırın ve yalnızca çıktısında görünen kareleri geride bırakın, geride bırakın) bırakılan JPEG'ler?). Bir MJPEG.mkv'ye mux, daha sonra mkvmerge ile bir şey yapın ve bunun içindeki çerçeve zaman damgalarını değiştirmek için zaman damgalarını kullanın mpdecimate.timestamps.

Eğer sadece jpeg verilerini MJPEG'e bağlamak yerine xcoding yapıyor olsaydınız, bu benim için daha kolay olurdu, çünkü ilk komutumu mpdecimate ve herhangi bir codec bileşeni ile kullanacaksınız ve copyJust Work (tm).

Bunların hiçbirini denemedim, çünkü bu eski bir soruydu. Ayrıca, jpegs dizininizi mpdecimate çıktısına dayalı olarak filtrelemenin ya da gerçekte zaman damgası akışını nasıl kullanacağınıza ilişkin boşlukları doldurmamamın nedeni de budur.

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.