Воспроизвести видео.avi с помощью GStreamer 1.0 и Python

Я искал много примеров использования библиотеки Python GStreamer в Windows, но единственные, которые хорошо работают, такие:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# GStreamer SDK Tutorials in Python
#
#     basic-tutorial-2
#
"""
basic-tutorial-2: GStreamer concepts
http://docs.gstreamer.com/display/GstSDK/Basic+tutorial+2%3A+GStreamer+concepts
"""

import sys
from gi.repository import Gst
Gst.init(None)

# Create the elements
source = Gst.ElementFactory.make("videotestsrc", "source")
sink = Gst.ElementFactory.make("autovideosink", "sink")

# Create the empty pipeline
pipeline = Gst.Pipeline.new("test-pipeline")


if not source or not sink or not pipeline:
    print("Not all elements could be created.", file=sys.stderr)
    exit(-1)

# Build the pipeline
pipeline.add(source)
pipeline.add(sink)
if not Gst.Element.link(source, sink):
    print("Elements could not be linked.", file=sys.stderr)
    exit(-1)

# Modify the source's properties
source.set_property("pattern", 0)

# Start playing
ret = pipeline.set_state(Gst.State.PLAYING)
if ret == Gst.StateChangeReturn.FAILURE:
    print("Unable to set the pipeline to the playing state.", file=sys.stderr)
    exit(-1)

# Wait until error or EOS
bus = pipeline.get_bus()
msg = bus.timed_pop_filtered(
    Gst.CLOCK_TIME_NONE, Gst.MessageType.ERROR | Gst.MessageType.EOS)

# Parse message
if (msg):
    if msg.type == Gst.MessageType.ERROR:
        err, debug = msg.parse_error()
        print("Error received from element %s: %s" % (
            msg.src.get_name(), err), file=sys.stderr)
        print("Debugging information: %s" % debug, file=sys.stderr)
    elif msg.type == Gst.MessageType.EOS:
        print("End-Of-Stream reached.")
    else:
        print("Unexpected message received.", file=sys.stderr)

# Free resources
pipeline.set_state(Gst.State.NULL)

это простой тест, использующий только "объект-приемник" или те, которые передают файл примера GStreamer (Sintel Movie Trailer), как этот:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# GStreamer SDK Tutorials in Python
#
#     basic-tutorial-4
#
"""
basic-tutorial-4: Time management
http://docs.gstreamer.com/display/GstSDK/Basic+tutorial+4%3A+Time+management
"""

import sys
from gi.repository import Gst
Gst.init(None)

# Python version of GST_TIME_ARGS


def convert_ns(t):
    s, ns = divmod(t, 1000000000)
    m, s = divmod(s, 60)

    if m < 60:
        return "0:%02i:%02i.%i" % (m, s, ns)
    else:
        h, m = divmod(m, 60)
        return "%i:%02i:%02i.%i" % (h, m, s, ns)


def handle_message(data, msg):
    if message.type == Gst.MessageType.ERROR:
        err, debug = message.parse_error()
        print("Error received from element %s: %s" % (message.src.get_name(), err), file=sys.stderr)
        print("Debugging information: %s" % debug, file=sys.stderr)
        data["terminate"] = True
    elif message.type == Gst.MessageType.EOS:
        print("End-Of-Stream reached.")
        data["terminate"] = True
    elif message.type == Gst.MessageType.DURATION_CHANGED:
        # The duration has changed, mark the current one as invalid
        data["duration"] = Gst.CLOCK_TIME_NONE
    elif message.type == Gst.MessageType.STATE_CHANGED:
        if message.src == data["playbin"]:
            old_state, new_state, pending_state = message.parse_state_changed()
            print("Pipeline state changed from %s to %s." % (old_state.value_nick, new_state.value_nick))
            data["playing"] = (new_state == Gst.State.PLAYING)
            if data["playing"]:
                query = Gst.Query.new_seeking(Gst.Format.TIME)
                if data["playbin"].query(query):
                    (aux, data["seek_enabled"], start, end) = query.parse_seeking()
                    if data["seek_enabled"]:
                        print("Seeking is ENABLED from %s to %s" % (convert_ns(start), convert_ns(end)))
                    else:
                        print("Seeking is DISABLED for this stream.")
                else:
                    print("Seeking query failed.", file=sys.stderr)
    else:
        print("Unexpected message received.", file=sys.stderr)


data = dict()

data["playing"] = False
data["terminate"] = False
data["seek_enabled"] = False
data["seek_done"] = False
data["duration"] = Gst.CLOCK_TIME_NONE

# Create the elements
data["playbin"] = Gst.ElementFactory.make("playbin", "playbin")

if not data["playbin"]:
    print("Not all elements could be created.", file=sys.stderr)
    exit(-1)

# Set the URI to play
data["playbin"].set_property(
    "uri", "http://docs.gstreamer.com/media/sintel_trailer-480p.webm")

# Start playing
ret = data["playbin"].set_state(Gst.State.PLAYING)
if ret == Gst.StateChangeReturn.FAILURE:
    print("Unable to set the pipeline to the playing state.", file=sys.stderr)
    exit(-1)

# Listen to the bus
bus = data["playbin"].get_bus()
while not data["terminate"]:
    message = bus.timed_pop_filtered(100 * Gst.MSECOND,
                                     Gst.MessageType.STATE_CHANGED | 
                                     Gst.MessageType.ERROR | 
                                     Gst.MessageType.EOS | 
                                     Gst.MessageType.DURATION_CHANGED)

    # Parse message
    if message:
        handle_message(data, message)
    else:
        if data["playing"]:
            fmt = Gst.Format.TIME
            current = -1
            # Query the current position of the stream
            _, current = data['playbin'].query_position(fmt)
            if not current:
                print("Could not query current position", file=sys.stderr)

            # If we didn't know it yet, query the stream duration
            if data["duration"] == Gst.CLOCK_TIME_NONE:
                _, data["duration"] = data['playbin'].query_duration(fmt)
                if not data["duration"]:
                    print("Could not query current duration", file=sys.stderr)

            print("Position %s / %s\r" % (
                convert_ns(current), convert_ns(data["duration"])), end=' ')
            sys.stdout.flush()

            # If seeking is enabled, we have not done it yet, and the time is
            # right, seek
            if data["seek_enabled"] and not data["seek_done"] and current > 10 * Gst.SECOND:
                print("\nReached 10s, performing seek...")
                data['playbin'].seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 30 * Gst.SECOND)
                data["seek_done"] = True


# Free resources
data["playbin"].set_state(Gst.State.NULL)

Итак, после попытки изменить код у меня есть несколько вопросов:

  1. Является ли этот "file:///C:/folder/video.avi" правильным форматом пути для GStreamer?
  2. Я знаю, что должен использовать объект "playerbin" и установить его свойство uri, но я не знаю, куда именно я должен поместить эти строки и как правильно его использовать.
  3. Есть ли проблема, связанная с форматом видео?

Спасибо большое за вашу помощь!

1 ответ

  1. Выглядит правильно, но я не могу проверить это, поскольку я использую Linux
  2. Измените строку:
    data["playbin"].set_property( "uri", "http://docs.gstreamer.com/media/sintel_trailer-480p.webm")
    в
    data["playbin"].set_property("uri", "file:///C:/folder/video.avi")
  3. Нет, все должно быть хорошо, playbin будет работать практически со всем, что вы на него бросаете.
  4. http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-plugins/html/gst-plugins-base-plugins-playbin.html
    чтобы увидеть свойства playbin, которые могут быть изменены
Другие вопросы по тегам