Как сказать хромать писать заголовок VBR в поток?
Я хочу использовать lame для кодирования mp3-файлов, но вместо того, чтобы записывать его непосредственно в файл, я хочу передать его в другую программу, которая в конечном итоге запишет его куда-нибудь. Проблема в том, что если lame обнаруживает, что его вывод является потоком, он не записывает заголовок VBR, и проигрыватели неправильно определяют длину файла. Например, если я сделаю это, то полученный файл будет неправильным:
lame infile.wav - >outfile.mp3
Я попробовал следующий трюк:
lame infile.wav /dev/stdout >outfile.mp3
Сначала это работает, но только если stdout напрямую перенаправлен в файл. Следующий случай не работает:
lame infile.wav /dev/stdout | cat >outfile.mp3
Если я использую ffmpeg (или avconv) в качестве внешнего интерфейса для lame, у меня точно такая же проблема.
Есть ли способ сказать lame, что я хочу, чтобы он записал заголовок VBR, даже если он думает, что пишет в поток?
1 ответ
Кажется, что это не может быть сделано таким образом. Проблема в том, что заголовок VBR записывается в начало файла, но вычисляется только в конце кодировки. Это требует поиска в файле, что невозможно, если вывод представляет собой канал.
Я побежал strace
на все варианты выше. Во 2-й версии (при записи в обычный файл) в конце я получаю следующее:
lseek(4, 0, SEEK_SET) = 0
write(4, "\377\373\220d\0\0\0"..., 417) = 417
close(4) = 0
В 1-й версии, где я использую -
в качестве выходного аргумента lame даже не пытается написать заголовок. В 3-й версии, однако, он пытается, но терпит неудачу, потому что вывод - труба.
lseek(4, 0, SEEK_SET) = -1 ESPIPE (Illegal seek)
В конце он также пишет сообщение об ошибке, которое легко пропустить из-за другого вывода, который он обычно печатает в stderr, если я не запускаю его с --silent
Опция (что я и сделал, чтобы очистить вывод strace):
fatal error: can't update LAME-tag frame!
Решением этой проблемы является либо запись во временный файл, затем дальнейшая передача, либо использование кодирования с постоянным битрейтом (в этом случае дополнительный заголовок не записывается в начале файла после кодирования).