Bagaimana cara mengkodekan urutan gambar jpg ke video dalam ffmpeg?

21

Saya memiliki sejumlah besar jpg yang ingin saya konversi menjadi video lossless (atau, paling tidak, sangat dekat dengan lossless selama waktu penyandian tidak jauh lebih tinggi daripada yang lain).

Secara naif, saya akan berpikir bahwa harus ada beberapa codec yang dapat menyimpan setiap frame jpg individu apa adanya (tanpa recompression), dan mungkin mencapai beberapa kompresi yang bagus dengan mengganti beberapa frame hanya dengan informasi pada delta dari frame sebelumnya. Dalam kasus saya ada banyak urutan frame yang identik satu sama lain, atau yang memiliki perbedaan kecil di antara mereka.

Apakah ada beberapa pengaturan codec dan cocok untuk ffmpeg yang dapat mencapai ini?

GJ.
sumber
Terkait: avp.stackexchange.com/questions/4642/…
Friend Of George
Juga Terkait: avp.stackexchange.com/questions/7300/…
Friend Of George
1
sequence-of-jpegs telah menjadi codec untuk waktu yang lama. Kamera digital yang tidak menggunakan h.264 selalu merekam MJPEG, dan kartu video capture digunakan untuk menggunakannya, saya pikir.
Peter Cordes

Jawaban:

24

Hanya mux gambar

Anda dapat dengan mudah mux gambar JPG untuk membuat video:

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

Perhatikan bahwa jika Anda menghilangkan -frameratemaka default -framerate 25akan diterapkan pada input.

Optimalisasi lossless

Anda dapat menggunakan jpegtranuntuk melakukan optimasi lossless pada setiap frame yang dapat memberikan penghematan ukuran file yang signifikan:

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

Sekarang mux dengan ffmpegseperti yang ditunjukkan di atas.

Memeriksa bahwa itu sebenarnya lossless

The framehash muxer dapat digunakan untuk membandingkan hash unik setiap frame untuk memastikan bahwa hasilnya adalah benar-benar lossless:

$ 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
...

Dalam contoh di atas setiap frame terkait untuk input dan output berbagi hash yang sama memastikan bahwa frame identik dan bahwa output adalah lossless.

Lihat juga

llogan
sumber
dapatkah Anda memperjelas apa framemd5yang seharusnya dicapai oleh kedua perintah itu di luar daftar hash? bagaimana saya mendapatkan kompresi tambahan ketika frame identik diidentifikasi?
GJ.
1
Hash dimasukkan hanya untuk menunjukkan kepada Anda bahwa frame adalah sama dengan gambar individu, sehingga mencapai kebutuhan Anda untuk menyimpan "setiap frame jpg individu apa adanya (tanpa kompresi ulang)".
llogan
Diposting jawaban saya sendiri dengan ide yang belum teruji untuk menjatuhkan frame duplikat, untuk berakhir dengan MJPEG.mkv VFR. VFR adalah satu-satunya cara yang dapat saya pikirkan untuk mengambil keuntungan dari redundansi temporal dengan MJPEG. : P
Peter Cordes
SSIM mungkin cara yang lebih cepat untuk membandingkan kesetiaan.
Gyan
11

Ini akan menghasilkan video H.264 lossless di mana frame akan menggunakan informasi dari frame lain

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

Penjelasan opsi:

  • -f image2 - Memberitahu ffmpeg untuk memilih grup gambar
  • -r 30 - Memberitahu ffmpeg untuk mengkodekan pada 30 frame (atau gambar) per detik (ubah ini ke framerate yang Anda inginkan)
  • -i %09d.jpg- Memberitahu ffmpeg untuk menggunakan gambar 000000000.jpg hingga 999999999.jpg sebagai input. Ubah 9in %09d.jpgmenjadi berapa banyak nol yang dimiliki nama-nama urutan gambar Anda. Jika nama file Anda, misalnya, img0001.jpg, maka ini akan dinyatakan sebagai img% 04d.jpg
  • -vcodec libx264 - Memberitahu ffmpeg untuk menampilkan ke file yang kompatibel dengan H.264
  • -profile:v high444 - memberitahu libx264 untuk menggunakan profil Prediksi Lossless 4: 4: 4 Tinggi, memungkinkan penyandian lossless
  • -refs 16 - memberitahu libx264 untuk menyimpan 16 gambar dalam buffer, sehingga dapat dirujuk oleh gambar lain dalam video
  • -crf 0 - memberitahu libx264 untuk melakukan penyandian lossless
  • -preset ultrafast - Memberitahu libx264 untuk memprioritaskan kecepatan encoding di atas ukuran file output
  • a.mp4- Memberitahu ffmpeg untuk menyimpan output dalam file MP4 bernama a.mp4. Ubah ini ke nama file dan format yang ingin Anda gunakan
