python 循环播放音乐_python gstreamer实现视频快进/快退/循环播放功能

本文介绍了如何使用Python的Gstreamer库来实现视频的快进、快退和循环播放功能,包括获取视频时长、当前播放位置以及跳转函数的详细讲解,并提供了一个实现这些功能的小播放器示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇文章主要介绍了python gstreamer 实现视频快进/快退/循环播放功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

Gstreamer到底是个啥?

GStreamer 是一个 基于pipeline的多媒体框架,基于GObject,以C语言写成。

应用GStreamer这个这个多媒体框架,你可以写出任意一种流媒体的应用来如:meidaplayer、音视频编辑器、VOIP、流媒体服务器、音视频编码等等。

关于视频快进/快退/循环播放的知识总结:

1.本地视频时长获取:

Gst.Pad.query_duration官方函数介绍:

1

2

3

4

5

6

7

8

9

10

11

12

def Gst.Pad.query_duration (self, format):

#python wrapper for 'gst_pad_query_duration'

Queries a pad for the total stream duration.

Parameters:

pad ( Gst.Pad ) –a Gst.Pad to invoke the duration query on.

format ( Gst.Format ) –the Gst.Format 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.

使用如下:

pipeline.query_duration(Gst.Format.TIME)[1]

其中pipeline为播放本地视频的管道,query_duration()函数返回一个元组,元组的形式为[Ture,duration:******],******为以ns为单位的视频时长。

2.视频播放当前位置获取:

Gst.Pad.query_position官方函数介绍:

1

2

3

4

5

6

7

8

9

10

11

12

def Gst.Pad.query_position (self, format):

#python wrapper for 'gst_pad_query_position'

Queries a pad for the stream position.

Parameters:

pad ( Gst.Pad ) –a Gst.Pad to invoke the position query on.

format ( Gst.Format ) –the Gst.Format 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.

使用方法与时长获取函数query_duration()相同。

3.播放跳转函数:

Gst.Element.seek_simple官方函数介绍:

1

2

3

4

5

6

7

8

9

10

11

def Gst.Element.seek_simple (self,format, seek_flags, seek_pos):

#python wrapper for 'gst_element_seek_simple'

Parameters:

element ( Gst.Element ) –a Gst.Element to seek on

format ( Gst.Format ) –a Gst.Format to execute the seekin, such as Gst.Format.TIME

seek_flags ( Gst.SeekFlags ) –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 seekin Gst.Format.TIME this valueis in nanoseconds- multiply with Gst.SECOND to

convert seconds to nanosecondsor with Gst.MSECOND to convert milliseconds to nanoseconds.

Returns ( gboolean ) :

TRUE (not introspectable)if the seek operation succeeded. Flushing seeks will

trigger a preroll, which will emit Gst.MessageType.ASYNC_DONE.

函数使用样例:

pipeline.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH, time)

其中time的单位为nanoseconds。

有视频快进/快退/循环播放功能的小播放器.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

import os, _thread, time

import gi

gi.require_version("Gst","1.0")

gi.require_version('Gtk','3.0')

from gi.repositoryimport Gst, GObject, Gtk, Gdk

class GTK_Main:

def __init__(self):

window= Gtk.Window(Gtk.WindowType.TOPLEVEL)

window.set_title("Vorbis-Player")

window.set_default_size(500,-1)

window.connect("destroy", Gtk.main_quit,"WM destroy")

vbox= Gtk.VBox()

window.add(vbox)

self.entry= Gtk.Entry()

vbox.pack_start(self.entry,False,False,0)

hbox= Gtk.HBox()

vbox.add(hbox)

buttonbox= Gtk.HButtonBox()

hbox.pack_start(buttonbox,False,False,0)

rewind_button= Gtk.Button("Rewind")

rewind_button.connect("clicked",self.rewind_callback)

buttonbox.add(rewind_button)

self.button= Gtk.Button("Start")

self.button.connect("clicked",self.start_stop)

buttonbox.add(self.button)

forward_button= Gtk.Button("Forward")

forward_button.connect("clicked",self.forward_callback)

buttonbox.add(forward_button)

self.time_label= Gtk.Label()

self.time_label.set_text("00:00 / 00:00")

hbox.add(self.time_label)

window.show_all()

self.player= Gst.Pipeline.new("player")

source= Gst.ElementFactory.make("filesrc","file-source")

demuxer= Gst.ElementFactory.make("decodebin","demuxer")

videoconv= Gst.ElementFactory.make("videoconvert","converter")

videosink= Gst.ElementFactory.make("xvimagesink","video-output")

demuxer.connect("pad-added",self.demuxer_callback, videoconv)

for elein [source, demuxer, videoconv, videosink]:

self.player.add(ele)

source.link(demuxer)

videoconv.link(videosink)

bus= self.player.get_bus()

bus.add_signal_watch()

bus.connect("message",self.on_message)

def start_stop(self, w):

if self.button.get_label()== "Start":

filepath= self.entry.get_text().strip()

if os.path.isfile(filepath):

filepath= os.path.realpath(filepath)

self.button.set_label("Stop")

self.player.get_by_name("file-source").set_property("location", filepath)

self.player.set_state(Gst.State.PLAYING)

self.play_thread_id= _thread.start_new_thread(self.play_thread, ())

else:

self.play_thread_id= None

self.player.set_state(Gst.State.NULL)

self.button.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:

time.sleep(0.2)

dur_int= self.player.query_duration(Gst.Format.TIME)[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

time.sleep(0.2)

while play_thread_id== self.play_thread_id:

pos_int= self.player.query_position(Gst.Format.TIME)[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()

time.sleep(1)

def on_message(self, bus, message):

t= message.type

if t== Gst.MessageType.EOS:

self.player.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH,0000000000)

elif t== Gst.MessageType.ERROR:

err, debug= message.parse_error()

print ("Error: %s" % err, debug)

self.play_thread_id= None

self.player.set_state(Gst.State.NULL)

self.button.set_label("Start")

self.time_label.set_text("00:00 / 00:00")

def demuxer_callback(self, demuxer, pad, dst):

caps= Gst.Pad.get_current_caps(pad)

structure_name= caps.to_string()

if structure_name.startswith("video"):

videorate_pad= dst.get_static_pad("sink")

pad.link(videorate_pad)

def rewind_callback(self, w):

rc, pos_int= self.player.query_position(Gst.Format.TIME)

seek_ns= pos_int- 10 * 1000000000

if seek_ns <0:

seek_ns= 0

print ('Backward: %d ns -> %d ns' % (pos_int, seek_ns))

self.player.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH, seek_ns)

def forward_callback(self, w):

rc, pos_int= self.player.query_position(Gst.Format.TIME)

seek_ns= pos_int+ 10 * 1000000000

print ('Forward: %d ns -> %d ns' % (pos_int, seek_ns))

self.player.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH, 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()

Gst.init(None)

GTK_Main()

Gtk.main()

总结

到此这篇关于python gstreamer 实现视频快进/快退/循环播放功能的文章就介绍到这了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值