Я работал с трубами и IO.popen
конкретно в Ruby и столкнулся с проблемой, которую я не могу понять. Я пытаюсь записать двоичные данные из процесса flac
в процесс lame
в файл. Структура кода, которую я использую, приведен ниже.ruby - IO.popen не работает lame stdin и stdout encoding
# 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 с пакетом ruby cygwin (1.9.3p429 (2013-05-15) [i386-cygwin]).
Я должен делать что-то неправильно, любая помощь очень ценится. Благодаря!
EXTRA # 1
Я хотел трубы и из двоичных данных из lame
процесса, потому что я пытаюсь создать платформу независимой (поддержки рубина ограничена конечно) перекодировать аудиофайлы , а двоичный код Windows lame
поддерживает только имена путей Windows, а не cygwin.
EDIT # 1
Я читал в некоторых местах (я не сохранить URL, я буду стараться искать их в моей истории браузера), что IO.popen
имеет проблемы с блокировкой процессов в Windows, и что это может быть так.
я играл с другими библиотеками, включая Руби Open3.popen3
и Open4
, однако после очень похожего кода структуры на один выше, процесс lame
до сих пор висит и остается отвечать на запросы.
EDIT # 2
Я нашел this статью, в которой говорил об ограничениях в ОС Windows на cmd.exe
и как он предотвращает использование потоковых данных из файлов на стандартный ввод.
Я отредактировал свой код, как показано ниже, чтобы проверить это, и, как оказалось, lame
зависает на записи stdin. Если я удалил (закомментировал) эту строку, процесс 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
}
EDIT # 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'? – icy