Ruby on Rails Command Line Access
Jan 29
I’ve been digging around for a while trying to find a way for Ruby on Rails to access the command line. To be more specific, I’ve been trying to get RoR to kick off an FFmpeg process. My objective has been to allow video uploads through a rails app and then kick off a process to convert the file to flv format.
Luckily I stumbled across this post where the author was using RoR to perform mysql database functions. I created a function that calls the ffmpeg process to encode an uploaded video. The function looks like:
def encodeVideo opts, stream
IO.popen(“ffmpeg #{opts}”, ‘w’){ |io| io.puts stream}
end
A pipe is opened and written to in the form of a command. Options are then passed to the function that tell it which video to encode, the encoding options, and the output file. The call looks like this:
encodeVideo “-i /home/dennis/swing.avi -ar 22050 -ab 64 -f flv -s 320×240 /home/dennis/swing.flv”, <<-END
If you’ve experimented with accessing the command line from other web frameworks you’ll see that it doesn’t get much easier than this. Kudos to Sam for showing me the light.

This doesn’t seem to work for me. What goes after the
OK, worked it out. I was uploading video and encoding it directly. I just need to replace the END argument with myFile.read. How would your END statement work?
You should file this under Ruby on Rails instead of your “i’ll fill this someday”.
Dave, what exactly are you trying to do and I’ll be glad to lend a hand.
I have a quick question for you. What i am trying to do is read thru an flv file and get the dimensions. That way i know what size to set the screen in my “view”. Do you know if the flv format has metadata that contains the dimensions of the video size? If this was the case then i could read thru that metadata and use it to set my screen dimensions in my “view”. Or i think what i could do is read the file with FFMPEG and then then get the dimensions from it but in order to do that i have to be able to take the command line output and save that into a string or some other form that i can read thru and manipulate in rails. Is their a way to save the output after you run a command in the command line? If you have any thoughts i would greatly appreciate them. Thanks again
Hi,
Quick question. I’m trying to understand what’ll work best for my project. I’m on the Windows platform. I have a web application that has takes in uploaded videos in different formats like .avi, .mov. .mpeg, .wmv…etc., and I want to be able to convert these formats into .flv so that a client flash player can play the file using a .swf. I’m using RoR. My question has to do with whether ffmpeg is reliable and scalable? Also, is there a way to automatically feed the uploaded files to Flash to do the encoding into .flv without using ffmpeg? Thanks.
One more question, are there any limitations to using Windows as a platform with ffmpeg? Does it work just as smoothly? Thanks.
To answer your questions:
1. I’ve found FFmpeg very reliable and scalable once you find the optimal encoding settings for your application. You need to think about the load you’ll be putting on the server if 10 users are uploading videos at the same time, while all the different FFmpeg threads are encoding the video. This can cause a good amount of load and it may make sense to implement some sort of off-line encoding where the user uploads their video and receives an email when it’s available. This all depends on what kind of app you’re building and may be unacceptable in certain scenarios.
Another option I wanted to mention is VideoEgg (www.videoegg.com). These guys have developed a browser plugin that enables users to drag/drop video into the plugin and encode it on the fly. This is all handled on the client machine and then is uploaded to VideoEgg’s servers (in .flv format). I believe you can get a free license to use it. It’s definitely worth looking into.
2. I’m not sure of any Windows limitations if that’s your server environment. I’ve never run FFmpeg on a production Windows server, but it should most definitely scale if your app is designed correctly.
Thank you so much Dennis. One last query on the code that you’ve shown to run the ffmpeg command. The question I had was, did you run that on a Windows platform or on Linux? The reason I ask is because I’ve heard of people having some issuse with using IO.popen on Windows. They say it is unreliable but I’m just not 100% sure. I’m developing on Windows XP. Thanks a bunch.
Sam, all of the code mentioned here was run on Linux. I haven’t experimented much integrating RoR with FFmpeg on Windows ,so I can’t offer much advice. If I get a chance I’ll dig around with the IO api on Win.
Hey,
What is your name? I used the code on this page and I wanted to cite you but I couldn’t find your name anywhere on the site.
Dennis Baldwin….thanks.
Hi. I am using RoR on Windows. I am wondering. How to you make the command i am running do so in the background?
In your example, a controller action is run. How do I call the action while allowing other actions to be called without interrupting what is happening.
Ian,
I would recommend calling some sort of bat file (Windows) or shell script (*nix) that kicks of the ffmpeg process. Another option would be to schedule a task that checks for new videos and handles the encoding independently of your Rails app. I’ll dig into the first option some more and post my results. Best of luck.
Dennis
Hi Dennis. I have a very similar conundrum, but just far enough off so that your solution doesn’t work for me. I would like to make a call to dig in a domain management tool I am working on. For example: dig @ns1.somedomain.com example.com and display the data returned in the webpage. I tried:
def dig
@dig = `dig @ns2.example.com #{@domain.domain_name}`
end
that works in irb but not in my controller/view. I have googled for this everywhere and have come up dry. Could you give me some insight?
i’m fairly new to ruby…
any suggestions getting the below to work…
i’d like to use myfile_field.read within encodeVideo
and then self.data = Student_Interviews.flv
def encodeVideo opts #, stream
IO.popen(“ffmpeg #{opts}”, ‘w’)#{ |io| io.puts stream}
end
def myfile=(myfile_field)
if myfile_field and myfile_field.length > 0
encodeVideo “-i /tmp/Student_Interviews.mov -ar 22050 -ab 64 -f flv -s 320×240 /tmp/Student_Interviews.flv”#, myfile_field.read
#self.data = myfile_field.read
self.filename = Myfile.base_part_of(myfile_field.original_filename) + Date.to_s
filesize = (myfile_field.length / 1000).to_i
if filesize == 0
self.filesize = 1 # a file of 0 KB doesn’t make sense
else
self.filesize = filesize
end
end
end
I’m not sure what problem you’re having, but if you’re on Windows you may want to reference this link: http://wiki.rubyonrails.org/rails/pages/HowtoUploadFiles. Scroll down to the part where it says “Note for Windows” and handling binary files. I hope this helps.
I’m back! It seems that the IO.popen(….) stuff was truncating my FLVs, plus it wasn’t actually using the io.puts stream stuff.
I’ve since replaced the IO.popen stuff with a simple system() call that calls ffmpeg with my options. Viola – all is working wonderfully. I’ll keep my fingers crossed!
FLV converter provide you with all popular FLV converter, encoder,decoder and other powerful tools that you can easily deal with youtube (.flv file)