Python实现本地视频/音频播放器

news2024/11/18 11:19:20

Python实现本地视频/音频播放器

在Python中,有几个库可以用于视频播放,但是没有一个库是完美的,因为它们可能依赖于外部软件或有一些限制。

先看介绍用Python实现本地视频播放器,再介绍用Python实现本地音乐播放器。

Python实现本地视频播放器

与HTML5+JavaScript实现本地视频播放器相比,使用Python实现比较麻烦。我发现网上给出的一些示例,通常有一些小问题,如画面和声音不同步等,或有画面没声音的。下面我给出一个简单而效果较好的例子。

Tkinter 是 Python 的一个内置库,它提供了构建图形用户界面 (GUI) 的工具。Tkinter 基于 Tk GUI 工具包。Tkinter 是 Python 标准库的一部分,因此您不需要安装任何额外的包。

                     

ffpyplayer是一个基于FFmpeg的Python多媒体播放库,它可以播放多种格式的视频和音频文件。相比pygame,ffpyplayer支持更多的媒体格式,包括常见的MP4、AVI、MKV、FLV等视频格式,以及MP3、WAV、FLAC等音频格式。

这是第三方库,需要安装, cmd命令行中,输入如下命令:

pip install ffpyplayer

如果你的电脑上安装了多个Python版本,你可以为特定版本的Python安装模块(库、包),还可以使用国内的镜像加快安装速度。例如我的电脑中安装了多个Python版本,要在Python 3.10版本中安装,并使用清华的镜像,cmd命令行中,输入如下命令:

py -3.10 -m pip install ffpyplayer -i https://pypi.tuna.tsinghua.edu.cn/simple

Pillow库是在PIL库的基础上发展起来的,它继承了PIL库的大部分功能,并进行了许多改进和增强。Pillow库已经成为了Python图像处理领域中使用最广泛的库之一,提供了丰富的图像处理功能,包括图片打开、大小调整、裁剪、旋转、滤镜等操作。PIL库在Python 3之后已经停止维护,取而代之的是Pillow库。

这是第三方库,需要安装, cmd命令行中,输入如下命令:

pip install Pillow

如果你的电脑上安装了多个Python版本,你可以为特定版本的Python安装模块(库、包),还可以使用国内的镜像加快安装速度。例如我的电脑中安装了多个Python版本,要在Python 3.10版本中安装,并使用清华的镜像,cmd命令行中,输入如下命令

py -3.10 -m pip install Pillow -i https://pypi.tuna.tsinghua.edu.cn/simple

下面,是Python使用这些库实现的简单的本地视频播放器,给先给出效果图:

源码如下:

import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
from tkinter.ttk import Style, Progressbar
from ffpyplayer.player import MediaPlayer

# 定义视频播放器类
class VideoPlayTk:
    # 初始化函数
    def __init__(self, root):
        self.root = root
        self.root.title('视频播放器')  # 设置窗口标题

        # 创建一个画布用于显示视频帧
        self.canvas = tk.Canvas(root, bg='black')
        self.canvas.pack(fill=tk.BOTH, expand=True)

        # 创建打开文件按钮
        self.open_button = tk.Button(root, text='打开', command=self.open_file)
        self.open_button.pack(side=tk.LEFT)

        # 创建暂停/播放按钮
        self.pause_button = tk.Button(root, text='暂停/继续', command=self.toggle_pause)
        self.pause_button.pack(side=tk.LEFT)

        # 初始化播放器和播放状态标志
        self.player = None
        self.is_paused = False
        self.is_stopped = False

    # 打开文件的函数
    def open_file(self):
        #file_path = filedialog.askopenfilename()  # 弹出文件选择对话框
        file_path = filedialog.askopenfilename(filetypes=[("Video files", "*.mp4;*.avi;*.mov;*.wmv;*.mkv;*.flv;*.mpeg;*.3gp")])
        if file_path:
            self.is_stopped = False
            self.is_paused = False
            self.start_video(file_path)  # 开始播放选择的视频文件

    # 开始播放视频的函数
    def start_video(self, file_path):
        self.player = MediaPlayer(file_path)  # 创建一个MediaPlayer对象
        self.play_video()  # 开始播放视频

    # 播放视频的函数
    def play_video(self):
        if self.is_stopped:
            self.player = None  # 如果停止播放,则释放播放器资源
            return

        frame, val = self.player.get_frame()  # 获取下一帧和帧间隔
        if val == 'eof':
            self.player = None  # 如果到达视频末尾,则释放播放器资源
            return
        elif frame is None:
            self.root.after(10, self.play_video)  # 如果没有帧,则稍后再试
            return

        # 将帧图像转换为Tkinter PhotoImage并显示在画布上
        image, pts = frame
        image = Image.frombytes("RGB", image.get_size(), bytes(image.to_bytearray()[0]))
        photo = ImageTk.PhotoImage(image=image)
        self.canvas.create_image(0, 0, image=photo, anchor=tk.NW)
        self.canvas.image = photo  # 保持对PhotoImage的引用,防止被垃圾回收

        # 如果没有暂停,则继续播放下一帧
        if not self.is_paused:
            self.root.after(int(val * 1000), self.play_video)

    # 切换暂停状态的函数
    def toggle_pause(self):
        if self.player:
            self.is_paused = not self.is_paused  # 切换暂停状态
            self.player.set_pause(self.is_paused)  # 设置播放器的暂停状态
            if not self.is_paused:
                self.play_video()  # 如果继续播放,则播放下一帧

