Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

convert a video to a sequence of frame images

I need to capture a video using a webcam and output a single image for each video frame captured.

I have tried using gstreamer with a multifilesink, e.g.:

gst-launch v4l2src device=/dev/video1 ! video/x-raw-yuv,framerate=30/1 ! ffmpegcolorspace ! pngenc ! multifilesink location="frame%d.png"

However, this does not actually output every frame, meaning that if I record for 2 seconds at 30 fps, I don't get 60 images. I'm assuming this is because the encoding can't go that fast, so I need another method.

I figured it might work if I have one pipeline capture a video, and a separate pipeline convert that video to frames, but I don't know enough about codecs. Do I need to encode the video to a file like h264 or mp4 just to then decode it again?

Does anyone have any thoughts or suggestions? Keep in mind that I need to be able to do this in code, not using an application like Adobe Premiere, for example.

Thanks!

like image 644
aptbosox Avatar asked Mar 25 '13 21:03

aptbosox


People also ask

How do I get frame by frame from a video?

Take a screenshot when the video is playing simply by pressing the Snapshot icon or pressing CTRL+ALT+S. You can use the Left or Right arrow button on the keyboard to playback the video frame by frame and save the frame in image format.


2 Answers

You could simply add a queue in there like this:

gst-launch v4l2src device=/dev/video1 ! video/x-raw-yuv,framerate=30/1 ! queue ! ffmpegcolorspace ! pngenc ! multifilesink location="frame%d.png"

This should make sure the video-capture is allowed to run at 30 fps, and then writing it to disk can happen in its own tempo. Just be aware that the queue will grow to quite a large size if you leave this setup for too long.

like image 109
Havard Graff Avatar answered Sep 22 '22 14:09

Havard Graff


the solution I have to offer doesn't use gstreamer but ffmpeg. I hope that's fine for you too.

As described in this forum post, you can use something like this:

ffmpeg -i movie.avi frame%d.png

to get a png/jpg image for each frame of the video.
But depending on the input file you use, you might have to convert it to an MPEG vid before running ffmpeg.

Note:
If you want leading zeroes in your image file names, use %05d instead (for 5-digit numbers, like in C's printf()):

ffmpeg -i movie.avi frame%05d.png

The output file format depends on the file extension, so you might use .jpg, .bmp, ... instead of .png.

like image 45
mreithub Avatar answered Sep 21 '22 14:09

mreithub