4

私はパイプ、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 ruby​​ パッケージ ( 1.9.3p429 (2013-05-15) [i386-cygwin] ) を使用して cygwin を使用しています。

私は何か間違ったことをしているに違いありません。どんな助けも大歓迎です。ありがとう!

エクストラ #1

オーディオファイルをトランスコードlameするためにプラットフォームに依存しない(もちろんルビーのサポートは限定されています)を作成しようとしているため、プロセスからバイナリデータをパイプインおよびパイプアウトしたいと考えています.WindowsバイナリはlameWindowsのパス名のみをサポートし、cygwinの.

編集#1

IO.popenWindows でプロセスをブロックすることに関する既知の問題があり、これが当てはまる可能性があるいくつかの場所を読みました (URL を保存しなかったので、ブラウザーの履歴で検索してみます) 。

RubyOpen3.popen3やを含む他のライブラリをいじってみOpen4ましたが、上記のコード構造と非常によく似たコード構造に従っているため、lameプロセスは依然としてハングし、応答しません。

編集#2

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

(最初の回答で)パイプの実装は信頼できないと述べたこのスタックオーバーフローを見つけました。cygwinこれはおそらく、実際には Windows に関連するものではなく (少なくとも直接的には)、cygwin とそのエミュレーションに関連している可能性があります。代わりに、 icyの回答に基づいて、次のコードを使用することを選択しまし

flac = "flac --decode --stdout \"#{file}\""
lame = "lame -V0 --vbr-new --verbose - \"#{dest}\""

system(flac + ' | ' + lame)
4

2 に答える 2