【问题标题】:How to pass Ruby's STDIN to an external program called by Open3.popen3?如何将 Ruby 的 STDIN 传递给 Open3.popen3 调用的外部程序?
【发布时间】:2015-10-22 03:15:46
【问题描述】:

我想从 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 收到一条错误消息:“Failed writing body”。

【问题讨论】:

    标签: ruby ffmpeg stream pipe stdin


    【解决方案1】:

    你错过了popen3 的一个关键特性,那就是它会为你提供句柄,你可以对它们做任何你想做的事情:

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

    【讨论】:

      【解决方案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
      

      【讨论】:

        【解决方案3】:

        如果“vpipe”做的最后一件事是调用另一个命令,并且您想不加修改地传递标准输入、标准输出和标准错误,那么使用Open3.popen3 是一种浪费。请改用exec!这很容易。

        【讨论】:

          猜你喜欢
          • 2014-10-09
          • 2023-04-07
          • 2017-02-12
          • 2016-05-31
          • 2017-08-18
          • 2013-02-08
          • 2014-06-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多