Pergunta básica: o que é um codec adequado para armazenar / arquivar dados de vídeo científicos de maneira isenta de perdas ?
Estou tentando ajudar meu grupo de pesquisa a armazenar / arquivar alguns vídeos gravados com um microscópio. Esses vídeos (em tons de cinza) estão no formato BGR24 não comprimido (rawvideo), 660x492 @ 61fps e normalmente com cerca de 1 minuto de duração. Meus colegas de laboratório estão enlouquecendo com o tamanho desses arquivos (gigabytes cada um). Eu sugeri compactá-los usando um codec sem perdas. (A necessidade do lossless aqui é porque os vídeos são dados científicos; portanto, há algum perigo de que um codec com perdas possa 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 (raw) 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 perda de 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
Por fim, extraí os dados brutos do YUV dos arquivos raw 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 comando diff
informa que os arquivos são diferentes quando eu esperava que fossem iguais. Por que isso acontece? Isso é apenas um pequeno erro de arredondamento ou estou possivelmente perdendo alguma coisa depois de fazer a compactação H264 (supostamente sem perdas)? Há alguma conversão de formatos de pixels acontecendo ( gray (YUV400) <-> YUV420
), mas os canais de cor (UV) devem estar vazios porque a entrada é monocromática.
Se eu estou de fato perdendo alguma coisa, há algo que eu possa fazer para consertar isso? Existe outro codec (sem perdas) que possa ser mais apropriado para meus dados?
Atualização 1 :
Eu usei o hexdump para comparar o conteúdo dos dados YUV não compactados de raw-gray.yuv
(nunca compactado) e x264-decompressed.yuv
(compactado e descompactado) em 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 do último. O mesmo é encontrado cavando um pouco mais fundo no arquivo.
Atualização 2 :
Se eu usar 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 informa que os dois arquivos são idênticos . Infelizmente, x264-bgr24.mkv
é cerca de 3 vezes maior que x264-yuv420.mkv
, então a compressão no modo RGB não é tão boa.
Eu li em algum lugar que libx264 comprime vídeo em tons de cinza eficientemente no modo YUV porque ele pega no fato de que somente o canal Y contém qualquer informação real (canais U e V são ambos 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 aproveite isso.
Então, existe uma maneira de eu usar o modo YUV sem alterar o vídeo, já que a compactação é muito mais eficiente assim?
Atualização 3 :
Consegui resolver o problema com a libx264 usando -pix_fmt yuvj420p
em vez 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 recebo 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 erros que pode estar relacionado ao meu problema. Eu não tenho certeza da maneira "correta" de fazer as coisas sem usar o formato de pixel yuvj420p aparentemente obsoleto.