Come codificare senza perdite una sequenza di immagini jpg in un video in ffmpeg?


21

Ho una vasta gamma di jpg che voglio convertire in un video senza perdita di dati (o, per lo meno, molto vicino a senza perdita di dati, a condizione che il tempo di codifica non sia molto più elevato di quello altrimenti).

Ingenuamente, penso che dovrebbe esserci un codec in grado di memorizzare i singoli frame jpg così com'è (senza ricompressione) e forse ottenere una buona compressione sostituendo alcuni dei frame con solo le informazioni sul delta dal frame precedente. Nel mio caso ci sono molte sequenze di fotogrammi identiche tra loro o che hanno una piccola differenza tra loro.

Esistono alcuni codec e impostazioni adatte per ffmpeg che possono raggiungere questo obiettivo?




1
sequenza di jpeg è stata un codec per molto tempo. Penso che le fotocamere digitali che non usano h.264 registrino invariabilmente MJPEG e le schede di acquisizione video utilizzate per usarlo.
Peter Cordes,

Risposte:


24

Mux solo le immagini

Puoi semplicemente combinare le immagini JPG per creare un video:

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

Si noti che se si omette, verrà applicato -framerateun valore predefinito di -framerate 25input.

Ottimizzazione senza perdite

È possibile utilizzare jpegtranper eseguire l'ottimizzazione senza perdita di dati su ciascun fotogramma che può fornire un notevole risparmio di dimensioni del file:

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

Ora mux con ffmpegcome mostrato sopra.

Verifica che sia effettivamente senza perdite

Il muxer framehash può essere utilizzato per confrontare l'hash univoco di ciascun frame per garantire che il risultato sia davvero senza perdite:

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

Negli esempi precedenti ogni frame associato per l'input e l'output condividono lo stesso hash garantendo che i frame siano identici e che l'output sia senza perdita.

Vedi anche


potresti chiarire cosa framemd5dovrebbero ottenere i due comandi oltre al semplice elenco degli hash? come potrei ottenere una compressione aggiuntiva quando vengono identificati frame identici?
GJ.

1
Gli hash sono stati inclusi solo per mostrarti che i frame sono gli stessi delle singole immagini, quindi raggiungi il tuo requisito di memorizzare "ogni singolo frame jpg così com'è (senza ricompressione)".
llogan,

Ho pubblicato una mia risposta con un'idea non testata per eliminare i frame duplicati, per finire con un VFR MJPEG.mkv. VFR è l'unico modo a cui riesco a pensare di sfruttare la ridondanza temporale con MJPEG. : P
Peter Cordes,

SSIM potrebbe essere un modo più rapido per confrontare la fedeltà.
Gyan,

11

Ciò produrrà un video H.264 senza perdita di dati in cui i frame utilizzeranno le informazioni di altri frame

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

Spiegazione delle opzioni:

  • -f image2 - dice a ffmpeg di selezionare un gruppo di immagini
  • -r 30 - dice a ffmpeg di codificare a 30 fotogrammi (o immagini) al secondo (cambiarlo nel framerate desiderato)
  • -i %09d.jpg- dice a ffmpeg di usare le immagini da 000000000.jpg a 999999999.jpg come input. Cambia 9in %09d.jpgin quanti zero ha i nomi della sequenza di immagini. Se i nomi dei tuoi file sono, ad esempio, img0001.jpg, allora questo sarebbe espresso come img% 04d.jpg
  • -vcodec libx264 - dice a ffmpeg di eseguire l'output in un file conforme a H.264
  • -profile:v high444 - dice a libx264 di usare il profilo High Lictless predittivo 4: 4: 4, consentendo la codifica lossless
  • -refs 16 - dice a libx264 di avere 16 immagini memorizzate in un buffer, in modo che possano essere referenziate da altre immagini nel video
  • -crf 0 - dice a libx264 di eseguire una codifica senza perdita di dati
  • -preset ultrafast - dice a libx264 di dare priorità alla velocità di codifica rispetto alle dimensioni del file di output
  • a.mp4- dice a ffmpeg di salvare l'output in un file MP4 chiamato a.mp4. Modificarlo con il nome e il formato del file che si desidera utilizzare

3
Alcune note: -f image2qui è superfluo. Il demuxer del file immagine dovrebbe usare al -framerateposto di -r. libx264 sceglierà automaticamente l'appropriato -profileper lossless e -presetsi occuperà di -refs.
Llogan,

-refs 5per lo più, a meno che tu non sappia che il tuo contenuto ha immagini identiche separate da molte altre, ciò potrebbe far perdere a x264 il riferimento prima che arrivi al duplicato. Più alto di quello che ultrafastrende leggermente diverso in modalità lossless, oltre al guadagno del CABAC del ~ 10% su CAVLC (per un elevato costo della CPU ai bitrate richiesti per la perdita). Scherzi a parte, su alcuni 720x480p60 (uscita deinterlacciata) live-action, superfastera 28GB, slowerera 27GB. Se il tempo di codifica non ha importanza, ma il tempo di decodifica lo è, assicurati di evitare CABAC. Forse anche -tune fastdecode. Il conteggio di ref moderato non dovrebbe far male.
Peter Cordes,

