Ross sent me an MD Chassis | Main | Not Dead

March 14, 2006

Creating video framegrabs from the command line

Please note, this blog has been archived and now lives at www.discretecosine.com

So, I've been hacking around with different methods for getting stills from video files via the command line. This is part of a larger project I'm working on, but I figured I'd document what I've come up with to hopefully make things easier for folks in the future.

Click the link for more...

So, first off, if you're not working on a Mac OSX / OSX Server platform, your options are pretty limited. You're pretty much guaranteed to end up using something related to ffmpeg, unless you go for commercial software.

In my case, this needs to happen via some interaction with a php script, so the easiest approach is to use the ffmpeg-php extension. This is actually a very cool extension, though it's rather fiddly to get installed right. You can get all sorts of information about a video, and extract whatever information you need.

A few downsides present themselves though. First off, ffmpeg is what we might fairly call "patent encumbered." Because nobody is paying the MPEG-LA for use of the mpeg codecs, ffmpeg is in violation of any number of patents. Now, you're fairly unlikely to be personally harmed for using it, but it's important to be aware of the legality.

Next, and more pressing, ffmpeg is terrible for doing frame grabs. You get lots of control, but it gets slower as a linear function of how far into the video you need to seek. It almost seems like it converts every frame of the video up to and including your target frame. On my 2ghz g5, it can do a grab of the first frame of a video instantly, but grabbing a frame from 10 minutes in can take up to 60 seconds. That's unacceptable. I need to poke in the code a bit more to get a better sense of why that's happening - it happens with both the CVS and stable branch, no matter how I compile it.

As best as I can tell, if you're on a non-Mac platform, that's really the only free way to do it. So let's move on to the Mac options.

First, you can use applescript (via osacript) to make Quicktime do it for you. You'll need QT Pro. This may be a good option for very low volume uses where you can monitor the display. Unfortunately, my experience with applescript and Quicktime is that things often go awry. Further, you're limited to performing one operation at a time, which is tough to do when you're deal with web access. You'd need to create a backend to do batch processing at intervals - no fun!

Next, you can use the QT_Tools software. This is a very lightweight set of applications which make calls into the Quicktime API. If you're looking to learn the Quicktime API, these are actually pretty helpful too. The source is available, but developer support is limited.

Semi-related, you should take a look at the movtoy4m software. It also uses the Quicktime API via the command line to do simple video processing. It's pretty helpful for pulling basic information. It is essentially abandoned at this point.

So that's where I'm at. I think for my solution, I'll end up using the QT_Tools route. I'm somewhat tempted to learn how to write a php extension and just code my own PHP-Quicktime ext. I get the feeling though that this wouldn't be nearly as easy as it seems. Perhaps I'll just make some very stripped down binaries I can call from within PHP.

Anyone have a fantastic option that I haven't thought of?

Posted by at March 14, 2006 6:02 PM | Tutorials

Comments

Here's the applescript, if anyone's curious. Run it from osascript with the movie as arg1 and the frame number as arg 2. A lot of this code came from Apple's QT examples.

on run argv
tell application "QuickTime Player"
activate

open item 1 of argv as POSIX file
set the current time of movie 1 to item 2 of argv as number
if not (exists movie 1) then error "No movies are open."

stop every movie


set the new_file to "image.jpg"
set AppleScript's text item delimiters to ":"
set the new_name to the last text item of (the new_file as string)
set the destination_folder to desktop & ":"
set AppleScript's text item delimiters to ""

set the current_time to current time of movie 1
select none of movie 1
copy movie 1
make new movie
paste movie 1

-- create a unique temp folder
repeat
set this_name to (random number from 100000 to 999999) as string
tell application "Finder"
if not (exists folder this_name of the desktop) then
set the temp_folder to (make new folder at desktop with properties {name:this_name}) as alias
exit repeat
end if
end tell
end repeat

set the tempfile_name to "TEMP_IMAGE"
set the target_file to ((temp_folder as string) & tempfile_name)
-- export the image as a JPEG
export movie 1 to file target_file as image sequence using settings preset "JPEG, 25 fps"

quit

end tell
end run

Posted by: Colin McFadden at March 14, 2006 11:45 PM

Very nice. If you're happy to involve Applescript, you might add iMagine Photo to your list:

A very nice piece of freeware which can also export movies. (It's essentially a scripting interface for the QuickTime graphics API.)

Posted by: Brennan Young at March 16, 2006 9:54 AM

Don't know if your found http://www.videoscript.com/
from their page - "VideoScript is free to download and use. Some extra features are available in the professional version"

it might do the things you want to do - doesn't have php integrated, but your migth be able to store things,...

Sven

Posted by: sven at March 16, 2006 9:24 PM

I'd love to see your custom quicktime-php scripts. As far as I know .. there's nothing else out there that doesn't have heavy web server deps.

Posted by: dyrek tarell at July 16, 2006 2:42 PM

I'm looking for this functionality right now, I get quicktimes from a camera ftp'd to a website, I then need to extract the 2nd frame from each quicktime via php and display it on a page. I was going to write a java command line version of the extract then call it from php, but if you have made any headway in the php integration I'd love to see it.

Posted by: grant at October 26, 2006 3:37 PM

On the subject of PHP...

I know for a fact that PHP4 is better (at least at this time) until all of the bugs are worked out of PHP5. Just like any other script, software etc. it takes time to work out all the bugs. As of right now our website contains about 800 professionally designed and written PHP scripts however even our programmers, coders know that majority of the scripts will work the best with PHP4. That is not
to say that we dont have some that will work with both however usually coding or "tweaking" them to work with both costs us too much development time.

So, for now. IMHO stick with PHP4 until all the bugs are worked out of PHP5, then

go for it.

Also, just for reference we also have some PHP scripts for posting videos (yes even in quicktime) that will stream from the users browser. Without any plugins or ffmpeg codex installed on the hosting account.

PopScript.com

Posted by: PopScript at May 18, 2007 1:50 PM

Use mplayer!!!

mplayer video.avi -vo jpeg


Try that! does a 30second decent res 40meg MOV file in about 1min on my system.
(your welcome)

Posted by: Chris Harris at August 29, 2007 7:54 AM

Unfortunately, that amount of time is exactly the problem. Mplayer and ffmpeg get linearly slower as the video gets longer. That doesn't work for a web app. I needed extraction times on the order of 1/10th of a second. So, that's why I went the custom code route...

Posted by: Colin McFadden at August 29, 2007 8:31 AM

VLC rocks for still image extraction -- cross platform, plus it jumps around instantaneously. It might not be quite as fast as your applescript, but it beats the crap out of twiddling your thumbs waiting for ffmpeg. Here's a sample command:

C:\VLC\vlc.exe -V image --image-out-format png --start-time=200 --stop-time=202 --image-out-prefix g:\rips\test\ --image-out-ratio 24 g:\rips\mr1022.mpg vlc:quit

Posted by: James at November 6, 2007 9:21 PM