windows - ruby - IO.popen not working lame stdin and stdout encoding -
i've been working pipes , io.popen in ruby , have come across problem can't figure out. trying write binary data flac process lame process file. code structure using below.
# file paths file = pathname.new('example.flac').realpath dest = pathname.new('example.mp3') # execute process , return io object wav = io.popen("flac --decode --stdout \"#{file}\"", 'rb') lame = io.popen("lame -v0 --vbr-new - -", 'r+b') # write output wav lame io object lame << wav.read # close pipe writing (should indicate # process input stdin finished). lame.close_write # open destiniation file , write lame stdout dest.open('wb'){|out| out << lame.read } # close pipes wav.close lame.close however, doesn't work. after flac has run, script hangs , lame remains idle (no processor usage @ all). no errors or exceptions occur.
i using cygwin on windows 7, cygwin ruby package (1.9.3p429 (2013-05-15) [i386-cygwin]).
i must doing wrong, appreciated. thanks!
extra #1
i wanting pipe in , out binary data lame process because trying create platform independent (ruby support limited of course) transcode audio files, , windows binary of lame supports windows' path names, , not cygwin's.
edit #1
i read in places (i did not save urls, i'll try looking them in browser history) io.popen has known issues blocking processes in windows , case.
i have played around other libraries including ruby's open3.popen3 , open4, following similar code structure 1 above, lame process still hangs , remains unresponsive.
edit #2
i found this article talked limitations of of windows's cmd.exe , how prevents use of streamed data files stdin.
i refactored code shown below test out, , turns out, lame freezes on stdin write. if removed (comment out) line, lame process executes (with 'unsupported audio format' warning). perhaps article said explain problem here.
# file paths file = pathname.new('example.flac').realpath dest = pathname.new('example.mp3') # local variables read_wav = nil read_lame = nil # flac process, exits succesfully io.popen("flac --decode --stdout \"#{file}\"", 'rb'){|wav| until wav.eof read_wav = wav.read end } # lame process, fails io.popen("lame -v0 --vbr-new --verbose - -", 'r+b'){|lame| lame << read_wav # if comment out this, process exits, instead of hanging lame.close_write until lame.eof read_lame << lame.read end } edit #3
i found stackoverflow (in first answer) mentioned cygwin pipe implementation unreliable. perhaps not related windows (at least not directly) instead cygwin , emulation. have instead opted use following code, based upon icy's answer, which works!
flac = "flac --decode --stdout \"#{file}\"" lame = "lame -v0 --vbr-new --verbose - \"#{dest}\"" system(flac + ' | ' + lame)
did try pipe | character?
tested on windows ruby installer
require 'open3' command = 'dir /b | sort /r' # windows example command open3.popen3(command) {|stdin, stdout, stderr, wait_thr| pid = wait_thr.pid puts stdout.read #<a list of files in cwd in reverse order> } other ways: ruby pipes: how tie output of 2 subprocesses together?
edit: using io::pipe
require 'open3' command1 = 'dir /b' command2 = 'sort /r' reader,writer = io.pipe open3.popen3(command1) {|stdin, stdout, stderr, wait_thr| writer.write stdout.read } writer.close stdout, stderr, status = open3.capture3(command2, :stdin_data => reader.read) reader.close puts "status: #{status}" #pid , exit code puts "stderr: #{stderr}" #use debug command2 errors puts stdout embedding 2 appears work, yet, blog referred said, 1 must wait first command finish (not real-time -- test ping command)
stdout2 = '' open3.popen3(command1) {|stdin, stdout, stderr, wait_thr| stdout2, stderr2, status2 = open3.capture3(command2, :stdin_data => stdout.read) } puts stdout2
Comments
Post a Comment