Como dizer lame para escrever cabeçalho VBR para transmitir?

1

Eu quero usar o lame para codificar arquivos mp3, mas em vez de escrevê-lo diretamente em um arquivo, eu quero canalizá-lo para outro programa que acabará por escrevê-lo em algum lugar. O problema é que, se o lame detecta que sua saída é um fluxo, ele não grava o cabeçalho VBR e os jogadores calculam o comprimento do arquivo errado. Por exemplo, se eu fizer isso, o arquivo resultante estará errado:

lame infile.wav - >outfile.mp3

Eu tentei o seguinte truque:

lame infile.wav /dev/stdout >outfile.mp3

Parece funcionar primeiro, mas apenas se o stdout for diretamente redirecionado para um arquivo. O caso a seguir não funciona:

lame infile.wav /dev/stdout | cat >outfile.mp3

Se eu usar o ffmpeg (ou avconv) como um front end para o lame, eu tenho exatamente o mesmo problema.

Existe alguma maneira de dizer ao lame que eu quero escrever o cabeçalho VBR mesmo que ele ache que está escrevendo para um fluxo?

    
por petersohn 14.02.2015 / 20:57

1 resposta

1

Parece que não pode ser feito dessa maneira. O problema é que o cabeçalho VBR é gravado no início do arquivo, mas é calculado apenas no final da codificação. Isso requer procurar no arquivo, o que não é possível se a saída for um canal.

Eu corri um strace em todas as variantes acima. Na segunda versão (quando escrevo para um arquivo normal), recebo o seguinte no final:

lseek(4, 0, SEEK_SET)                   = 0
write(4, "730d
lseek(4, 0, SEEK_SET)                   = -1 ESPIPE (Illegal seek)
fatal error: can't update LAME-tag frame!
lseek(4, 0, SEEK_SET)                   = 0
write(4, "730d
lseek(4, 0, SEEK_SET)                   = -1 ESPIPE (Illegal seek)
fatal error: can't update LAME-tag frame!
%pre%"..., 417) = 417 close(4) = 0
"..., 417) = 417 close(4) = 0

Na primeira versão, onde eu uso - como argumento de saída, o lame nem sequer tenta escrever o cabeçalho. Na terceira versão, no entanto, ele tenta, mas falha porque a saída é um pipe.

%pre%

Ele também grava uma mensagem de erro no final, que é facilmente ignorada por causa da outra saída que normalmente imprime para stderr, a menos que eu execute com a opção --silent (o que fiz, para tornar a saída de strace mais limpa) :

%pre%

A solução para esse problema é gravar em um arquivo temporário, depois canalizar isso mais adiante ou usar codificação de taxa de bits constante (caso em que nenhum cabeçalho adicional é gravado no início do arquivo após a codificação).

    
por 15.02.2015 / 09:56

Tags