Utilisation d'un codec vidéo sans perte pour l'archivage de données vidéo scientifiques (monochromes)

9

Question de base: qu'est-ce qu'un codec approprié pour stocker / archiver des données vidéo scientifiques sans perte ?

J'essaie d'aider mon groupe de recherche à stocker / archiver des vidéos enregistrées au microscope. Ces vidéos (en niveaux de gris) sont au format BGR24 non compressé (rawvideo), 660x492 @ 61fps, et durent généralement environ 1 minute. Mes collègues de laboratoire deviennent fous avec la taille de ces fichiers (gigaoctets chacun). J'ai suggéré de les compresser en utilisant un codec sans perte. (Le besoin de perte sans perte est dû au fait que les vidéos sont des données scientifiques; il existe donc un risque qu'un codec avec perte puisse altérer le contenu de manière incorrecte / inattendue.)

Voici ce que j'ai essayé. Tout d'abord, j'ai saisi les 10 premières secondes d'une de ces vidéos et converti au format monochrome (brut) à l'aide de FFMpeg.

ffmpeg -t 10 -i RecordedData.avi -c:v rawvideo -pix_fmt gray raw_gray.mkv

Ensuite, j'ai essayé d'utiliser le mode sans perte de libx264 (en définissant -crf 0) pour compresser le fichier résultant

ffmpeg -i raw-gray.mkv -c:v libx264 -crf 0 -pix_fmt yuv420p -color_range pc x264-yuv420p.mkv

Enfin, j'ai extrait les données brutes YUV des fichiers bruts et h264 MKV et les ai comparés.

ffmpeg -i raw-gray.mkv -c:v rawvideo -pix_fmt gray raw-gray.yuv
ffmpeg -i x264-yuv420p.mkv -c:v rawvideo -pix_fmt gray x264-decompressed.yuv
diff -sq raw-gray.yuv x264-decompressed.yuv

Ici, la diffcommande signale que les fichiers diffèrent lorsque je m'attendais à ce qu'ils soient identiques. Pourquoi est-ce? Est-ce juste une légère erreur d'arrondi, ou est-ce que je peux perdre quelque chose après avoir fait la compression H264 (supposément sans perte)? Il y a une certaine conversion des formats de pixels en cours ( gray (YUV400) <-> YUV420), mais les canaux de couleur (UV) doivent être vides car l'entrée est monochrome.

Si je perds effectivement quelque chose, puis-je faire quelque chose pour y remédier? Existe-t-il un autre codec (sans perte) qui pourrait être plus approprié pour mes données?


Mise à jour 1 : j'ai utilisé hexdump pour comparer plus en détail le contenu des données YUV non compressées de raw-gray.yuv(jamais compressé) et x264-decompressed.yuv(compressé puis décompressé). Voici les premiers octets.

[raw-gray.yuv]

00000000  4e 50 51 53 53 52 51 50  51 51 50 4f 50 50 50 50
00000010  51 51 50 51 52 53 51 51  52 52 53 53 52 51 51 53
00000020  51 53 54 55 53 51 52 54  53 53 52 50 51 50 52 52
00000030  51 52 51 51 51 52 54 52  52 52 51 51 51 53 57 58
00000040  57 57 55 54 54 52 53 51  51 52 53 55 55 54 53 53
00000050  51 51 52 52 53 52 51 50  50 50 50 51 51 4f 4f 4e
00000060  4c 4d 4e 4d 4f 50 4f 50  51 51 51 52 52 52 52 50
00000070  50 50 52 52 53 55 55 55  57 52 53 53 53 54 56 56

[x264-decompressed.yuv]

00000000  53 55 56 57 57 56 56 55  56 56 55 54 55 55 55 55
00000010  56 56 55 56 56 57 56 56  56 56 57 57 56 56 56 57
00000020  56 57 58 59 57 56 56 58  57 57 56 55 56 55 56 56
00000030  56 56 56 56 56 56 58 56  56 56 56 56 56 57 5b 5c
00000040  5b 5b 59 58 58 56 57 56  56 56 57 59 59 58 57 57
00000050  56 56 56 56 57 56 56 55  55 55 55 56 56 54 54 53
00000060  51 52 53 52 54 55 54 55  56 56 56 56 56 56 56 55
00000070  55 55 56 56 57 59 59 59  5b 56 57 57 57 58 5a 5a

Les valeurs de l'ancien fichier sont de 4 à 5 inférieures aux valeurs de ce dernier. La même chose se trouve en creusant un peu plus profondément dans le fichier.


Mise à jour 2 : Si j'utilise libx264 en mode RVB, je peux obtenir une correspondance exacte avec l'original en faisant la même chose que ci-dessus en plus de ce qui suit.

