Posted on 21/10/09 by Felix Geisendörfer
I'm currently implementing /video/thumbnail functionality for transload.it and did some research on how to implement it.
First I set out to create a single thumbnail which was very easy:
ffmpeg -i intro.mov -vframes 1 -s 320x240 -ss 10 thumb.jpg
This takes a video file (-i intro.mov) and extract a single frame (-vframes 1) with 320x240px (-s 320x240) at an offset of 10 seconds (-ss 10) and saves it as thumb.jpg.
So far so good. But we actually want to offer the ability to take multiple thumbnails (like 8) in 1/8th increments of the video playtime. My initial idea was that there had to be more efficient way then calling up ffmpeg 8 times, and indeed I found one:
ffmpeg -i intro.mov -r 1/10 -s 320x240 thumb_%03d.jpg
This command works the same as the one above, except that it tries to set the frame rate to 1/10 (-r 1/10 = 1 frame every 10 seconds) and saves the results as thumb_000.jpg, thumb_001.jpg, thumb_002.jpg etc. Unfortunately I could not get it to produce the exact results I wanted. I would always end up with the first frame being captured twice, and the frame rate I set would be off by 2-3 seconds.
So I hopped to IRC and asked #ffmpeg for help. Dark_Shikari (one of the crazy people who build the best video codec in the world) was kind enough to help me.
It turns out that the offset parameter (-ss) needs to be set before the input parameter (-i). That will cause ffmpeg to seek to that position in the stream *without* decoding it and in fact skipping anything but key frames! This is pretty significant as performance improved from ~20 seconds for 4 thumbnails to about 2-3 seconds.
So my final setup is pretty much like this. First I find out the video duration by running:
This gives me all kinds of useful information including the length of the video:
ID_AUDIO_ID=0 ID_VIDEO_ID=1 ID_FILENAME=intro.mov ID_DEMUXER=mov ID_VIDEO_FORMAT=avc1 ID_VIDEO_BITRATE=0 ID_VIDEO_WIDTH=630 ID_VIDEO_HEIGHT=360 ID_VIDEO_FPS=25.000 ID_VIDEO_ASPECT=0.0000 ID_AUDIO_FORMAT=sowt ID_AUDIO_BITRATE=0 ID_AUDIO_RATE=48000 ID_AUDIO_NCH=2 ID_LENGTH=81.32 ID_VIDEO_CODEC=ffh264 ID_AUDIO_BITRATE=1536000 ID_AUDIO_RATE=48000 ID_AUDIO_NCH=2 ID_AUDIO_CODEC=pcm
I then divide the length by the amount of thumbnails I need, and run a loop like this:
ffmpeg -ss $i*$interval -i intro.mov -vframes 1 -s 320x240 thumb_$i.jpg
Where $i is the number of the thumb I'm extracting and $interval is the duration of the video divided by the amount of thumbs.
Works like a charm!
-- Felix Geisendörfer aka the_undefined
You can skip to the end and add a comment.
This post is too old. We do not allow comments here anymore in order to fight spam. If you have real feedback or questions for the post, please contact us.