catching process output (Kernel#system)

C

Chris Donhofer

hi!

when executing a program via the system method, how do i catch the
output of the executed program?

furthermore, is there a tutorial describing how to use the system
function the best way?

TIA, chris
 
C

Chris Donhofer

hi!

Paul said:
By not using "Kernel::system()".

To get the error status of a completed process:

err = system("command")

To get the output from a process:

output = `command`


thx!



That depends on what you think is the best way. Maybe you could describe the
application you have in mind.

im trying to create a simple application that does the following:

1. get a list of files(media files) in a certain directory
2. for every file:
a. get the filetype
b. choose the appropriate converter (f.i. ffmpeg, swf2flv)
c. convert the file
d. continue
3. write process output to logfile

cheers, chris
 
V

Vincent Fourmond

Hello !
im trying to create a simple application that does the following:

1. get a list of files(media files) in a certain directory
2. for every file:
a. get the filetype
b. choose the appropriate converter (f.i. ffmpeg, swf2flv)
c. convert the file
d. continue
3. write process output to logfile

In that case, the `command` syntax is perfectly adapted. (or system,
for the conversion). In case you need to check the return value of the
`commands`, use $? .

If you need to work with bigger output, where it would not be suitable
to store it all in a Ruby variable, give a look at IO.popen

Cheers !

Vince
 
R

Robert Klemme

Vincent said:
In that case, the `command` syntax is perfectly adapted. (or system,
for the conversion). In case you need to check the return value of the
`commands`, use $? .

If you need to work with bigger output, where it would not be suitable
to store it all in a Ruby variable, give a look at IO.popen

Plus, an alternative syntax fpr `ls foo` is %x{ls foo}.

robert
 
C

Chris Donhofer

thx for the answers guys!

but still, i cant get the output into my array. below is the code im
using - what am i doing wrong?

cheers, chris

def do_convert
#testcode
#convert file
puts "STARTING CONVERSION..."
op = ["ffmpeg result/output:".upcase, " "]

#using ls instead of ffmpeg, so everyone can test this
IO.popen("ls") do |l|
op.insert(-1, l)
end

#i also tried "p = IO.popen('ls')" and then
#my_array = p.readlines, but with the same result

#display output
op.each do |line|
puts line
end

end
 
C

Chris Donhofer

i was a bit too quick posting the last msg, the code should be:

IO.popen("ffmpeg -i my.mov -t flv fruhwirth150306.flv") do |l|
op.insert(-1, l.gets) #using gets now
end

still...the only outpu i get is nil.
 
V

Vincent Fourmond

Hello !

This works, at least where popen is available

op = []

IO.popen("ls") do |l|
op += l.readlines
end
p op

However, if you are on a Win box, my guess is it won't work... Use
backticks, then. Just for information, the argument of the block of
popen or open is an the IO object representing the file you opened.

Cheers

Vince
 
M

MonkeeSage

Chris said:
i was a bit too quick posting the last msg, the code should be:

IO.popen("ffmpeg -i my.mov -t flv fruhwirth150306.flv") do |l|
op.insert(-1, l.gets) #using gets now
end

still...the only outpu i get is nil.

Hmmm...you're telling ffmpeg to output a file. So...what output are you
trying to get from ffmpeg on stdout? The encoding progress or
something?

Regards,
Jordan
 
C

Chris Donhofer

@vincent:
thx, this works perfectly for 'ls', but unfortunately not for ffmpeg - i
guess i didn't see the difference between the ways those two commands
do their output.
Hmmm...you're telling ffmpeg to output a file. So...what output are you
trying to get from ffmpeg on stdout? The encoding progress or
something?

Regards,
Jordan

im trying to catch this:

ffmpeg version 0.4.9-pre1, build 4747, Copyright (c) 2000-2004 Fabrice
Bellard
configuration: --build i386-linux --enable-gpl --enable-pp
--enable-zlib --enable-vorbis --enable-a52 --enable-dts --disable-debug
--prefix=/usr
built on Mar 8 2006 21:32:15, gcc: 3.3.5 (Debian 1:3.3.5-13)
Input #0, mov,mp4,m4a,3gp,3g2, from
'/home/insel/projects/flv_encoder/in/fruhwirth150306.mov':
Duration: 01:17:40.0, start: 0.000000, bitrate: 64 kb/s
Stream #0.0: Video: rpza, 800x600, 1.00 fps
Output #0, flv, to 'fruhwirth150306.flv':
Stream #0.0: Video: flv, 800x600, 1.00 fps, q=2-31, 200 kb/s
Stream mapping:
Stream #0.0 -> #0.0
Press [q] to stop encoding
frame= 4660 q=0.0 Lsize= 76131kB time=4660.0 bitrate= 133.8kbits/s
video:76059kB audio:0kB global headers:0kB muxing overhead 0.095749%

cheers, chris
 
M

MonkeeSage

Hi Chris,

ffmpeg writes that on stderr rather than stdout, so a simple way to
capture it is with output redirection (the 2>&1 part means redirect
stderr to stdout):

op = ["ffmpeg result/output:".upcase, " "]
....
op << %x{ffmpeg -v 2>&1}

For a more robust solution to capturing stderr look at popen3 in the
standard library [1] or the popen4 extension from rubyforge [2].

Also note that it's somewhat complicated to try to read the output of
programs like ffmpeg to get the encoding status for realtime display in
your app. To do that you'll probably have to use threads and a polling
loop or IO#select among other things. I don't know if that's why you
want to read the output, but I just thought I'd let you know.

[1] http://www.ruby-doc.org/stdlib/libdoc/open3/rdoc/index.html
[2] http://popen4.rubyforge.org/

Regards,
Jordan
 
C

Chris Donhofer

i got my video converter script working and since im very new to ruby,
i'd really appreciate feedback, so i can learn how to use ruby better.
(the script is attached)
all comments welcome! =)

