如何将Ruby的STDIN传递给Open3.popen3调用的外部程序?

时间:2015-07-30 16:29:37

标签: ruby ffmpeg stream pipe stdin

我想从Ruby脚本调用ffmpeg,让我们调用" vpipe",我希望这个Ruby脚本充当命令过滤器:从管道中获取输入。它的唯一目的是选择第一个音频流并删除章节数据(如果存在):

#!/usr/bin/ruby
require "open3"

output_file=ARGV[0]

cmd=%Q{ffmpeg -y -i - -map 0:v -map 0:a -c:v copy -c:a:0 copy -map_chapters -1 #{output_file}}

Open3.popen3(cmd,:stdin_data=>STDIN)

然后我想按照以下方式致电我的计划:

curl http://www.example.com/video.wmv | vpipe processed.wmv

不幸的是没有用,因为popen3没有这样的选项:stdin_data。我也试过Open3.capture3可以接受这个参数,但后来我收到了来自curl的错误信息:"写入正文"。

3 个答案:

答案 0 :(得分:2)

当你的程序在一个管道命令的下游时,它的STDIN将被输入上一个命令的输出。

使用Open3.popen3时,您可以完全控制分叉流程“STDINSTDOUTSTDERR。您需要手动为其提供所需的数据,并根据需要使用输出。

Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
  # consume outputs in STDOUT and STDERR, otherwise the ffmpeg process may be blocked if it produces a lot of outputs
  Thread.new do
    while stdout.read
    end
  end
  Thread.new do
    while stderr.read
    end
  end
  while data = STDIN.read(64)  # read output of the upstream command
    stdin.write(data)          # manually pipe it to the ffmpeg command
  end
  wait_thr.join
end

答案 1 :(得分:0)

你错过了popen3的一个关键功能,就是它会为你提供句柄,你可以随心所欲地做任何事情:

Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
  # Use stdin, stdout, stderr as you wish.
end

答案 2 :(得分:0)

如果最后一件事" vpipe"是调用另一个命令,你想要不经修改就传递stdin,stdout和stderr,然后使用Open3.popen3是一种浪费。请改用exec!这很容易。