# 程序入口点
if __name__ == '__main__':
    root = tk.Tk()  # 创建Tkinter根窗口
    app = VideoPlayTk(root)  # 创建视频播放器应用
    root.mainloop()  # 进入Tkinter事件循环

下面是改进:带有播放显示时间轴,效果图如下:

源码如下:

import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
from tkinter.ttk import Style, Progressbar
from ffpyplayer.player import MediaPlayer

class VideoPlayTk:
    def __init__(self, root):
        self.root = root
        self.root.title('视频播放器')

        # 创建一个画布用于显示视频帧
        self.canvas = tk.Canvas(root, bg='black')
        self.canvas.pack(fill=tk.BOTH, expand=True)

        # 创建打开文件按钮
        self.open_button = tk.Button(root, text='打开', command=self.open_file)
        self.open_button.pack(side=tk.LEFT)

        # 创建暂停/播放按钮
        self.pause_button = tk.Button(root, text='暂停/继续', command=self.toggle_pause)
        self.pause_button.pack(side=tk.LEFT)

        # 创建时间轴,时间轴指示的时间可能不准确,注意to 值的设置
        self.timeline = tk.Scale(root, from_=0, to=250, orient=tk.HORIZONTAL)
        self.timeline.pack(fill=tk.X)

        # 初始化播放器和播放状态标志
        self.player = None
        self.is_paused = False
        self.is_stopped = False
        self.video_duration = 0

    def open_file(self):
        file_path = filedialog.askopenfilename(filetypes=[("Video files", "*.mp4;*.avi;*.mov;*.wmv;*.mkv;*.flv;*.mpeg;*.3gp")])
        if file_path:
            self.is_stopped = False
            self.is_paused = False
            self.start_video(file_path) # 开始播放选择的视频文件

    def start_video(self, file_path):
        self.player = MediaPlayer(file_path)
        self.video_duration = self.player.get_metadata()['duration']
        self.timeline.config(to=self.video_duration)
        self.play_video() # 开始播放视频 

    def play_video(self):
        if self.is_stopped:
            self.player = None
            return

        frame, val = self.player.get_frame() # 获取下一帧和帧间隔
        if val == 'eof':
            self.player = None
            return
        elif frame is None:
            self.root.after(10, self.play_video) # 如果没有帧,则稍后再试
            return

        # 将帧图像转换为Tkinter PhotoImage并显示在画布上
        image, pts = frame
        image = Image.frombytes("RGB", image.get_size(), bytes(image.to_bytearray()[0]))
        photo = ImageTk.PhotoImage(image=image)
        self.canvas.create_image(0, 0, image=photo, anchor=tk.NW)
        self.canvas.image = photo

        self.timeline.set(pts)  # Update the timeline value(更新时间轴值)

        # 如果没有暂停,则继续播放下一帧
        if not self.is_paused:
            self.root.after(int(val * 1000), self.play_video)

    def toggle_pause(self):
        if self.player:
            self.is_paused = not self.is_paused  # 切换暂停状态
            self.player.set_pause(self.is_paused) # 设置播放器的暂停状态
            if not self.is_paused:
                self.play_video()  # 如果继续播放,则播放下一帧

if __name__ == '__main__':
    root = tk.Tk()
    app = VideoPlayTk(root)
    root.mainloop()


提示,时间轴指示的时间可能不准确。待找到处理方法时更新。

附录

Python使用pillow库(PIL库)的使用介绍 https://blog.csdn.net/cnds123/article/details/126141838

Python简单GUI程序示例(四、视频播放器)https://blog.csdn.net/cnds123/article/details/122903311

Python实现的本地音乐播放器

使用tkinter库来构建用户界面,以及pygame库来处理音频播放。

pygame是一个用于编写游戏和多媒体应用程序的Python模块。它提供了许多功能,包括绘制图形、处理音频、处理输入设备等。功能比较丰富易用

pygame库是第三方库,需要安装, cmd命令行中,输入如下命令:

pip install pygame

