Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create video thumbnails with Python and Gstreamer

I'd like to create thumbnails for MPEG-4 AVC videos using Gstreamer and Python. Essentially:

  1. Open the video file
  2. Seek to a certain point in time (e.g. 5 seconds)
  3. Grab the frame at that time
  4. Save the frame to disc as a .jpg file

I've been looking at this other similar question, but I cannot quite figure out how to do the seek and frame capture automatically without user input.

So in summary, how can I capture a video thumbnail with Gstreamer and Python as per the steps above?

like image 666
David Planella Avatar asked Apr 03 '13 14:04

David Planella


People also ask

How do I create a thumbnail from a video in Python?

You can use ffmpeg-python to create a thumbnail and upload it for use with your video. If you don't want to get into learning FFMPEG, you can also use api. video's endpoint that allows you to pick a time from the video, and have it set as the video thumbnail for you automatically.

How do I create a thumbnail image in Python?

One way to achieve this, is by creating a thumbnail of all images using the thumbnail() function from pillow library. This method modifies the image to contain a thumbnail version of itself and the size of the image will be no larger than the given size.

How video thumbnails are created?

Making a video thumbnail is relatively straightforward. You can take a screenshot from your video that best explains its contents, or you can use a tool like Photoshop or Canva to overlay text or icons on the image. To make a screen capture on a PC, use the Windows Snipping Tool.


2 Answers

An example in Vala, with GStreamer 1.0 :

var playbin = Gst.ElementFactory.make ("playbin", null);
playbin.set ("uri", "file:///path/to/file");
// some code here.
var caps = Gst.Caps.from_string("image/png");
Gst.Sample sample;
Signal.emit_by_name(playbin, "convert-sample", caps, out sample);
if(sample == null)
    return;
var sample_caps = sample.get_caps ();
if(sample_caps == null)
    return;
unowned Gst.Structure structure = sample_caps.get_structure(0);
int width = (int)structure.get_value ("width");
int height = (int)structure.get_value ("height");
var memory = sample.get_buffer().get_memory (0);
Gst.MapInfo info;
memory.map (out info, Gst.MapFlags.READ);
uint8[] data = info.data;
like image 91
yannick inizan Avatar answered Oct 20 '22 11:10

yannick inizan


To elaborate on ensonic's answer, here's an example:

import os
import sys

import gst

def get_frame(path, offset=5, caps=gst.Caps('image/png')):
    pipeline = gst.parse_launch('playbin2')
    pipeline.props.uri = 'file://' + os.path.abspath(path)
    pipeline.props.audio_sink = gst.element_factory_make('fakesink')
    pipeline.props.video_sink = gst.element_factory_make('fakesink')
    pipeline.set_state(gst.STATE_PAUSED)
    # Wait for state change to finish.
    pipeline.get_state()
    assert pipeline.seek_simple(
        gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH, offset * gst.SECOND)
    # Wait for seek to finish.
    pipeline.get_state()
    buffer = pipeline.emit('convert-frame', caps)
    pipeline.set_state(gst.STATE_NULL)
    return buffer

def main():
    buf = get_frame(sys.argv[1])

    with file('frame.png', 'w') as fh:
        fh.write(str(buf))

if __name__ == '__main__':
    main()

This generates a PNG image. You can get raw image data using gst.Caps("video/x-raw-rgb,bpp=24,depth=24") or something like that.

Note that in GStreamer 1.0 (as opposed to 0.10), playbin2 has been renamed to playbin and the convert-frame signal is named convert-sample.

The mechanics of seeking are explained in this chapter of the GStreamer Application Development Manual. The 0.10 playbin2 documentation no longer seems to be online, but the documentation for 1.0 is here.

like image 8
daf Avatar answered Oct 20 '22 10:10

daf