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, "730dlseek(4, 0, SEEK_SET) = -1 ESPIPE (Illegal seek)
fatal error: can't update LAME-tag frame!
lseek(4, 0, SEEK_SET) = 0
write(4, "730dlseek(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.
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) :
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).