如果你的电脑上安装了多个Python版本,你可以为特定版本的Python安装模块(库、包),还可以使用国内的镜像加快安装速度。例如我的电脑中安装了多个Python版本,要在Python 3.10版本中安装,并使用清华的镜像,cmd命令行中,输入如下命令:

py -3.10 -m pip install pygame -i https://pypi.tuna.tsinghua.edu.cn/simple

给先给出效果图:

有打开“按钮”按钮加载音乐文件,“暂停/继续”按钮用于暂停、继续播放,并能显示当前播放的时间(每秒更新/时长)。

源码如下:

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

class MusicPlayer:
    def __init__(self, root):
        self.root = root
        self.root.title('Music Player')
        self.root.geometry('400x200')

        pygame.init()
        pygame.mixer.init()

        self.status = 'stopped'
        self.current_time = 0
        self.total_time = 0

        self.load_button = tk.Button(self.root, text='加载音乐', width=10, command=self.load_music)
        self.load_button.pack()

        self.play_button = tk.Button(self.root, text='播放', width=10, command=self.play_music)
        self.play_button.pack()

        self.pause_button = tk.Button(self.root, text='暂停/继续', width=10, command=self.toggle)
        self.pause_button.pack()

        self.time_label = tk.Label(self.root, text='00:00 / 00:00')
        self.time_label.pack()

        self.file_label = tk.Label(self.root, text='加载的音乐文件: ')
        self.file_label.pack()

        self.update_time()

    def load_music(self):
        self.file_path = filedialog.askopenfilename(filetypes=[("Audio files", "*.mp3; *.wav; *.ogg")])
        pygame.mixer.music.load(self.file_path)
        self.total_time = pygame.mixer.Sound(self.file_path).get_length()
        self.file_label.config(text='加载的音乐文件: ' + self.file_path)

    def play_music(self):
        if self.status != 'playing':
            pygame.mixer.music.play()
            self.status = 'playing'

    def toggle(self):
        if self.status == 'paused':
            pygame.mixer.music.unpause()
            self.status = 'playing'
        elif self.status == 'playing':
            pygame.mixer.music.pause()
            self.status = 'paused'

    def update_time(self):
        if self.status == 'playing':
            self.current_time = pygame.mixer.music.get_pos() // 1000
            mins, secs = divmod(self.current_time, 60)
            timeformat = '{:02d}:{:02d}'.format(mins, secs)
            total_mins, total_secs = divmod(int(self.total_time), 60)
            total_timeformat = '{:02d}:{:02d}'.format(total_mins, total_secs)
            self.time_label.config(text='{} / {}'.format(timeformat, total_timeformat))
        self.root.after(1000, self.update_time)

if __name__ == "__main__":
    root = tk.Tk()
    app = MusicPlayer(root)
    root.mainloop()

附录

Python中的pygame游戏模块的使用 https://blog.csdn.net/cnds123/article/details/119514520

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1624980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C 数据结构】图

文章目录 【 1. 基本原理 】1.1 无向图1.2 有向图1.3 基本知识 【 2. 图的存储结构 】2.1 完全图2.2 稀疏图和稠密图2.3 连通图2.3.1 (普通)连通图连通图 - 无向图非连通图 的 连通分量 2.3.2 强连通图强连通图 - 有向图非强连通有向图 的 强连通分量 2.3.3 生成树 - 连通图2.3…

重仓比特币

作者:Arthur Hayes Co-Founder of 100x. 编译:liam ccvalue (下文中表达的任何观点均为作者的个人观点,不应作为投资决策的依据,也不应被视为参与投资交易的建议或意见)。 我们中断牛市常规节目,为您播报这…

【研发管理】产品经理知识体系-产品创新中的市场调研

导读:在产品创新过程中,市场调研的重要性不言而喻。它不仅是产品创新的起点,也是确保产品成功推向市场的关键步骤。对于产品经理系统学习和掌握产品创新中的市场调研相关知识体系十分重要。 目录 概述:市场调研重要性 1、相关概…

华为数字化转型与数据管理实践介绍(附PPT下载)

华为作为全球领先的信息与通信技术(ICT)解决方案提供商,在数字化转型和数据管理领域拥有丰富的实践经验和技术积累。其数字化转型解决方案旨在帮助企业通过采用最新的ICT技术,实现业务流程、组织结构和文化的全面数字化&#xff0…

Kafka 3.x.x 入门到精通(03)——对标尚硅谷Kafka教程

Kafka 3.x.x 入门到精通(03)——对标尚硅谷Kafka教程 2. Kafka基础2.1 集群部署2.2 集群启动2.3 创建主题2.4 生产消息2.4.1 生产消息的基本步骤2.4.2 生产消息的基本代码2.4.3 发送消息2.4.3.1 拦截器2.4.3.1.1 增加拦截器类2.4.3.1.2 配置拦截器 2.4.3…

