【发布时间】:2013-08-08 13:18:36
【问题描述】:
我一直在使用管道和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 保持空闲(根本没有处理器使用)。 没有错误或异常发生。
我在 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
我发现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
}
编辑#3
我发现这个stackoverflow(在第一个答案中)提到cygwin 管道实现不可靠。这实际上可能与 Windows 无关(至少不直接),而是与 cygwin 及其仿真有关。我选择使用以下代码,基于 icy 的回答,which works!
flac = "flac --decode --stdout \"#{file}\""
lame = "lame -V0 --vbr-new --verbose - \"#{dest}\""
system(flac + ' | ' + lame)
【问题讨论】:
-
编辑尝试
Open3#capture3和设置:stdin_data。还是和lame << read_wav一样?
标签: ruby windows cygwin lame flac