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