Я работал с каналами и IO.popen
конкретно в Ruby и столкнулся с проблемой, которую не могу понять. Я пытаюсь записать двоичные данные из процесса flac
в процесс lame
в файл. Структура кода, которую я использую, приведена ниже.
# file paths
file = Pathname.new('example.flac').realpath
dest = Pathname.new('example.mp3')
# execute the process and return the IO object
wav = IO.popen("flac --decode --stdout \"#{file}\"", 'rb')
lame = IO.popen("lame -V0 --vbr-new - -", 'r+b')
# write output from wav to the lame IO object
lame << wav.read
# close pipe for writing (should indicate to the
# process that input for stdin is finished).
lame.close_write
# open up destiniation file and write from lame stdout
dest.open('wb'){|out|
out << lame.read
}
# close all pipes
wav.close
lame.close
Однако это не работает. После запуска flac
скрипт зависает, а lame
остается бездействующим (вообще не использует процессор). Ошибки или исключения не возникают.
Я использую cygwin в Windows 7 с пакетом cygwin ruby (1.9.3p429 (2013-05-15) [i386-cygwin]).
Должно быть, я делаю что-то не так, любая помощь очень ценится. Спасибо!
ДОПОЛНИТЕЛЬНО #1
Я хочу вводить и выводить двоичные данные из процесса lame
, потому что я пытаюсь создать независимую от платформы (поддержка ruby, конечно, ограничена) для перекодирования аудиофайлов, а двоичный файл Windows только для lame
поддерживает имена путей Windows, а не cygwin.
ИЗМЕНИТЬ №1
Я читал в некоторых местах (URL-адреса не сохранял, попробую поискать в истории браузера), что у IO.popen
были известные проблемы с блокировкой процессов в Windows и что это может быть так.
Я экспериментировал с другими библиотеками, включая Ruby Open3.popen3
и Open4
, однако, следуя структуре кода, очень похожей на приведенную выше, процесс lame
по-прежнему зависает и не отвечает.
РЕДАКТИРОВАНИЕ №2
Я нашел эта статья, в которой говорилось об ограничениях Windows cmd.exe
и о том, как он предотвращает использование потоковых данных из файлов в стандартный ввод.
Я реорганизовал свой код, чтобы он выглядел так, как показано ниже, чтобы проверить это, и, как оказалось, lame
зависает при записи на стандартный ввод. Если я удалю (закомментирую) эту строку, будет выполнен процесс lame
(с предупреждением о «неподдерживаемом аудиоформате»). Возможно, то, что сказано в статье, может объяснить мою проблему здесь.
# file paths
file = Pathname.new('example.flac').realpath
dest = Pathname.new('example.mp3')
# some local variables
read_wav = nil
read_lame = nil
# the flac process, which exits succesfully
IO.popen("flac --decode --stdout \"#{file}\"", 'rb'){|wav|
until wav.eof do
read_wav = wav.read
end
}
# the lame process, which fails
IO.popen("lame -V0 --vbr-new --verbose - -", 'r+b'){|lame|
lame << read_wav # if I comment out this, the process exits, instead of hanging
lame.close_write
until lame.eof do
read_lame << lame.read
end
}
ИЗМЕНИТЬ №3
Я нашел этот stackoverflow, который ( в первом ответе) упомянул, что реализация канала cygwin
ненадежна. Возможно, это может быть связано не с Windows (по крайней мере, не напрямую), а с cygwin и его эмуляцией. Вместо этого я решил использовать следующий код, основанный на ответе icy, который работает!
flac = "flac --decode --stdout \"#{file}\""
lame = "lame -V0 --vbr-new --verbose - \"#{dest}\""
system(flac + ' | ' + lame)
Open3#capture3
и установить:stdin_data
. Или это то же самое, что иlame << read_wav
? - person icy   schedule 13.08.2013