TIA, chris



#@Author: Christian (insel) Donhofer
#@Contact: (e-mail address removed)

require 'ftools'
require 'date'

class FlvEncoder

def instantiate

end

def start_conversion
@ts = DateTime.now
msg "FLV_Encoder [SESSION STARTING](#{@ts.day}.#{@ts.month}.#{@ts.year}, #{@ts.hour}:#{@ts.min}:#{@ts.sec})..."

#define working directories
@indir = Dir.pwd+"/in"
@spooldir = Dir.pwd+"/spool"
@outdir = Dir.pwd+"/out"
@bakdir = Dir.pwd+"/bak"
@dumpdir = Dir.pwd+"/dump"

@files = []

#get filelist
msg "reading #{@indir}"
@files = Dir.entries(@indir)
#transcode all media files
@files.each do |file|
do_convert(file) unless (file.eql?(".") || file.eql?(".."))
end
end

def do_convert(file)
@ts = DateTime.now
msg "[PROCESS STARTING](#{@ts.day}.#{@ts.month}.#{@ts.year}, #{@ts.hour}:#{@ts.min}:#{@ts.sec})..."

#create backup
msg "Creating backup instance...".upcase
msg "#{@indir}/#{file} ---> #{@bakdir}/#{file}"
File.copy("#{@indir}/#{file}", "#{@bakdir}/#{file}")

#move file
msg "MOVING FILE..."
msg "#{@indir}/#{file} ---> #{@spooldir}/#{file}"
File.move("#{@indir}/#{file}", "#{@spooldir}/#{file}")

#define actual and targetfile
actual_file = "#{@spooldir}/#{file}";
target_file = "#{@outdir}/"+File.basename(file, File.extname(file))+".flv";

#check file for readability
if(File.exist?(actual_file) && File.readable?(actual_file))
msg "File ready for conversion..."
else
msg "File not readable or not found - [SKIP]"
return
end

#convert file
msg "STARTING CONVERSION..."

if(File.extname(actual_file)==".mov"|| File.extname(actual_file)==".avi")
msg "USING FFMPEG..."
msg "CMD: ffmpeg -i #{actual_file} -t flv #{target_file} 2>&1"
IO.popen("ffmpeg -i #{actual_file} -t flv #{target_file} 2>&1") do |l|
msg l.readlines
end
elsif(File.extname(actual_file)==".swf")
msg "USING SWF2FLV..."
msg "CMD: swf2flv #{actual_file} #{target_file}"
IO.popen("swf2flv #{actual_file} #{target_file}") do |l|
msg l.readlines
end
else
msg "FILETYPE NOT RECKOGNIZED, DUMPING FILE, [SKIP]..."
File.move("#{@spooldir}/#{file}", "#{@dumpdir}/#{file}")
return
end

msg "[UNLINK]ING(DELETING) FILE IN SPOOL DIRECTORY..."
File.unlink("#{@spooldir}/#{file}") if File.exist?("#{@spooldir}/#{file}")


#check resulting flv file
msg "[FLVINFO] for resulting file:"
IO.popen("flvinfo #{target_file}") do |l|
msg l.readlines
end

@ts = DateTime.now
msg "[PROCESS ENDING](#{@ts.day}.#{@ts.month}.#{@ts.year}, #{@ts.hour}:#{@ts.min}:#{@ts.sec})..."

#TODO write log to file
end

#log/output text
def msg(str)
puts str
#write to log
if @log.nil?
@log = []
end
@log.push str
end
end

#create converter
conv = FlvEncoder.new
conv.start_conversion
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top