记得安装pyglet 包,AVbin(http://avbin.github.io/AVbin/Download.html)

参考链接:

Pyglet教程

http://www.hawstein.com/posts/pyglet-tutorial.html

代码示例1:

  1. import pyglet
  2. from pyglet.media import *
  3. window=pyglet.window.Window()
  4. player=Player()
  5. source=load('test.mp4')
  6. player.queue(source)
  7. player.play()
  8. print(player.get_texture())
  9. @window.event
  10. def on_draw():
  11. window.clear()
  12. player.get_texture().blit(20,100)
  13.  
  14. pyglet.app.run()

代码示例2:

  1. #coding=utf-8
  2. # ----------------------------------------------------------------------------
  3. # pyglet
  4. # Copyright (c) 2006-2008 Alex Holkner
  5. # All rights reserved.
  6. #
  7. # Redistribution and use in source and binary forms, with or without
  8. # modification, are permitted provided that the following conditions
  9. # are met:
  10. #
  11. # * Redistributions of source code must retain the above copyright
  12. # notice, this list of conditions and the following disclaimer.
  13. # * Redistributions in binary form must reproduce the above copyright
  14. # notice, this list of conditions and the following disclaimer in
  15. # the documentation and/or other materials provided with the
  16. # distribution.
  17. # * Neither the name of pyglet nor the names of its
  18. # contributors may be used to endorse or promote products
  19. # derived from this software without specific prior written
  20. # permission.
  21. #
  22. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25. # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  26. # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27. # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  28. # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  30. # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  32. # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. # POSSIBILITY OF SUCH DAMAGE.
  34. # ----------------------------------------------------------------------------
  35.  
  36. '''Audio and video player with simple GUI controls.
  37. '''
  38.  
  39. __docformat__ = 'restructuredtext'
  40. __version__ = '$Id: $'
  41.  
  42. import sys
  43.  
  44. from pyglet.gl import *
  45. import pyglet
  46. from pyglet.window import key
  47.  
  48. def draw_rect(x, y, width, height):
  49. glBegin(GL_LINE_LOOP)
  50. glVertex2f(x, y)
  51. glVertex2f(x + width, y)
  52. glVertex2f(x + width, y + height)
  53. glVertex2f(x, y + height)
  54. glEnd()
  55.  
  56. class Control(pyglet.event.EventDispatcher):
  57. x = y = 0
  58. width = height = 10
  59.  
  60. def __init__(self, parent):
  61. super(Control, self).__init__()
  62. self.parent = parent
  63.  
  64. def hit_test(self, x, y):#点中控件
  65. return (self.x < x < self.x + self.width and
  66. self.y < y < self.y + self.height)
  67.  
  68. def capture_events(self):
  69. self.parent.push_handlers(self)
  70.  
  71. def release_events(self):
  72. self.parent.remove_handlers(self)
  73.  
  74. class Button(Control):
  75. charged = False
  76.  
  77. def draw(self):
  78. if self.charged:
  79. glColor3f(0, 1, 0)
  80. draw_rect(self.x, self.y, self.width, self.height)
  81. glColor3f(1, 1, 1)
  82. self.draw_label()
  83.  
  84. def on_mouse_press(self, x, y, button, modifiers):
  85. self.capture_events()
  86. self.charged = True
  87.  
  88. def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
  89. self.charged = self.hit_test(x, y)
  90.  
  91. def on_mouse_release(self, x, y, button, modifiers):
  92. self.release_events()
  93. if self.hit_test(x, y):
  94. self.dispatch_event('on_press')
  95. self.charged = False
  96.  
  97. Button.register_event_type('on_press')#注册事件
  98.  
  99. class TextButton(Button):
  100. def __init__(self, *args, **kwargs):
  101. super(TextButton, self).__init__(*args, **kwargs)
  102. self._text = pyglet.text.Label('', anchor_x='center', anchor_y='center')
  103.  
  104. def draw_label(self):
  105. self._text.x = self.x + self.width / 2
  106. self._text.y = self.y + self.height / 2
  107. self._text.draw()
  108.  
  109. def set_text(self, text):
  110. self._text.text = text
  111.  
  112. text = property(lambda self: self._text.text,
  113. set_text)
  114.  
  115. class Slider(Control):
  116. THUMB_WIDTH = 6
  117. THUMB_HEIGHT = 10
  118. GROOVE_HEIGHT = 2
  119.  
  120. def draw(self):
  121. center_y = self.y + self.height / 2
  122. draw_rect(self.x, center_y - self.GROOVE_HEIGHT / 2,
  123. self.width, self.GROOVE_HEIGHT)
  124. pos = self.x + self.value * self.width / (self.max - self.min)
  125. draw_rect(pos - self.THUMB_WIDTH / 2, center_y - self.THUMB_HEIGHT / 2,
  126. self.THUMB_WIDTH, self.THUMB_HEIGHT)
  127.  
  128. def coordinate_to_value(self, x):#改变进度
  129. return float(x - self.x) / self.width * (self.max - self.min) + self.min
  130.  
  131. def on_mouse_press(self, x, y, button, modifiers):
  132. value = self.coordinate_to_value(x)
  133. self.capture_events()
  134. self.dispatch_event('on_begin_scroll')
  135. self.dispatch_event('on_change', value)
  136.  
  137. def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
  138. value = min(max(self.coordinate_to_value(x), self.min), self.max)
  139. self.dispatch_event('on_change', value)
  140.  
  141. def on_mouse_release(self, x, y, button, modifiers):
  142. self.release_events()
  143. self.dispatch_event('on_end_scroll')
  144.  
  145. Slider.register_event_type('on_begin_scroll')
  146. Slider.register_event_type('on_end_scroll')
  147. Slider.register_event_type('on_change')
  148.  
  149. class PlayerWindow(pyglet.window.Window):
  150. GUI_WIDTH = 400
  151. GUI_HEIGHT = 40
  152. GUI_PADDING = 4#按钮间隔
  153. GUI_BUTTON_HEIGHT = 16
  154.  
  155. def __init__(self, player):
  156. super(PlayerWindow, self).__init__(caption='Media Player',
  157. visible=False,
  158. resizable=True)
  159. self.player = player
  160. self.player.push_handlers(self)
  161. self.player.eos_action = self.player.EOS_PAUSE
  162.  
  163. self.slider = Slider(self)
  164. self.slider.x = self.GUI_PADDING#类变量
  165. self.slider.y = self.GUI_PADDING * 2 + self.GUI_BUTTON_HEIGHT
  166. self.slider.on_begin_scroll = lambda: player.pause()
  167. self.slider.on_end_scroll = lambda: player.play()
  168. self.slider.on_change = lambda value: player.seek(value)
  169.  
  170. self.play_pause_button = TextButton(self)
  171. self.play_pause_button.x = self.GUI_PADDING
  172. self.play_pause_button.y = self.GUI_PADDING
  173. self.play_pause_button.height = self.GUI_BUTTON_HEIGHT
  174. self.play_pause_button.width = 45
  175. self.play_pause_button.on_press = self.on_play_pause
  176.  
  177. win = self#自有妙用
  178. self.window_button = TextButton(self)
  179. self.window_button.x = self.play_pause_button.x + \
  180. self.play_pause_button.width + self.GUI_PADDING
  181. self.window_button.y = self.GUI_PADDING
  182. self.window_button.height = self.GUI_BUTTON_HEIGHT
  183. self.window_button.width = 90
  184. self.window_button.text = 'Windowed'
  185. self.window_button.on_press = lambda: win.set_fullscreen(False)#注意不能写self
  186.  
  187. self.controls = [
  188. self.slider,
  189. self.play_pause_button,
  190. self.window_button,
  191. ]
  192.  
  193. x = self.window_button.x + self.window_button.width + self.GUI_PADDING
  194. i = 0
  195. for screen in self.display.get_screens():
  196. screen_button = TextButton(self)
  197. screen_button.x = x
  198. screen_button.y = self.GUI_PADDING
  199. screen_button.height = self.GUI_BUTTON_HEIGHT
  200. screen_button.width = 80
  201. screen_button.text = 'Screen %d' % (i + 1)
  202. screen_button.on_press = \
  203. (lambda s: lambda: win.set_fullscreen(True, screen=s))(screen)
  204. self.controls.append(screen_button)
  205. i += 1
  206. x += screen_button.width + self.GUI_PADDING
  207.  
  208. def on_eos(self):
  209. self.gui_update_state()
  210.  
  211. def gui_update_source(self):
  212. if self.player.source:
  213. source = self.player.source
  214. self.slider.min = 0.
  215. self.slider.max = source.duration
  216. self.gui_update_state()
  217.  
  218. def gui_update_state(self):
  219. if self.player.playing:
  220. self.play_pause_button.text = 'Pause'
  221. else:
  222. self.play_pause_button.text = 'Play'
  223.  
  224. def get_video_size(self):
  225. if not self.player.source or not self.player.source.video_format:
  226. return 0, 0
  227. video_format = self.player.source.video_format
  228. width = video_format.width
  229. height = video_format.height
  230. if video_format.sample_aspect > 1:
  231. width *= video_format.sample_aspect
  232. elif video_format.sample_aspect < 1:
  233. height /= video_format.sample_aspect
  234. return width, height
  235.  
  236. def set_default_video_size(self):
  237. '''Make the window size just big enough to show the current
  238. video and the GUI.'''
  239. width = self.GUI_WIDTH
  240. height = self.GUI_HEIGHT
  241. video_width, video_height = self.get_video_size()
  242. width = max(width, video_width)
  243. height += video_height
  244. self.set_size(int(width), int(height))
  245.  
  246. def on_resize(self, width, height):
  247. '''Position and size video image.'''
  248. super(PlayerWindow, self).on_resize(width, height)
  249.  
  250. self.slider.width = width - self.GUI_PADDING * 2
  251.  
  252. height -= self.GUI_HEIGHT
  253. if height <= 0:
  254. return
  255.  
  256. video_width, video_height = self.get_video_size()
  257. if video_width == 0 or video_height == 0:
  258. return
  259.  
  260. display_aspect = width / float(height)
  261. video_aspect = video_width / float(video_height)
  262. if video_aspect > display_aspect:
  263. self.video_width = width
  264. self.video_height = width / video_aspect
  265. else:
  266. self.video_height = height
  267. self.video_width = height * video_aspect
  268. self.video_x = (width - self.video_width) / 2
  269. self.video_y = (height - self.video_height) / 2 + self.GUI_HEIGHT
  270.  
  271. def on_mouse_press(self, x, y, button, modifiers):
  272. for control in self.controls:
  273. if control.hit_test(x, y):
  274. control.on_mouse_press(x, y, button, modifiers)
  275.  
  276. def on_key_press(self, symbol, modifiers):
  277. if symbol == key.SPACE:
  278. self.on_play_pause()
  279. elif symbol == key.ESCAPE:
  280. self.dispatch_event('on_close')
  281.  
  282. def on_close(self):
  283. self.player.pause()
  284. self.close()
  285.  
  286. def on_play_pause(self):
  287. if self.player.playing:
  288. self.player.pause()
  289. else:
  290. if self.player.time >= self.player.source.duration:#如果放完了
  291. self.player.seek(0)
  292. self.player.play()
  293. self.gui_update_state()
  294.  
  295. def on_draw(self):
  296. self.clear()
  297.  
  298. # Video
  299. if self.player.source and self.player.source.video_format:
  300. self.player.get_texture().blit(self.video_x,
  301. self.video_y,
  302. width=self.video_width,
  303. height=self.video_height)
  304.  
  305. # GUI
  306. self.slider.value = self.player.time
  307. for control in self.controls:
  308. control.draw()
  309.  
  310. if __name__ == '__main__':
  311. if len(sys.argv) < 2:
  312. print 'Usage: media_player.py <filename> [<filename> ...]'
  313. sys.exit(1)
  314.  
  315. for filename in sys.argv[1:]:
  316. player = pyglet.media.Player()
  317. window = PlayerWindow(player)
  318.  
  319. source = pyglet.media.load(filename)
  320. player.queue(source)
  321.  
  322. window.gui_update_source()
  323. window.set_default_video_size()
  324. window.set_size(400,400)
  325. window.set_visible(True)
  326.  
  327. window.gui_update_state()
  328. player.play()
  329.  
  330. pyglet.app.run()

python + Pyglet ---播放视频的更多相关文章

  1. 用Python实现检测视频真伪?

    译者注:本文以一段自打24小时耳光的视频为例子,介绍了如何利用均值哈希算法来检查重复视频帧.以下是译文. 有人在网上上传了一段视频,他打了自己24个小时的耳光.他真的这么做了吗?看都不用看,肯定没有! ...

  2. 利用PyQt GUI显示图片、实时播放视频

    ---作者吴疆,未经允许,严禁转载,违权必究--- ---欢迎指正,需要源码和文件可站内私信联系--- -----------点击此处链接至博客园原文----------- 功能说明:PyQt界面程序 ...

  3. Python爬取视频指南

    摘自:https://www.jianshu.com/p/9ca86becd86d 前言 前两天尔羽说让我爬一下菜鸟窝的教程视频,这次就跟大家来说说Python爬取视频的经验 正文 https://w ...

  4. 嵌入式 vlc从接收到数据流到播放视频的过程分析(经典)

    个人整理: Vlc流播放流程 vlc源码目录树: 目录名称 说明 bindings Java, CIL 和Python绑定 doc 帮助文档 (不是更新的) extras 另叙. include VL ...

  5. AVAssetReader+AVAssetReaderTrackOutput播放视频

    该文章引用自:http://www.jianshu.com/p/3d5ccbde0de1 IOS 微信聊天发送小视频的秘密(AVAssetReader+AVAssetReaderTrackOutput ...

  6. Android实现播放视频

    转载:http://www.bdqn.cn/news/201311/12100.shtml 使用VideoView播放视频 VideoView,用于播放一段视频媒体,它继承了SurfaceView,位 ...

  7. Android使用TextureView播放视频

    1.引言 如果你想显示一段在线视频或者任意的数据流比如视频或者OpenGL 场景,你可以用android中的TextureView做到. 1).TextureView的兄弟SurfaceView 应用 ...

  8. WPF播放视频

    在现在的项目中需要使用到播放视频的功能,本来打算使用VLC来做的.后来发现WPF 4.0之后新增了MediaElement类,可以实现视频播放. <Grid> <Grid.RowDe ...

  9. Cocos2dx3.11.1Android播放视频,后台 黑屏,无法记忆播放bug修改

    /* * Copyright (C) 2006 The Android Open Source Project * Copyright (c) 2014 Chukong Technologies In ...

随机推荐

  1. Windows 10 共享需要网络凭据的问题

    如果Windows在资源管理器的网络中双击其他的网络设备,提示要输入网络凭据的解决办法: 打开"网络共享中心" -> "更改高级共享设置"->&qu ...

  2. vuecli3.0 webpack4 配置vuex

    废话不说,直接写步骤 1. npm install vux --save 2. npm install less less-loader --save-dev 3. npm install @vux/ ...

  3. Leetcode题目160.相交链表(简单)

    题目描述 编写一个程序,找到两个单链表相交的起始节点. 如下面的两个链表: 在节点 c1 开始相交. 输入:intersectVal = 8, listA = [4,1,8,4,5], listB = ...

  4. vue-图片预览,查看大图

    [前言] 在 vue 项目中经常碰到图片预览需求,也就是点击小图查看大图.也有一些这样的第三方插件,如 vue-preview 等.但使用起来感觉版本经常变,而且有时 UI 需要在预览页面上加更多的东 ...

  5. 9Patch图

    NinePatch是一种很有用的PNG图片格式,它可以在特定区域随文字大小进行缩放. - 上边线控制水平拉伸- 左边线控制竖直拉伸- 右边线和下边线控制内容区域 如下: 背景图片的中间区域会随着文字的 ...

  6. monkey 查找闪退页面的方法

    使用了命令 adb shell monkey  --pct-touch 100 -v -p  com.iBer.iBerAppV2  5000 >/Users/kaibinliu/Desktop ...

  7. [Kaggle] How to handle big data?

    上一篇,[Kaggle] How to kaggle?[方法导论] 这里再做一点进阶学习. 写在前面 "行业特征" 的重要性 Ref: Kaggle2017—1百万美金的肺癌检测竞 ...

  8. 【转】ffluos编译

    FluffOS是在MUDOS基础上更新完成的.进行了许多新功能和bug修复. 针对LPC有很好的兼容性,如果你的MUD运行MUDOS V22+版本,可以很容易运行在fluffos上. 系统环境: Cn ...

  9. WMPageController设置menuView的左右视图

    效果图如下: 绿色的是自定义的emenuView的rightView哟!!! 代码实现如下: // // CategoryVC.m // JSHui // // Created by Apple on ...

  10. k8s 工具集

    Volcano 资源调度器 apollo 配置中心 spinnaker 持续部署系统 jaeger 分布式跟踪系统.它用于监视和诊断基于微服务的分布式系统,包括: 分布式上下文传播 分布式交易监控 根 ...