Usando um codec de vídeo sem perdas para arquivar dados de vídeo científico (monocromático)

9

Pergunta básica: o que é um codec adequado para armazenar / arquivar dados científicos de vídeo de maneira sem perdas ?

Estou tentando ajudar meu grupo de pesquisa a armazenar / arquivar alguns vídeos gravados com um microscópio. Esses vídeos (em escala de cinza) estão no formato BGR24 não compactado (vídeo bruto), 660x492 a 61fps e, geralmente, com duração de aproximadamente 1 minuto. Meus colegas de laboratório estão ficando loucos com o tamanho desses arquivos (gigabytes cada). Sugeri compactá-los usando um codec sem perdas. (A necessidade de perda aqui é porque os vídeos são dados científicos; portanto, existe o perigo de um codec com perda poder alterar o conteúdo de maneiras ruins / inesperadas.)

Aqui está o que eu tentei. Primeiro, peguei os primeiros 10 segundos de um desses vídeos e os converti para um formato monocromático (bruto) usando o FFMpeg.

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

Em seguida, tentei usar o modo sem perdas da libx264 (configurando -crf 0) para compactar o arquivo resultante

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

Finalmente, extraí os dados brutos do YUV dos arquivos brutos e h264 MKV e os comparei.

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

Aqui, o diffcomando relata que os arquivos diferem quando eu esperava que fossem os mesmos. Por que é isso? Isso é apenas um pequeno erro de arredondamento, ou estou perdendo alguma coisa depois de fazer a compactação H264 (supostamente sem perdas)? Há alguma conversão de formatos de pixel acontecendo ( gray (YUV400) <-> YUV420), mas os canais coloridos (UV) devem estar vazios porque a entrada é monocromática.

Se estou perdendo alguma coisa, posso fazer alguma coisa para consertar isso? Existe outro codec (sem perdas) que possa ser mais apropriado para meus dados?


Atualização 1 : usei o hexdump para comparar o conteúdo dos dados YUV descompactados de raw-gray.yuv(nunca compactado) e x264-decompressed.yuv(compactado e descompactado) com mais detalhes. Aqui estão os primeiros bytes.

[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

Os valores do arquivo anterior são 4 a 5 menores que os valores no último. O mesmo é encontrado cavando um pouco mais fundo no arquivo.


Atualização 2 : Se eu usar a libx264 no modo RGB, posso obter uma correspondência exata com o original, fazendo o mesmo que acima, além do seguinte.

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

O último comando relata que os dois arquivos são idênticos . Infelizmente, x264-bgr24.mkvé cerca de 3 vezes maior que x264-yuv420.mkv, portanto, a compactação no modo RGB não é tão boa.

Li em algum lugar que libx264 compacta vídeo em escala de cinza com eficiência no modo YUV, porque percebe o fato de que apenas o canal Y contém informações reais (os canais U e V são zero para vídeo monocromático). No modo RGB, acredito que todos os canais conteriam informações idênticas para entrada monocromática. Talvez a libx264rgb não tire proveito disso.

Então, existe uma maneira de eu usar o modo YUV sem alterar o vídeo, já que a compactação é muito mais eficiente dessa maneira?


Atualização 3 : Consegui resolver o problema com a libx264 usando em -pix_fmt yuvj420pvez de -pix_fmt yuv420p -color_range pc. Em seguida, reproduzo o arquivo original exatamente após a compactação / descompactação. A partir da documentação do FFmpeg, tive a impressão de que esses dois conjuntos de sinalizadores eram equivalentes, mas evidentemente esse não é o caso. O único problema é que eu tenho um aviso com o último conjunto de sinalizadores: [swscaler @ 0x55b56347fe20] deprecated pixel format used, make sure you set the range correctly. Além disso, encontrei este relatório de bug que pode estar relacionado ao meu problema. Não tenho certeza da maneira "correta" de fazer as coisas sem usar o formato de pixel yuvj420p aparentemente obsoleto.

Nick C.
fonte
11
Como os dados são descompactados, seria melhor transformá-los em um formato de texto (por exemplo, usar hexdump) e executar a comparação. diffdirá simplesmente que os arquivos estão em algum lugar diferente. Um bit, um megabyte, é tudo a mesma coisa. Ao inspecionar o hexadecimal, você pode estimar melhor o que aconteceu e se é algo com que se preocupar. Verifique também se a operação não arredondou a largura ou a altura do vídeo (aconteceu comigo).
precisa saber é o seguinte
11
Uma possível fonte de interrupção pode ser uma fixação de canal Y diferente (conforme CCIR-601). Verifique se, por acaso, você parece perder valores Y abaixo de 16 e acima de 240. Veja também video.stackexchange.com/questions/16840/…
LSerni 5/17/17
11
Você também pode usar o ffmpeg para re-decompor seus dois vídeos em imagens individuais e usar o imagemagickcompare para compará-los.
xenoid 5/09/17
11
Uma boa maneira de comparar a ausência de perdas é usar o hash muxer. Mostra a saída completa de ffmpeg -i RecordedData.avi. libx264rgb suporta bgr24, portanto, você pode considerar esse codificador como uma opção.
Llogan 6/09/17
11
Apenas codifique-os sem perdas usando o modo RGB de x264 (pule a conversão de formato de pixel).
Gyan

Respostas:

6

Esta não é uma resposta direta ao seu problema real, mas eu consideraria o uso do FFV1codec interno do FFmpeg :

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

Como alternativa, a versão 3 dela:

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

Então:

$ 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

Não é tão eficiente quanto a libx264 no modo sem perdas ao usar yuv420p, mas é mais eficiente do que usar a libx264 com bgr24(nos meus testes, a taxa de dados estava em algum lugar). Algumas instituições como a Biblioteca do Congresso também reconhecem o FFV1 como um formato de preservação adequado .

slhck
fonte
Esta é uma resposta à minha pergunta básica original, que editei para deixar mais claro. Não encontrei nenhum problema com o FFV1. De fato, o FFV1 alcançou a mesma taxa de compactação que libx264 (w / -crf 0 -preset medium) para o meu vídeo em particular, e foi mais rápido. Melhor ainda, ele suporta diretamente o grayformato de pixel. De fato, essa parece ser uma excelente solução.
Nick C.