import pygame
import tkinter as tk
from tkinter import filedialog
import os
import threading
import time

# 定义一些常量
SCREEN_SIZE = (800, 600)
VIDEO_SIZE = (640, 480)
FONT_SIZE = 30
WHITE = (255, 255, 255)

class PygamePlayer:
    """
    Pygame 音视频播放器类
    """
    def __init__(self, font_size=FONT_SIZE):
        """
        初始化播放器

        Args:
            font_size (int, optional): 字体大小. Defaults to FONT_SIZE.
        """
        os.environ['SDL_VIDEODRIVER'] = 'dummy'
        pygame.display.init()
        pygame.init()  # 初始化pygame模块
        pygame.display.set_caption('PygamePlayer')  # 设置窗口标题
        self.screen = pygame.display.set_mode(SCREEN_SIZE, pygame.NOFRAME)  # 设置pygame显示屏幕
        self.video_surface = pygame.Surface(VIDEO_SIZE)  # 创建视频界面
        self.clock = pygame.time.Clock()  # 创建一个pygame时间对象
        self.duration = 0  # 视频文件总时长,毫秒
        self.current_time = 0  # 当前播放时间,毫秒
        self.paused = True  # 是否暂停
        self.full_screen = False  # 是否全屏播放
        self.loaded = False  # 是否已经载入媒体文件
        self.volume = 0.5  # 声音大小
        self.media_type = None  # 媒体类型,音频或视频
        self.font = pygame.font.SysFont(None, font_size)  # 设置字体和字体大小

    def load_media(self, path):
        """
        加载媒体文件

        Args:
            path (str): 媒体文件路径
        """
        try:
            if os.path.isfile(path):  # 判断路径是不是文件
                self.loaded = True  # 文件已载入标志位
                if path.endswith('.mp4') or path.endswith('.avi') or path.endswith('.mkv'):  # 如果是视频文件
                    self.media_type = 'video'
                    self.media = pygame.movie.Movie(path)  # 加载视频
                    self.media.set_display(self.video_surface, (0, 0, VIDEO_SIZE[0], VIDEO_SIZE[1]))  # 设置视频显示区域
                    self.duration = self.media.get_length()  # 获取视频时长

                elif path.endswith('.mp3') or path.endswith('.wav'):  # 如果是音频文件
                    self.media_type = 'audio'
                    pygame.mixer.music.load(path)  # 加载音频文件
                    self.duration = pygame.mixer.Sound(path).get_length() * 1000  # 获取音频时长,转换为毫秒
        except Exception as e:
            print(f'文件加载失败!{e}')
            self.choose_file()

    def play(self):
        """
        播放媒体文件
        """
        if self.media_type == 'video':
            self.media.play()  # 播放视频
            self.paused = False
        elif self.media_type == 'audio':
            self.set_volume(self.volume)
            pygame.mixer.music.play()  # 播放音频
            self.paused = False

    def pause(self):
        """
        暂停媒体文件
        """
        if self.media_type == 'video':
            self.media.stop()  # 停止视频
            self.paused = True
        elif self.media_type == 'audio':
            pygame.mixer.music.pause()  # 暂停音频
            self.paused = True

    def rewind(self):
        """
        后退10秒
        """
        self.set_current_time(self.current_time - 10000)

    def fast_forward(self):
        """
        快进10秒
        """
        self.set_current_time(self.current_time + 10000)

    def toggle_full_screen(self):
        """
        切换全屏模式
        """
        self.full_screen = not self.full_screen  # 切换全屏标志位
        if self.full_screen:
            self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN | pygame.DOUBLEBUF)  # 全屏播放
        else:
            self.screen = pygame.display.set_mode(SCREEN_SIZE)  # 恢复原来的窗口大小

    def choose_file(self):
        """
        选择媒体文件
        """
        root = tk.Tk()
        root.withdraw()  # 隐藏tk窗口
        file_path = filedialog.askopenfilename()
        if file_path:
            self.load_media(file_path)
            self.play()

    def set_volume(self, volume):
        """
        设置音量

        Args:
            volume (float): 音量值,范围为0.0到1.0
        """
        if self.media_type == 'audio':
            pygame.mixer.music.set_volume(volume)

    def set_current_time(self, current_time):
        """
        设置当前播放时间

        Args:
            current_time (int): 当前播放时间,单位为毫秒
        """
        if self.media_type == 'audio':
            if current_time < 0:
                current_time = 0
            elif current_time > self.duration:
                current_time = self.duration
            pygame.mixer.music.set_pos(current_time)
        elif self.media_type == 'video':
            if current_time < 0:
                current_time = 0
            elif current_time > self.duration:
                current_time = self.duration
            self.media.set_time(current_time)

    def manage_keys(self, keys):
        """
        处理键盘事件

        Args:
            keys (list): 键盘按键状态
        """
        if keys[pygame.K_SPACE]:
            if self.paused:
                self.play()
            else:
                self.pause()
        if keys[pygame.K_RIGHT]:
            self.fast_forward()
        if keys[pygame.K_LEFT]:
            self.rewind()
        if keys[pygame.K_ESCAPE]:
            self.toggle_full_screen()
        if keys[pygame.K_q]:
            self.quit()

    def quit(self):
        """
        退出程序
        """
        pygame.quit()
        quit()

    def run(self):
        """
        运行播放器
        """
        while True:
            if self.loaded:
                # 处理事件
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        self.quit()
                    if event.type == pygame.KEYDOWN:
                        self.manage_keys(pygame.key.get_pressed())
                    if event.type == pygame.MOUSEBUTTONDOWN:
                        if event.button == 1:
                            self.choose_file()
                # 更新时间
                if self.media_type == 'audio':
                    self.current_time = pygame.mixer.music.get_pos()
                elif self.media_type == 'video':
                    self.current_time = self.media.get_time()
                    if self.media.get_time() >= self.duration:  # 视频播放完毕,重新播放
                        self.media.stop()
                        self.media.play()
                # 绘制
                if self.full_screen:
                    self.video_surface = pygame.transform.scale(self.video_surface, SCREEN_SIZE)
                else:
                    self.video_surface = pygame.transform.scale(self.video_surface, VIDEO_SIZE)
                self.screen.blit(self.video_surface, (0, 0))
                # 在屏幕上绘制当前时间和总时间
                time_text = time.strftime('%H:%M:%S', time.gmtime(self.current_time / 1000)) + ' / ' + time.strftime('%H:%M:%S', time.gmtime(self.duration / 1000))
                time_surface = self.font.render(time_text, True, WHITE)  # 创建时间显示surface
                self.screen.blit(time_surface, (10, 10))  # 在屏幕上绘制时间
                pygame.display.update()  # 更新屏幕
            self.clock.tick(60)  # 设置帧率为60


if __name__ == '__main__':
    player = PygamePlayer()  # 创建播放器对象
    player.run()  # 运行播放器
Python Pygame 音视频播放器 - 使用 Tkinter 选择文件

原文地址: https://www.cveoy.top/t/topic/otA2 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录