Ruby Gem在命令行和irb上运行 - 在作为ruby脚本运行或通过Java Process运行时失败

时间:2012-03-26 16:46:08

标签: ruby gem irb

我一直试图让某个Google API工作两天。已经尝试了三个不同的项目 - 一个在Perl(很早就死了),一个在Python中(在最后一个障碍时崩溃和烧毁),最后一个在Ruby中。当从命令行调用作为标准命令时,Ruby实际上工作,即:

speech2text somefile.wav

如果你打开irb并输入项目网站上的示例代码,它甚至可以工作:

require 'speech'
audio = Speech::AudioToText.new("i-like-pickles.wav")
puts audio.to_text.inspect

但是,使用ruby -rubygems somescript.rb执行时,带有上述内容的Ruby .rb文件将不起作用。它退出了:

/Library/Ruby/Gems/1.8/gems/speech2text-0.3.4/lib/speech/audio_inspector.rb:50:in `initialize': undefined method `first' for nil:NilClass (NoMethodError)
from /Library/Ruby/Gems/1.8/gems/speech2text-0.3.4/lib/speech/audio_splitter.rb:77:in `new'
from /Library/Ruby/Gems/1.8/gems/speech2text-0.3.4/lib/speech/audio_splitter.rb:77:in `initialize'
from /Library/Ruby/Gems/1.8/gems/speech2text-0.3.4/lib/speech/audio_to_text.rb:15:in `new'
from /Library/Ruby/Gems/1.8/gems/speech2text-0.3.4/lib/speech/audio_to_text.rb:15:in `to_text'
from script/test_s2t.rb:6

尝试将Java中的命令行二进制文件speech2text用作运行时进程会导致反馈相同的错误消息。它抱怨的违规行是:

    def initialize(file)
  self.duration = Duration.new(`ffmpeg -i #{file} 2>&1`.strip.scan(/Duration: (.*),/).first.first)
end

但实际上存在问题的想法似乎不太可能,因为它在irb或终端上的二进制文件中执行时效果很好。

这里真正的问题是我根本不懂Ruby - 我使用Java工作,而我只需要这个API就能运行。它运行在一些方法的事实告诉我,我可能正确安装它,但除非我可以让.rb脚本工作或让它在外部执行,我看不到如何使用它。我已经把JRuby推荐给了我,但这对我来说可能太复杂了,因为它似乎需要手工安装JRuby的红宝石宝石,我不知道该怎么做(或者至少,我不喜欢我想我知道怎么做!)

对核心错误消息的任何建议都非常感激,但是如果你看到问题的明确回避,请告诉我。

编辑 - 这确实是一个路径问题 - 至少在表面上是这样。 Ruby无法找到所涉及的确切文件,因此,speech2text / ffmpeg失败的结果相当模糊。谢谢!

2 个答案:

答案 0 :(得分:1)

这闻起来像路径问题。您应该始终指定文件的完整路径,因为其他进程可以在内部将其工作目录更改为其他位置。另一种可能性是更改$PATH,以便ffmpeg无法解析为绝对路径。

通常,您应该尝试将路径指定为尽可能绝对。

答案 1 :(得分:0)

你使用反引号可能会掩盖问题:

`ffmpeg -i #{file} 2>&1`.strip.scan(/Duration: (.*),/).first.first

如果您什么也没收到,或者您的搜索结果中没有“持续时间:”,那么您将收到错误消息。

首先,确认您的路径是正确的。任何嵌入的空格都会破坏您的命令,因为ffmpeg将接收文件名作为多个参数,而不是完整的文件路径。您可以使用任何系统调用或popen来防止这种情况,或者逃避任何嵌入空格和单/双引号。至少,尝试:

`ffmpeg -i "#{file}" 2>&1`

`ffmpeg -i '#{file}' 2>&1`

考虑将您对ffmpeg的调用分成多个步骤,进行防御性编写,并了解正在发生的事情。这是未经测试的代码,但应该给你一个想法:

ffmpeg_results = `ffmpeg -i #{ file } 2>&1`
if (!ffmpeg_results.strip.empty?)
  duration = ffmpeg_results.strip[/Duration: (.*),/, 1]
  if (!duration.strip.empty? && duration.to_i > 0)
    ...
  end
else
  puts "ffmpeg_results are empty"
end  

您希望在继续之前尝试每一步,至少直到您确定自己的流程是防弹的,或者根据需要进行防弹。