Spring Bean 的生命周期与作用域解析及实战

引言 在Spring框架中,Bean是构成应用的核心组件,它们负责执行应用中的业务逻辑。理解Spring Bean的生命周期和作用域对于开发高效、稳定的Spring应用至关重要。本文将详细解析Spring Bean的生命周期和作用域,并通过实战案例加深理解。 一、…

使用FunASR处理语音识别

FunASR是阿里的一个语音识别工具,比SpeechRecognition功能多安装也很简单; 官方介绍:FunASR是一个基础语音识别工具包,提供多种功能,包括语音识别(ASR)、语音端点检测(VAD&#xff…

微软ML Copilot框架释放机器学习能力

摘要:大模型席卷而来,通过大量算法模型训练推理,能根据人类输入指令产生图文,其背后是大量深度神经网络模型在做运算,这一过程称之为机器学习,本文从微软语言大模型出发,详解利用大型语言模型&a…

Java设计模式:使用责任链模式和状态模式优化‘审批流程‘

Java设计模式:使用责任链模式和状态模式优化审批流程 摘要引言 需求流程图正文内容📐 基本概念介绍 功能实现示例1:设计模式:责任链模式方法:好处: 示例2:设计模式:责任链模式方法和操作流程:好…

【stm32】swjtu西南交大嵌入式实验三 外部中断实验:按键中断

实验内容: 1、编写程序,设置主程序:跑马灯以 0.2s 的速度旋转;将 KB1 设置为外部中断,下 降沿触发,按下 KB1 则全彩灯的 R 灯闪烁 5 次。编译、下载程序到开发板,观察实 验现象;按下…

torch.cuda.is_avaliable()在命令行里是true,pycharm是false【省流:换Pycharm】

我的问题: 1、torch.cuda.is_avaliable()在命令行里是true,但是pycharm是false 2、pycharm选择pytorch所在的解释器,加载失败。 3、pytorch所在的解释器加载成功,但是里边的torch包莫名消失。 解决方法: 在调试了很…

Sping源码(七)—context: component-scan标签如何扫描、加载Bean

序言 简单回顾一下。上一篇文章介绍了从xml文件context component-scan标签的加载流程到ConfigurationClassPostProcessor的创建流程。 本篇会深入了解context component-scan标签底层做了些什么。 component-scan 早期使用Spring进行开发时,很多时候都是注解 标…

免费好用各科目的刷题软件

一 、前言 刷题,即通过大量做题来提高解题能力和考试成绩的行为,主要有以下几个好处: 1. 熟悉题型和考试格式 通过刷题,可以对考试中可能出现的题型和格式有更深入的了解,有助于在实际考试中快速识别题目类型和解题…

Java使用IText根据pdf模板创建pdf文件

1.导包 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.10</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-as…

mdk输出本语句在源程序中行数以及函数名称

代码如下&#xff1a; /* USER CODE BEGIN WHILE */while (1){printf("anlog uart1 test 2024-4-16\r\n");printf("[%s] %d\r\n",__func__,__LINE__);printf("[%s] %d",__func__,__LINE__);HAL_Delay(200);/* USER CODE END WHILE *//* USER COD…

MyBatis源码之MyBatis中SQL语句执行过程

MyBatis源码之MyBatis中SQL语句执行过程 SQL执行入口 我们在使用MyBatis编程时有两种方式&#xff1a; 方式一代码如下&#xff1a; SqlSession sqlSession sqlSessionFactory.openSession(); List<Student> studentList sqlSession.selectList("com.sjdwz.da…

AWS SES发送邮件如何正确配置?操作指南?

AWS SES发送邮件有哪些限制&#xff1f;AWS SES发信的注意事项&#xff1f; AWS SES作为亚马逊云服务提供的一项高效、可靠的电子邮件发送服务&#xff0c;受到了众多企业的青睐。然而&#xff0c;如何正确配置AWS SES发送邮件。AokSend将详细解析AWS SES发送邮件的配置过程&a…

GO语言写Prometheus自定义node-exporter的Docker容器测试

1. 安装docker-compose 执行以下命令&#xff0c;安装docker-compose到CentOS7.9环境中&#xff1a; # 下载二进制文件 sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.7/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/d…

耐酸碱腐蚀PFA冷凝回流装置进口透明聚四氟材质PFA梨形漏斗特氟龙圆底烧瓶

PFA分液漏斗&#xff1a;也叫特氟龙分液漏斗、特氟龙梨型分液漏斗。 规格参考&#xff1a;125ml、250ml、500ml、1000ml 其主要特性有&#xff1a; 1.内壁对溶剂无粘贴性和吸附&#xff0c;可完全排空&#xff0c;分界面清晰可见&#xff1b; 2.密封性好&#xff0c;可防止…

Laravel 6 - 第十七章 配置数据库

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …