ホームページ バックエンド開発 Python チュートリアル Pythonで実装されたビデオプレーヤー機能

Pythonで実装されたビデオプレーヤー機能

Jun 01, 2018 pm 04:33 PM
python 関数 プレーヤー

この記事では、主に Python で実装されたビデオ プレーヤー関数を紹介し、pyglet ライブラリに基づいて Python の関連操作スキルを分析して、完全な例の形式でビデオ再生関数を実装します。この記事の例では、Python プレーヤー関数で実装されたビデオについて説明します。参考のために、次のようにみんなと共有してください:

# -*- coding:utf-8 -*-
#! python3
# ----------------------------------------------------------------------------
# pyglet
# Copyright (c) 2006-2008 Alex Holkner
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions 
# are met:
#
# * Redistributions of source code must retain the above copyright
#  notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright 
#  notice, this list of conditions and the following disclaimer in
#  the documentation and/or other materials provided with the
#  distribution.
# * Neither the name of pyglet nor the names of its
#  contributors may be used to endorse or promote products
#  derived from this software without specific prior written
#  permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ----------------------------------------------------------------------------
'''Audio and video player with simple GUI controls.
'''
__docformat__ = 'restructuredtext'
__version__ = '$Id: $'
import sys
from pyglet.gl import *
import pyglet
from pyglet.window import key
def draw_rect(x, y, width, height):
  glBegin(GL_LINE_LOOP)
  glVertex2f(x, y)
  glVertex2f(x + width, y)
  glVertex2f(x + width, y + height)
  glVertex2f(x, y + height)
  glEnd()
class Control(pyglet.event.EventDispatcher):
  x = y = 0
  width = height = 10
  def __init__(self, parent):
    super(Control, self).__init__()
    self.parent = parent
  def hit_test(self, x, y):#点中控件
    return (self.x < x < self.x + self.width and 
        self.y < y < self.y + self.height)
  def capture_events(self):
    self.parent.push_handlers(self)
  def release_events(self):
    self.parent.remove_handlers(self)
class Button(Control):
  charged = False
  def draw(self):
    if self.charged:
      glColor3f(0, 1, 0)
    draw_rect(self.x, self.y, self.width, self.height)
    glColor3f(1, 1, 1)
    self.draw_label()
  def on_mouse_press(self, x, y, button, modifiers):
    self.capture_events()
    self.charged = True
  def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
    self.charged = self.hit_test(x, y)
  def on_mouse_release(self, x, y, button, modifiers):
    self.release_events()
    if self.hit_test(x, y):
      self.dispatch_event(&#39;on_press&#39;)
    self.charged = False
Button.register_event_type(&#39;on_press&#39;)#注册事件
class TextButton(Button):
  def __init__(self, *args, **kwargs):
    super(TextButton, self).__init__(*args, **kwargs)
    self._text = pyglet.text.Label(&#39;&#39;, anchor_x=&#39;center&#39;, anchor_y=&#39;center&#39;)
  def draw_label(self):
    self._text.x = self.x + self.width / 2
    self._text.y = self.y + self.height / 2
    self._text.draw()
  def set_text(self, text):
    self._text.text = text
  text = property(lambda self: self._text.text,
          set_text)
class Slider(Control):
  THUMB_WIDTH = 6
  THUMB_HEIGHT = 10
  GROOVE_HEIGHT = 2
  def draw(self):
    center_y = self.y + self.height / 2
    draw_rect(self.x, center_y - self.GROOVE_HEIGHT / 2, 
         self.width, self.GROOVE_HEIGHT)
    pos = self.x + self.value * self.width / (self.max - self.min)
    draw_rect(pos - self.THUMB_WIDTH / 2, center_y - self.THUMB_HEIGHT / 2, 
         self.THUMB_WIDTH, self.THUMB_HEIGHT)
  def coordinate_to_value(self, x):#改变进度
    return float(x - self.x) / self.width * (self.max - self.min) + self.min
  def on_mouse_press(self, x, y, button, modifiers):
    value = self.coordinate_to_value(x)
    self.capture_events()
    self.dispatch_event(&#39;on_begin_scroll&#39;)
    self.dispatch_event(&#39;on_change&#39;, value)
  def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
    value = min(max(self.coordinate_to_value(x), self.min), self.max)
    self.dispatch_event(&#39;on_change&#39;, value)
  def on_mouse_release(self, x, y, button, modifiers):
    self.release_events()
    self.dispatch_event(&#39;on_end_scroll&#39;)
Slider.register_event_type(&#39;on_begin_scroll&#39;)
Slider.register_event_type(&#39;on_end_scroll&#39;)
Slider.register_event_type(&#39;on_change&#39;)
class PlayerWindow(pyglet.window.Window):
  GUI_WIDTH = 400
  GUI_HEIGHT = 40
  GUI_PADDING = 4#按钮间隔
  GUI_BUTTON_HEIGHT = 16
  def __init__(self, player):
    super(PlayerWindow, self).__init__(caption=&#39;Media Player&#39;,
                      visible=False, 
                      resizable=True)
    self.player = player
    self.player.push_handlers(self)
    self.player.eos_action = self.player.EOS_PAUSE
    self.slider = Slider(self)
    self.slider.x = self.GUI_PADDING#类变量
    self.slider.y = self.GUI_PADDING * 2 + self.GUI_BUTTON_HEIGHT
    self.slider.on_begin_scroll = lambda: player.pause()
    self.slider.on_end_scroll = lambda: player.play()
    self.slider.on_change = lambda value: player.seek(value)
    self.play_pause_button = TextButton(self)
    self.play_pause_button.x = self.GUI_PADDING
    self.play_pause_button.y = self.GUI_PADDING
    self.play_pause_button.height = self.GUI_BUTTON_HEIGHT
    self.play_pause_button.width = 45
    self.play_pause_button.on_press = self.on_play_pause
    win = self#自有妙用
    self.window_button = TextButton(self)
    self.window_button.x = self.play_pause_button.x + \
                self.play_pause_button.width + self.GUI_PADDING
    self.window_button.y = self.GUI_PADDING
    self.window_button.height = self.GUI_BUTTON_HEIGHT
    self.window_button.width = 90
    self.window_button.text = &#39;Windowed&#39;
    self.window_button.on_press = lambda: win.set_fullscreen(False)#注意不能写self
    self.controls = [
      self.slider, 
      self.play_pause_button,
      self.window_button,
    ]
    x = self.window_button.x + self.window_button.width + self.GUI_PADDING
    i = 0
    for screen in self.display.get_screens():
      screen_button = TextButton(self)
      screen_button.x = x
      screen_button.y = self.GUI_PADDING
      screen_button.height = self.GUI_BUTTON_HEIGHT
      screen_button.width = 80
      screen_button.text = &#39;Screen %d&#39; % (i + 1)
      screen_button.on_press = \
        (lambda s: lambda: win.set_fullscreen(True, screen=s))(screen)
      self.controls.append(screen_button)
      i += 1
      x += screen_button.width + self.GUI_PADDING
  def on_eos(self):
    self.gui_update_state()
  def gui_update_source(self):
    if self.player.source:
      source = self.player.source
      self.slider.min = 0.
      self.slider.max = source.duration
    self.gui_update_state()
  def gui_update_state(self):
    if self.player.playing:
      self.play_pause_button.text = &#39;Pause&#39;
    else:
      self.play_pause_button.text = &#39;Play&#39;
  def get_video_size(self):
    if not self.player.source or not self.player.source.video_format:
      return 0, 0
    video_format = self.player.source.video_format
    width = video_format.width
    height = video_format.height
    if video_format.sample_aspect > 1:
      width *= video_format.sample_aspect
    elif video_format.sample_aspect < 1:
      height /= video_format.sample_aspect
    return width, height
  def set_default_video_size(self):
    &#39;&#39;&#39;Make the window size just big enough to show the current
    video and the GUI.&#39;&#39;&#39;
    width = self.GUI_WIDTH
    height = self.GUI_HEIGHT
    video_width, video_height = self.get_video_size()
    width = max(width, video_width)
    height += video_height
    self.set_size(int(width), int(height))
  def on_resize(self, width, height):
    &#39;&#39;&#39;Position and size video image.&#39;&#39;&#39;
    super(PlayerWindow, self).on_resize(width, height)
    self.slider.width = width - self.GUI_PADDING * 2
    height -= self.GUI_HEIGHT
    if height <= 0:
      return
    video_width, video_height = self.get_video_size()
    if video_width == 0 or video_height == 0:
      return
    display_aspect = width / float(height)
    video_aspect = video_width / float(video_height)
    if video_aspect > display_aspect:
      self.video_width = width
      self.video_height = width / video_aspect
    else:
      self.video_height = height
      self.video_width = height * video_aspect
    self.video_x = (width - self.video_width) / 2
    self.video_y = (height - self.video_height) / 2 + self.GUI_HEIGHT
  def on_mouse_press(self, x, y, button, modifiers):
    for control in self.controls:
      if control.hit_test(x, y):
        control.on_mouse_press(x, y, button, modifiers)
  def on_key_press(self, symbol, modifiers):
    if symbol == key.SPACE:
      self.on_play_pause()
    elif symbol == key.ESCAPE:
      self.dispatch_event(&#39;on_close&#39;)
  def on_close(self):
    self.player.pause()
    self.close()
  def on_play_pause(self):
    if self.player.playing:
      self.player.pause()
    else:
      if self.player.time >= self.player.source.duration:#如果放完了
        self.player.seek(0)
      self.player.play()
    self.gui_update_state()
  def on_draw(self):
    self.clear()
    # Video
    if self.player.source and self.player.source.video_format:
      self.player.get_texture().blit(self.video_x,
                      self.video_y,
                      width=self.video_width,
                      height=self.video_height)
    # GUI
    self.slider.value = self.player.time
    for control in self.controls:
      control.draw()
if __name__ == &#39;__main__&#39;:
  if len(sys.argv) < 2:
    print(&#39;Usage: media_player.py <filename> [<filename> ...]&#39;)
    sys.exit(1)
  for filename in sys.argv[1:]:
    player = pyglet.media.Player()
    window = PlayerWindow(player)
    source = pyglet.media.load(filename)
    player.queue(source)
    window.gui_update_source()
    window.set_default_video_size()
    window.set_size(400,400)
    window.set_visible(True)
    window.gui_update_state()
    player.play()
  pyglet.app.run()
ログイン後にコピー

関連する推奨事項:


Pythonを使用してビデオダウンロード関数のサンプルコードを実装する



以上がPythonで実装されたビデオプレーヤー機能の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

mysqlは支払う必要がありますか mysqlは支払う必要がありますか Apr 08, 2025 pm 05:36 PM

MySQLには、無料のコミュニティバージョンと有料エンタープライズバージョンがあります。コミュニティバージョンは無料で使用および変更できますが、サポートは制限されており、安定性要件が低く、技術的な能力が強いアプリケーションに適しています。 Enterprise Editionは、安定した信頼性の高い高性能データベースを必要とするアプリケーションに対する包括的な商業サポートを提供し、サポートの支払いを喜んでいます。バージョンを選択する際に考慮される要因には、アプリケーションの重要性、予算編成、技術スキルが含まれます。完璧なオプションはなく、最も適切なオプションのみであり、特定の状況に応じて慎重に選択する必要があります。

hadidb:pythonの軽量で水平方向にスケーラブルなデータベース hadidb:pythonの軽量で水平方向にスケーラブルなデータベース Apr 08, 2025 pm 06:12 PM

hadidb:軽量で高レベルのスケーラブルなPythonデータベースHadIDB(HadIDB)は、Pythonで記述された軽量データベースで、スケーラビリティが高くなっています。 PIPインストールを使用してHADIDBをインストールする:PIPINSTALLHADIDBユーザー管理CREATEユーザー:CREATEUSER()メソッド新しいユーザーを作成します。 Authentication()メソッドは、ユーザーのIDを認証します。 fromhadidb.operationimportuseruser_obj = user( "admin"、 "admin")user_obj。

MySQLワークベンチはMariadBに接続できますか MySQLワークベンチはMariadBに接続できますか Apr 08, 2025 pm 02:33 PM

MySQLワークベンチは、構成が正しい場合、MariadBに接続できます。最初にコネクタタイプとして「mariadb」を選択します。接続構成では、ホスト、ポート、ユーザー、パスワード、およびデータベースを正しく設定します。接続をテストするときは、ユーザー名とパスワードが正しいかどうか、ポート番号が正しいかどうか、ファイアウォールが接続を許可するかどうか、データベースが存在するかどうか、MariadBサービスが開始されていることを確認してください。高度な使用法では、接続プーリングテクノロジーを使用してパフォーマンスを最適化します。一般的なエラーには、不十分な権限、ネットワーク接続の問題などが含まれます。エラーをデバッグするときは、エラー情報を慎重に分析し、デバッグツールを使用します。ネットワーク構成を最適化すると、パフォーマンスが向上する可能性があります

MongoDBデータベースパスワードを表示するNAVICATの方法 MongoDBデータベースパスワードを表示するNAVICATの方法 Apr 08, 2025 pm 09:39 PM

Hash値として保存されているため、Navicatを介してMongoDBパスワードを直接表示することは不可能です。紛失したパスワードを取得する方法:1。パスワードのリセット。 2。構成ファイルを確認します(ハッシュ値が含まれる場合があります)。 3.コードを確認します(パスワードをハードコードできます)。

MySQLを解く方法は、ローカルホストに接続できません MySQLを解く方法は、ローカルホストに接続できません Apr 08, 2025 pm 02:24 PM

MySQL接続は、次の理由が原因である可能性があります。MySQLサービスは開始されず、ファイアウォールは接続をインターセプトし、ポート番号が間違っています。ユーザー名またはパスワードが間違っています。My.cnfのリスニングアドレスは不適切に構成されています。トラブルシューティング手順には以下が含まれます。 2.ファイアウォール設定を調整して、MySQLがポート3306をリッスンできるようにします。 3.ポート番号が実際のポート番号と一致していることを確認します。 4.ユーザー名とパスワードが正しいかどうかを確認します。 5. my.cnfのバインドアドレス設定が正しいことを確認してください。

mysqlはインターネットが必要ですか? mysqlはインターネットが必要ですか? Apr 08, 2025 pm 02:18 PM

MySQLは、基本的なデータストレージと管理のためにネットワーク接続なしで実行できます。ただし、他のシステムとのやり取り、リモートアクセス、または複製やクラスタリングなどの高度な機能を使用するには、ネットワーク接続が必要です。さらに、セキュリティ対策(ファイアウォールなど)、パフォーマンスの最適化(適切なネットワーク接続を選択)、およびデータバックアップは、インターネットに接続するために重要です。

高負荷アプリケーションのMySQLパフォーマンスを最適化する方法は? 高負荷アプリケーションのMySQLパフォーマンスを最適化する方法は? Apr 08, 2025 pm 06:03 PM

MySQLデータベースパフォーマンス最適化ガイドリソース集約型アプリケーションでは、MySQLデータベースが重要な役割を果たし、大規模なトランザクションの管理を担当しています。ただし、アプリケーションのスケールが拡大すると、データベースパフォーマンスのボトルネックが制約になることがよくあります。この記事では、一連の効果的なMySQLパフォーマンス最適化戦略を検討して、アプリケーションが高負荷の下で効率的で応答性の高いままであることを保証します。実際のケースを組み合わせて、インデックス作成、クエリ最適化、データベース設計、キャッシュなどの詳細な主要なテクノロジーを説明します。 1.データベースアーキテクチャの設計と最適化されたデータベースアーキテクチャは、MySQLパフォーマンスの最適化の基礎です。いくつかのコア原則は次のとおりです。適切なデータ型を選択し、ニーズを満たす最小のデータ型を選択すると、ストレージスペースを節約するだけでなく、データ処理速度を向上させることもできます。

Amazon AthenaでAWS接着クローラーの使用方法 Amazon AthenaでAWS接着クローラーの使用方法 Apr 09, 2025 pm 03:09 PM

データの専門家として、さまざまなソースから大量のデータを処理する必要があります。これは、データ管理と分析に課題をもたらす可能性があります。幸いなことに、AWS GlueとAmazon Athenaの2つのAWSサービスが役立ちます。

See all articles