E se hai una CPU da masterizzare, puoi anche provare -preset placeboper qualche frazione extra di percentuale.
DrYak,

Anche per completezza h265 ha anche la sua modalità lossless. -vcodec libx265 -x265-params lossless=1è l'opzione equivalente. (Ma nella mia esperienza (= registrazione delle presentazioni di PowerPoint), non è necessariamente migliore, ed è molto più lento di h264) Resta sintonizzato per AOMedia AV1 / IETF dell'anno prossimo NETVC1 / Daala di Xiph / qualunque cosa verrà rinominata da allora ... modalità senza perdita di dati
DrYak,

5

Puoi creare aviun'animazione come una serie di pngimmagini ( png è senza perdita, quindi la jpeg => pngconversione non dovrebbe degradare le tue immagini):

se le tue immagini hanno un nome img_0001.jpg

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

dove "25" è la frequenza dei fotogrammi desiderata nel video risultante. -start_numbernon è necessario se è 1, ma è utile se il primo numero di video non è 1.

Se si desidera codificare mjpegcon la riga di comando della massima qualità è:

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

E il bello è che puoi convertire il video in una serie a immagini:

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

eccetera...


Questo non soddisfa veramente le esigenze di chi chiede. Sta cercando un modo in cui la cornice possa essere aggiornata senza perdono solo quando l'immagine cambia. Ciò significa che la stessa immagine può essere utilizzata più di una volta. Anche jpeg per natura non è senza perdita in quanto credo che usi la compressione jpeg anche alla massima qualità.
AJ Henderson

In realtà immagino che fosse disposto ad avere un po 'di compressione, anche se non sono sicuro di come andrà su lunghe sequenze dello stesso frame. Penso ancora che sia necessario un formato di presentazione con frame rate variabile, anche se non sono sicuro che ffmpeg ne supporti uno.
AJ Henderson

CorePNG è anche in grado di creare fotogrammi P. Di solito jpeg non è una compressione senza perdita di dati, e dubito che mjpeg possa creare fotogrammi P. Accetto di non rispondere alla domanda quando viene posta, ma do una soluzione per avere un video senza perdita di dati con ffmpeg.
Olivier S,

4

Per espandere la risposta di LordNeckbeard, sì, basta unire i dati JPEG in un flusso video MJPEG. Questa sarà la più piccola rappresentazione dell'esatta sequenza di immagini in uscita, anche se MJPEG è un codec terribilmente inefficiente per gli standard odierni. (nessuna ridondanza temporale e nemmeno alcuna previsione intra.

Puoi realizzare un video MJPEG a framerate variabili per sfruttare le immagini duplicate nel tuo input.

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

Hrm, questo non funzionerà, dal momento che mpdecimate non funzionerà su dati compressi, e non possiamo permettere a ffmpeg di decodificare e quindi ripetere il jpeg dei dati dell'immagine senza perdita e costi della CPU.

Forse se hai sostituito i file sorgente jpg duplicati con file vuoti con quel numero di sequenza, o qualcosa del genere?

Dal momento che questa domanda non è nemmeno recente, non mi prenderò il tempo per capire come farlo a meno che qualcuno non risponda per chiedere come. Ma poiché MJPEG può andare in un contenitore mkv, sono sicuro che è possibile avere un file che non duplica i dati jpeg per frame ripetuti, ma invece non ha un frame di output da decodificare fino a quando la sequenza di duplicati è al di sopra di.

Oh, ecco un'idea:

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

Quindi rimuovi (o sposta da parte) tutti i jpeg per i frame che mpdecimate vuole eliminare (probabilmente ha alcune opzioni di registrazione? O -vf showinfo e analizzalo, e sposta o hardlink solo i frame che appaiono nel suo output, lasciandosi indietro i JPEG rilasciati?). combinalo con un MJPEG.mkv, quindi fai qualcosa con mkvmerge per sostituire i timestamp del frame in quello con i timestamp da mpdecimate.timestamps.

Se stavi xcodificando, invece di unire semplicemente i dati jpeg su MJPEG, questo sarebbe MOLTO più semplice, dato che useresti il ​​mio primo comando con mpdecimate e qualsiasi codec diverso da copy, e funzionerebbe (tm).

Non ho provato nulla di tutto ciò, poiché questa era una vecchia domanda. Anche il motivo per cui non ho colmato le lacune su come filtrare effettivamente la tua directory di jpeg in base all'output di mpdecimate o su come usare effettivamente il flusso di data / ora.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.