ffmpeg -i raw-gray.mkv -c:v libx264rgb -crf 0 -pix_fmt bgr24 x264-bgr24.mkv
ffmpeg -i x264-bgr24.mkv -c:v rawvideo -pix_fmt gray x264-bgr24-decomp.yuv
diff -sq raw-gray.yuv x264-bgr24-decomp.yuv

La dernière commande signale que les deux fichiers sont identiques . Malheureusement, il x264-bgr24.mkvest environ 3 fois plus grand que x264-yuv420.mkvla compression en mode RVB.

J'ai lu quelque part que libx264 comprime efficacement la vidéo en niveaux de gris en mode YUV car il détecte que seul le canal Y contient des informations réelles (les canaux U et V sont tous les deux nuls pour la vidéo monochrome). En mode RVB, je pense que tous les canaux contiendraient des informations identiques pour l'entrée monochrome. Peut-être que libx264rgb n'en profite pas.

Donc, existe-t-il un moyen pour moi d'utiliser le mode YUV sans altérer la vidéo, car la compression est beaucoup plus efficace de cette façon?


Mise à jour 3 : j'ai pu résoudre le problème avec libx264 en utilisant -pix_fmt yuvj420pau lieu de -pix_fmt yuv420p -color_range pc. Ensuite, je reproduis le fichier d'origine exactement après compression / décompression. De la documentation FFmpeg, j'avais l'impression que ces deux ensembles de drapeaux étaient équivalents, mais ce n'est évidemment pas le cas. Le seul problème est que je reçois un avertissement avec ce dernier ensemble de drapeaux: [swscaler @ 0x55b56347fe20] deprecated pixel format used, make sure you set the range correctly. J'ai également trouvé ce rapport de bogue qui pourrait être lié à mon problème. Je ne suis pas sûr de la "bonne" façon de faire les choses sans utiliser le format pixel yuvj420p apparemment déconseillé.

Nick C.
la source
1
Étant donné que les données sont décompressées, vous feriez mieux de les transformer à la fois au format texte (par exemple en utilisant hexdump) et d'exécuter le diff à ce sujet. diffdira simplement que les fichiers sont quelque part différents. Un bit, un mégaoctet, c'est tout de même. En inspectant le différentiel hexadécimal, vous pouvez mieux estimer ce qui s'est passé et si vous devez vous inquiéter. Vérifiez également que l'opération n'a pas arrondi la largeur ou la hauteur de la vidéo (je m'en suis aperçu).
LSerni
1
Une source possible de perturbation pourrait être un serrage de canal Y différent (selon CCIR-601). Vérifiez si par hasard vous semblez perdre des valeurs Y inférieures à 16 et supérieures à 240. Voir aussi video.stackexchange.com/questions/16840/…
LSerni
1
Vous pouvez également utiliser ffmpeg pour recomposer vos deux vidéos en images individuelles et utiliser imagemagickcompare pour les comparer.
xenoid
1
Un bon moyen de comparer l' absence de perte est d'utiliser le multiplexeur de hachage . Affiche la sortie complète de ffmpeg -i RecordedData.avi. libx264rgb prend en charge bgr24, vous pouvez donc considérer cet encodeur comme une option.
llogan
1
Il suffit de les encoder sans perte en utilisant le mode RVB de x264 (ignorer la conversion au format pixel).
Gyan

Réponses:

6

Ce n'est pas une réponse directe à votre problème réel, mais j'envisagerais d'utiliser le FFV1codec FFmpeg-internal :

$ ffmpeg -i raw-gray.mkv -c:v ffv1 ffv1.mkv

Alternativement, la version 3 de celui-ci:

$ ffmpeg -i raw-gray.mkv -c:v ffv1 -level 3 ffv1.mkv

Alors:

$ ffmpeg -i ffv1.mkv -c:v rawvideo -pix_fmt gray raw-gray.yuv
$ diff -sq raw-ffv1.yuv raw-gray.yuv
Files raw-ffv1.yuv and raw-gray.yuv are identical

Ce n'est pas aussi efficace que libx264 en mode sans perte lors de l'utilisation yuv420p, mais il est plus efficace que d'utiliser libx264 avec bgr24(dans mes tests, le débit de données était quelque part entre les deux). Certaines institutions comme la Bibliothèque du Congrès reconnaissent également FFV1 comme format de conservation approprié .

slhck
la source
Ceci est une réponse à ma question de base d'origine, que j'ai modifiée pour la rendre plus claire. Je n'ai rencontré aucun problème avec FFV1. En fait, FFV1 a atteint le même taux de compression que libx264 (w / -crf 0 -preset medium) pour ma vidéo particulière, et c'était plus rapide. Encore mieux, il prend directement en charge le grayformat pixel. En effet, cela semble être une excellente solution.
Nick C.