A Tricaster TC40 (ou simplesmente como Tricaster 40) faz suas gravações em QuickTime MOV. A questão é que se algo acontece com o sistema que interrompe a gravação do arquivo você terá um arquivo ilegível. MOV, tal como MP4 e outros formatos, escrevem as informações sobre a leitura do arquivo e a localização de cada pacote de áudio e vídeo no extremo final do arquivo, o que causa ele ficar irreconhecível caso o processo não aconteça até o final como deveria. Mas há uma forma manual de recuperar e recompor este arquivo danificado.
O primeiro passo são os scripts em Python que escrevi para extrair e separar os blocos de vídeo e áudio do arquivo danificado. Lembrando que:
- Não sou um programador profissional. Faço isso de acordo com as minhas necessidade imediatas. O código poderia ser muito mais otimizado, amigável, rápido, mas não tenho o conhecimento ou tempo pra isso.
- Este código funciona estritamente de acordo com as características observadas na configuração de arquivo utilizado por mim, que é um arquivo com vídeo em MPEG-2 4:2:2 I-frames e dois canais de áudio estéreo PCM, o segundo sendo completamente mudo. Em diferentes situações o código pode necessitar uma total reescrita.
Script: extract-audio.py
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import os.path def read_in_chunks(infile, chunk_size=4): packet = False bloco_audio = b"" infile.seek(512) for chunk in iter(lambda: infile.read(chunk_size), ''): if chunk == b"\x00\x00\x01\xb3": if bloco_audio != b"": if bloco_audio[-4608:] == (b"\x00" * 4608): yield bloco_audio[-9216:-4608] bloco_audio = chunk continue bloco_audio += chunk infile = open(sys.argv[1], "rb") path = os.path.dirname(sys.argv[1])+"/"+os.path.splitext(os.path.split(sys.argv[1])[1])[0]+"_audio.raw" out = open(path, 'w') for chunk in read_in_chunks(infile): out.write(chunk)
Script: extract-video.py
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import os.path def read_in_chunks(infile, chunk_size=4): packet = False padding = False bloco_video = b"" infile.seek(512) for chunk in iter(lambda: infile.read(chunk_size), ''): if packet == True and chunk == b"\x00\x00\x01\xb3": packet = False if bloco_video != b"": if bloco_video[-4608:] == (b"\x00" * 4608): yield bloco_video[:-9216] else: yield bloco_video bloco_video = b"" if chunk == b"\x00\x00\x01\xb3": packet = True bloco_video += chunk continue if packet == True: bloco_video += chunk continue infile = open(sys.argv[1], "rb") path = os.path.dirname(sys.argv[1])+"/"+os.path.splitext(os.path.split(sys.argv[1])[1])[0]+"_video.ts" out = open(path, 'w') for chunk in read_in_chunks(infile): out.write(chunk)
(Não entrarei no aspecto de como rodar Python e FFMPEG em algum sistema pois devem ter instruções muito melhores e atualizadas internet afora.)
Após rodar estes scripts com "python extract-audio.py o-arquivo-danificado.mov" e "python extract-video.py o-arquivo-danificado.mov", e isso vai demorar bastante principalmente se o arquivo tiver vários gigabytes, você terá na mesma pasta do arquivo MOV arquivos com o mesmo tempo só que finais _audio.raw e _video.ts. Agora entra o FFMPEG para reorganizar eles a serem legíveis. E tudo dependerá do formato que o áudio e video pertencem.
Algumas correções necessárias para reprodução correta: video_track_timescale para corrigir a velocidade do arquivo (59,94 fps neste caso, pode ser diferente em outros arquivos) e vtag para assinalar a faixa de vídeo como a do formato escrito pela Tricaster e não o MPEG padrão. Também os parâmetros para definir para o programa player como deve ser lido o áudio PCM.
ffmpeg -i arquivo_video.ts -f s16le -ar 48000 -ac 2 -i arquivo_audio.raw -map 0:0 -map 1:0 \ -vcodec copy -video_track_timescale 60000 -vtag xd59 -acodec copy arquivo_video.mov
Isto feito temos um arquivo MOV com o vídeo e áudio que estava presente no arquivo danificado, agora legícvel em um novo arquivo MOV.