Comment encoder sans perte une séquence d'images jpg en vidéo dans ffmpeg?


21

J'ai un grand nombre de jpgs que je veux convertir en vidéo sans perte (ou, à tout le moins, très proche de sans perte tant que le temps d'encodage n'est pas beaucoup plus élevé qu'autrement).

Naïvement, je pense qu'il devrait y avoir un codec qui peut stocker chaque trame jpg individuelle telle quelle (sans recompression), et peut-être obtenir une bonne compression en remplaçant certaines des trames par juste les informations sur le delta de la trame précédente. Dans mon cas, il existe de nombreuses séquences d'images qui sont identiques les unes aux autres, ou qui ont une petite différence entre elles.

Y a-t-il un codec et des paramètres appropriés pour ffmpeg qui peuvent y parvenir?




1
sequence-of-jpegs est un codec depuis longtemps. Les appareils photo numériques qui n'utilisent pas h.264 enregistrent invariablement le MJPEG, et les cartes de capture vidéo utilisées pour l'utiliser, je pense.
Peter Cordes

Réponses:


24

Mux juste les images

Vous pouvez simplement multiplexer les images JPG pour faire une vidéo:

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

Notez que si vous omettez, -framerateune valeur par défaut de -framerate 25sera appliquée à l'entrée.

Optimisation sans perte

Vous pouvez utiliser jpegtranpour effectuer une optimisation sans perte sur chaque trame, ce qui peut permettre de réduire considérablement la taille du fichier:

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

Maintenant, mux avec ffmpegcomme indiqué ci-dessus.

Vérifier qu'il est réellement sans perte

Le multiplexeur framehash peut être utilisé pour comparer le hachage unique de chaque trame afin de s'assurer que le résultat est vraiment sans perte:

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

Dans les exemples ci-dessus, chaque trame associée pour l'entrée et la sortie partage le même hachage, garantissant que les trames sont identiques et que la sortie est sans perte.

Regarde aussi


pourriez-vous clarifier ce que les deux framemd5commandes sont censées accomplir au-delà de la simple énumération des hachages? comment pourrais-je obtenir une compression supplémentaire lorsque des images identiques sont ainsi identifiées?
GJ.

1
Les hachages ont été inclus uniquement pour vous montrer que les cadres sont les mêmes que les images individuelles.
llogan

Posté une réponse de ma part avec une idée non testée pour supprimer les trames en double, pour se retrouver avec un VFR MJPEG.mkv. VFR est le seul moyen auquel je peux penser pour tirer parti de la redondance temporelle avec MJPEG. : P
Peter Cordes

SSIM peut être un moyen plus rapide de comparer la fidélité.
Gyan

11

Cela produira une vidéo H.264 sans perte où les images utiliseront les informations d'autres images

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

Explication des options:

  • -f image2 - indique à ffmpeg de sélectionner un groupe d'images
  • -r 30 - indique à ffmpeg d'encoder à 30 images (ou images) par seconde (changez-la en votre cadence d'images souhaitée)
  • -i %09d.jpg- indique à ffmpeg d'utiliser les images 000000000.jpg à 999999999.jpg comme entrée. Modifiez le 9dans %09d.jpgde combien de zéros les noms de votre séquence d'images a. Si vos noms de fichiers sont, par exemple, img0001.jpg, alors cela serait exprimé en img% 04d.jpg
  • -vcodec libx264 - indique à ffmpeg de sortir vers un fichier compatible H.264
  • -profile:v high444 - indique à libx264 d'utiliser le profil High 4: 4: 4 Predictive Lossless, permettant un encodage sans perte
  • -refs 16 - indique à libx264 d'avoir 16 images stockées dans un tampon, afin qu'elles puissent être référencées par d'autres images dans la vidéo
  • -crf 0 - indique à libx264 d'effectuer un encodage sans perte
  • -preset ultrafast - indique à libx264 de prioriser la vitesse d'encodage sur la taille du fichier de sortie
  • a.mp4- indique à ffmpeg d'enregistrer la sortie dans un fichier MP4 appelé a.mp4. Remplacez-le par le nom de fichier et le format que vous souhaitez utiliser

3
Quelques notes: -f image2c'est superflu ici. Le démultiplexeur de fichiers image doit utiliser à la -framerateplace de -r. libx264 choisira automatiquement le approprié -profilepour lossless, et le -presettraitera -refs.
llogan

-refs 5à MOST, sauf si vous savez que votre contenu contient des images identiques séparées par plusieurs autres, cela pourrait entraîner la perte de la référence de x264 avant qu'il n'atteigne le doublon. Plus élevé que ce qui ultrafastfait peu de différence en mode sans perte, autre que le gain de 10% de CABAC par rapport à CAVLC (pour un coût élevé en CPU aux débits requis pour sans perte). Sérieusement, sur certains 720x480p60 en direct (sortie désentrelacé) superfast, slowerétait de 28 Go , était de 27 Go. Si le temps de codage n'a pas d'importance, mais le temps de décodage le fait, assurez-vous d'éviter CABAC. Peut-être même -tune fastdecode. Le nombre de références modéré ne devrait pas faire de mal.
Peter Cordes

