What is Gstreamer?
GStreamer is a pipeline-based multimedia framework written in C language based on GObject.
By applying GStreamer, the multimedia framework, you can write any kind of streaming applications such as: meidaplayer, audio and video editor, VOIP, streaming media server, audio and video encoding, etc.
Summary of knowledge about fast forward/fast rewind/loop playback of videos:
1. Obtain the local video duration:
Introduction to the official function of .query_duration:
def .query_duration (self, format): #python wrapper for 'gst_pad_query_duration' Queries a pad for the total stream duration. Parameters: pad ( ) –a to invoke the duration query on. format ( ) –the requested Returns a tuple made of: ( gboolean ) –TRUE (not introspectable) if the query could be performed. duration ( gint64 ) –TRUE (not introspectable) if the query could be performed.
Use as follows:
pipeline.query_duration()[1]
Where pipeline is the pipeline for playing local videos, the query_duration() function returns a tuple, the form of the tuple is [Ture,duration:******], and ******* is the video duration in units of ns.
2. Get the current location of the video playback:
Introduction to the official function of .query_position:
def .query_position (self, format): #python wrapper for 'gst_pad_query_position' Queries a pad for the stream position. Parameters: pad ( ) –a to invoke the position query on. format ( ) –the requested Returns a tuple made of: ( gboolean ) –TRUE (not introspectable) if the query could be performed. cur ( gint64 ) –TRUE (not introspectable) if the query could be performed.
Use method and duration to get functionquery_duration()
same.
3. Play the jump function:
.seek_simple official function introduction:
def .seek_simple (self, format, seek_flags, seek_pos): #python wrapper for 'gst_element_seek_simple' Parameters: element ( ) –a to seek on format ( ) –a to execute the seek in, such as seek_flags ( ) –seek options; playback applications will usually want to use GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT here seek_pos ( gint64 ) –position to seek to (relative to the start); if you are doing a seek in this value is in nanoseconds - multiply with to convert seconds to nanoseconds or with to convert milliseconds to nanoseconds. Returns ( gboolean ) : TRUE (not introspectable) if the seek operation succeeded. Flushing seeks will trigger a preroll, which will emit .ASYNC_DONE.
Function usage example:
pipeline.seek_simple(, , time)
The unit of time is nanoseconds.
A small player with video fast forward/fast backward/loop playback functions.
import os, _thread, time import gi gi.require_version("Gst", "1.0") gi.require_version('Gtk', '3.0') from import Gst, GObject, Gtk, Gdk class GTK_Main: def __init__(self): window = () window.set_title("Vorbis-Player") window.set_default_size(500, -1) ("destroy", Gtk.main_quit, "WM destroy") vbox = () (vbox) = () vbox.pack_start(, False, False, 0) hbox = () (hbox) buttonbox = () hbox.pack_start(buttonbox, False, False, 0) rewind_button = ("Rewind") rewind_button.connect("clicked", self.rewind_callback) (rewind_button) = ("Start") ("clicked", self.start_stop) () forward_button = ("Forward") forward_button.connect("clicked", self.forward_callback) (forward_button) self.time_label = () self.time_label.set_text("00:00 / 00:00") (self.time_label) window.show_all() = ("player") source = ("filesrc", "file-source") demuxer = ("decodebin", "demuxer") videoconv = ("videoconvert", "converter") videosink = ("xvimagesink", "video-output") ("pad-added", self.demuxer_callback, videoconv) for ele in [source, demuxer, videoconv, videosink]: (ele) (demuxer) (videosink) bus = .get_bus() bus.add_signal_watch() ("message", self.on_message) def start_stop(self, w): if .get_label() == "Start": filepath = .get_text().strip() if (filepath): filepath = (filepath) .set_label("Stop") .get_by_name("file-source").set_property("location", filepath) .set_state() self.play_thread_id = _thread.start_new_thread(self.play_thread, ()) else: self.play_thread_id = None .set_state() .set_label("Start") self.time_label.set_text("00:00 / 00:00") def play_thread(self): play_thread_id = self.play_thread_id Gdk.threads_enter() self.time_label.set_text("00:00 / 00:00") Gdk.threads_leave() print(play_thread_id) print(self.play_thread_id) while play_thread_id == self.play_thread_id: (0.2) dur_int = .query_duration()[1] if dur_int == -1: continue dur_str = self.convert_ns(dur_int) Gdk.threads_enter() self.time_label.set_text("00:00 / " + dur_str) Gdk.threads_leave() break (0.2) while play_thread_id == self.play_thread_id: pos_int = .query_position()[1] pos_str = self.convert_ns(pos_int) if play_thread_id == self.play_thread_id: Gdk.threads_enter() self.time_label.set_text(pos_str + " / " + dur_str) Gdk.threads_leave() (1) def on_message(self, bus, message): t = if t == : .seek_simple(, , 0000000000) elif t == : err, debug = message.parse_error() print ("Error: %s" % err, debug) self.play_thread_id = None .set_state() .set_label("Start") self.time_label.set_text("00:00 / 00:00") def demuxer_callback(self, demuxer, pad, dst): caps = .get_current_caps(pad) structure_name = caps.to_string() if structure_name.startswith("video"): videorate_pad = dst.get_static_pad("sink") (videorate_pad) def rewind_callback(self, w): rc, pos_int = .query_position() seek_ns = pos_int - 10 * 1000000000 if seek_ns < 0: seek_ns = 0 print ('Backward: %d ns -> %d ns' % (pos_int, seek_ns)) .seek_simple(, , seek_ns) def forward_callback(self, w): rc, pos_int = .query_position() seek_ns = pos_int + 10 * 1000000000 print ('Forward: %d ns -> %d ns' % (pos_int, seek_ns)) .seek_simple(, , seek_ns) def convert_ns(self, t): s,ns = divmod(t, 1000000000) m,s = divmod(s, 60) if m < 60: return "%02i:%02i" %(m,s) else: h,m = divmod(m, 60) return "%i:%02i:%02i" %(h,m,s) GObject.threads_init() (None) GTK_Main() ()
Summarize
This is the article about python gstreamer implementing video fast forward/fast reversal/loop playback functions. For more related python gstreamer implementing video fast forward/fast reversal/loop playback content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!