我一直在使用Ruby中的管道和IO.popen
,并遇到了一个问题,我无法解决。我正在尝试将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
保持空闲(根本没有处理器使用)。没有出现任何错误或异常。我正在Windows 7上使用cygwin,使用cygwin ruby包(1.9.3p429(2013-05-15)[i386-cygwin])。
我一定是做错了什么,任何帮助都非常感谢。谢谢!
额外#1
我想从
lame
进程中进行二进制数据的输入和输出,因为我正在尝试创建一个平台无关(当然,ruby支持有限)用于转码音频文件,而lame
的Windows二进制文件仅支持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
是一样的吗? - icy