Adam Chance
sumber
3
Beberapa catatan: -f image2berlebihan di sini. The file gambar demuxer harus menggunakan -frameratebukan -r. libx264 akan secara otomatis memilih yang sesuai -profileuntuk lossless, dan -presetakan menangani -refs.
Logo
-refs 5di MOST, kecuali Anda tahu konten Anda memiliki gambar yang identik dipisahkan oleh beberapa yang lain, yang mungkin menyebabkan x264 kehilangan referensi sebelum sampai ke duplikat. Lebih tinggi daripada ultrafastmembuat sedikit berbeda dalam mode lossless, selain CABAC ~ 10% keuntungan atas CAVLC (untuk biaya cpu tinggi pada bitrate yang diperlukan untuk lossless). Serius, pada beberapa live-action 720x480p60 (output deinterlace), superfastadalah 28GB, sloweradalah 27GB. Jika waktu enkode tidak masalah, tetapi waktu decode tidak, pastikan Anda menghindari CABAC. Bahkan mungkin -tune fastdecode. Hitungan ref moderat seharusnya tidak sakit.
Peter Cordes
Dan jika Anda memiliki CPU yang akan dibakar, Anda bahkan dapat mencoba -preset placebobeberapa persen ekstra persen.
DrYak
Selain itu untuk kelengkapan h265 juga memiliki mode lossless sendiri. -vcodec libx265 -x265-params lossless=1adalah opsi yang setara. (Tapi dalam pengalaman saya (= merekam presentasi slideshow Powerpoint), itu belum tentu lebih baik, dan jauh lebih lambat daripada h264) Tetap selaras untuk AV1 / IETF tahun depan dari AOMedia, NETVC1 / IETF, Daala Xiph / apa pun yang akan diubah namanya saat itu ... Mode lossless
DrYak
5

Anda dapat membuat avianimasi sebagai serangkaian pnggambar (tidak png ada kerugian sehingga jpeg => pngkonversi tidak boleh menurunkan gambar Anda):

jika gambar Anda bernama img_0001.jpg

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

di mana "25" adalah frame rate yang Anda inginkan dalam video yang dihasilkan. -start_numbertidak diperlukan jika 1, tetapi berguna jika nomor video pertama Anda bukan 1.

Jika Anda ingin menyandikan mjpegdengan baris perintah kualitas tertinggi adalah:

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

Dan keindahannya adalah Anda dapat mengonversi video kembali ke seri gambar:

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

dll ...

Olivier S
sumber
Ini tidak benar-benar memenuhi kebutuhan para penanya. Dia mencari cara agar frame dapat diperbarui tanpa kehilangan hanya ketika gambar berubah. Ini berarti gambar yang sama dapat digunakan lebih dari sekali. Juga jpeg secara alami tidak lossless karena saya percaya ini menggunakan kompresi jpeg bahkan pada kualitas maksimal.
AJ Henderson
Sebenarnya saya kira dia bersedia melakukan beberapa kompresi, meskipun saya tidak yakin bagaimana ini akan dilakukan pada urutan panjang dari frame yang sama. Saya masih berpikir format presentasi frame rate variabel adalah apa yang diperlukan meskipun saya tidak yakin apakah ffmpeg mendukung.
AJ Henderson
CorePNG juga dapat membuat bingkai P. Biasanya jpeg bukan kompresi lossless, dan saya ragu mjpeg dapat membuat frame P. Saya setuju saya tidak menjawab pertanyaan seperti yang ditanyakan, tetapi saya memberikan solusi untuk memiliki video lossless dengan ffmpeg.
Olivier S
4

Untuk memperluas jawaban LordNeckbeard, ya, cukup masukkan data JPEG ke dalam aliran video MJPEG. Itu akan menjadi representasi terkecil dari urutan yang tepat dari gambar output, meskipun MJPEG adalah codec yang sangat tidak efisien menurut standar saat ini. (tidak ada redundansi temporal, dan bahkan tidak ada prediksi intra.

Anda dapat membuat video MJPEG variabel-framerate untuk mengambil keuntungan dari gambar duplikat di input Anda.

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

Hrm, ini tidak akan berfungsi, karena mpdecimate tidak akan bekerja pada data terkompresi, dan kami tidak dapat membiarkan ffmpeg mendekode dan kemudian kembali jpeg data gambar tanpa kehilangan dan biaya CPU.

Mungkin jika Anda mengganti duplikat file sumber jpg dengan file kosong dengan nomor urut itu, atau sesuatu?

Karena pertanyaan ini bahkan tidak baru, saya tidak akan meluangkan waktu untuk mencari tahu bagaimana melakukannya kecuali seseorang menjawab untuk bertanya bagaimana. Tapi karena MJPEG dapat masuk ke wadah mkv, saya yakin mungkin untuk memiliki file yang tidak menduplikasi data jpeg untuk frame berulang, tetapi sebaliknya tidak memiliki frame output untuk memecahkan kode sampai urutan duplikat adalah lebih.

Oh, ini ide:

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

Kemudian hapus (atau minggir) semua jpeg untuk frame yang ingin dijatuhkan mpdecimate (mungkin ia memiliki beberapa opsi logging? Atau -vf showinfo, dan parsing itu, dan pindahkan atau hardlink hanya frame yang muncul di outputnya, meninggalkan JPEG yang dijatuhkan?). mux yang ke MJPEG.mkv, lalu lakukan sesuatu dengan mkvmerge untuk mengganti frame timestamp di dalamnya dengan timestamps dari mpdecimate.timestamps.

Jika Anda xcoding, bukan hanya muxing data jpeg ke MJPEG, ini akan jauh lebih mudah, karena Anda hanya akan menggunakan perintah pertama saya dengan mpdecimate dan codec selain copy, dan itu hanya akan berfungsi (tm).

Saya belum mencoba semua ini, karena ini adalah pertanyaan lama. Juga alasan saya belum mengisi celah bagaimana sebenarnya menyaring direktori jpeg Anda berdasarkan pada output mpdecimate, atau bagaimana cara benar-benar menggunakan aliran cap waktu.

Peter Cordes
sumber