Et si vous avez un processeur à graver, vous pouvez même essayer -preset placeboquelques fractions de pourcentage supplémentaires.
DrYak

Pour être complet, le h265 possède également son propre mode sans perte. -vcodec libx265 -x265-params lossless=1est l'option équivalente. (Mais selon mon expérience (= enregistrement de présentations de diaporamas Powerpoint), ce n'est pas nécessairement mieux, et c'est beaucoup plus lent que h264) Restez à l'écoute pour AV1 / IETF NETVC1 / Xiph's Daala de l'AOMedia de l'année prochaine / quoi que ce soit qui sera renommé d'ici là ... mode sans perte
DrYak

5

Vous pouvez créer une avianimation comme une série d' pngimages ( png est sans perte de sorte que la jpeg => pngconversion ne doit pas dégrader vos images):

si vos images sont nommées img_0001.jpg

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

où "25" est la fréquence d'images que vous souhaitez dans la vidéo résultante. -start_numbern'est pas nécessaire s'il est 1, mais il est utile si votre premier numéro de vidéo n'est pas 1.

Si vous souhaitez encoder mjpegavec une ligne de commande de la plus haute qualité, c'est:

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

Et la beauté de la chose est que vous pouvez reconvertir la vidéo en une série d'images:

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

etc...


Cela ne répond pas vraiment aux besoins des demandeurs. Il cherche un moyen de mettre à jour le cadre sans perte uniquement lorsque l'image change. Cela signifie que la même image peut être utilisée plusieurs fois. De plus, le format jpeg par nature n'est pas sans perte car je pense qu'il utilise la compression jpeg même à la qualité maximale.
AJ Henderson

En fait, je suppose qu'il était prêt à avoir une compression, bien que je ne sois pas sûr de la façon dont cela va se passer sur de longues séquences de la même image. Je pense toujours qu'un format de présentation à fréquence d'images variable est nécessaire, mais je ne suis pas sûr que ffmpeg en prenne en charge.
AJ Henderson

CorePNG est également capable de créer des trames P. En général, jpeg n'est pas une compression sans perte, et je doute que mjpeg puisse créer des trames P. Je suis d'accord, je ne réponds pas à la question telle qu'elle est posée, mais je donne une solution pour avoir une vidéo sans perte avec ffmpeg.
Olivier S

4

Pour développer la réponse de LordNeckbeard, oui, il suffit de multiplexer les données JPEG dans un flux vidéo MJPEG. Ce sera la plus petite représentation de la séquence exacte des images de sortie, même si MJPEG est un codec terriblement inefficace par rapport aux normes actuelles. (pas de redondance temporelle, et même pas de prédiction intra.

Vous pouvez créer une vidéo MJPEG à cadence variable pour tirer parti des images en double dans votre entrée.

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

Hrm, cela ne fonctionnera pas, car mpdecimate ne fonctionnera pas sur les données compressées, et nous ne pouvons pas laisser ffmpeg décoder puis re-jpeger les données d'image sans perte et sans coût CPU.

Peut-être que si vous avez remplacé les fichiers source jpg en double par des fichiers vides avec ce numéro de séquence, ou quelque chose?

Puisque cette question n'est même pas récente, je ne vais pas prendre le temps de comprendre comment le faire à moins que quelqu'un ne réponde pour demander comment. Mais comme MJPEG peut aller dans un conteneur mkv, je suis sûr qu'il est possible d'avoir un fichier qui ne duplique pas les données jpeg pour les trames répétées, mais qui n'a simplement pas de trame de sortie à décoder jusqu'à ce que la séquence de doublons soit plus de.

Oh, voici une idée:

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

Ensuite, supprimez (ou déplacez de côté) tous les fichiers jpeg pour les images que mpdecimate veut supprimer (probablement il a des options de journalisation? Ou -vf showinfo, et analysez cela, et déplacez ou liez en dur uniquement les images qui apparaissent dans sa sortie, en laissant derrière les fichiers JPEG supprimés?). multiplexez cela dans un MJPEG.mkv, puis faites quelque chose avec mkvmerge pour remplacer les horodatages de trame dans celui par les horodatages de mpdecimate.timestamps.

Si vous étiez en xcodage, au lieu de simplement muxer des données jpeg vers MJPEG, ce serait BEAUCOUP plus facile, car vous utiliseriez simplement ma première commande avec mpdecimate et tout codec autre que copy, et cela fonctionnerait simplement (tm).

Je n'ai rien essayé de tout cela, car c'était une vieille question. Aussi la raison pour laquelle je n'ai pas comblé les lacunes sur la façon de filtrer votre répertoire de fichiers JPEG en fonction de la sortie mpdecimate, ou sur la façon d'utiliser réellement le flux d'horodatage.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.