6.8 KiB
6.8 KiB
AudioPlayer 技术文档
基于 ffpyplayer 的 Python 音频播放器类,支持加载音频文件、播放控制(播放/暂停/停止)、循环播放、音量调节和事件回调等功能。
📦 概述
AudioPlayer 是一个轻量级的音频播放器封装类,利用 ffpyplayer 库实现对本地音频文件的播放控制。该类提供了简洁的接口用于常见操作,如播放、暂停、跳转、循环等,并支持自定义事件处理。
🧩 依赖库
ffpyplayer: 多媒体播放后端(基于 FFmpeg)time: 用于时间相关操作
pip install ffpyplayer
⚠️ 注意:
ffpyplayer在某些平台上可能需要手动编译或安装预构建版本。
🧱 类定义
class AudioPlayer(source=None, autoplay=False, loop=False, on_stop=None)
初始化一个音频播放器实例。
参数说明:
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
source |
str 或 None |
None |
音频文件路径(可选,在初始化时设置或后续通过 set_source() 设置) |
autoplay |
bool |
False |
是否在加载音频后自动开始播放 |
loop |
bool |
False |
是否启用循环播放模式 |
on_stop |
callable 或 None |
None |
当音频停止时调用的回调函数 |
🔧 属性列表
| 属性名 | 类型 | 描述 |
|---|---|---|
volume |
float |
当前音量(范围 0.0 ~ 1.0),默认为 1.0 |
state |
str |
当前状态:'play', 'pause', 'stop' |
source |
str |
当前音频源路径 |
quitted |
bool |
标记是否已请求退出(内部使用) |
loop |
bool |
是否开启循环播放 |
autoplay |
bool |
是否自动播放 |
player |
MediaPlayer 实例或 None |
ffpyplayer.player.MediaPlayer 对象 |
on_stop |
callable 或 None |
停止播放时触发的用户回调函数 |
cmds |
list |
(预留)命令队列(当前未使用) |
📚 方法说明
set_source(source: str)
设置音频源并立即加载。
参数:
source(str): 音频文件路径
行为:
- 更新
self.source - 调用
load()加载新资源
load() -> None
加载当前 source 指定的音频文件。
逻辑流程:
- 若无
source,直接返回。 - 卸载已有播放器(调用
unload())。 - 创建新的
MediaPlayer实例,配置选项:vn=True: 禁用视频流sn=True: 启用字幕流(不影响音频)
- 使用
callback和loglevel='info' - 等待最多 10 秒获取音频元数据(尤其是 duration)
- 初始暂停播放器以准备控制
- 设置音量
- 若
autoplay=True,则调用play()
⚠️ 注意:此方法包含阻塞等待(最大 10s),用于确保能读取到音频时长信息。
unload() -> None
释放当前播放器资源,重置状态。
效果:
- 清空
player - 设置状态为
'stop' - 重置
quitted标志
__del__()
析构函数,确保对象销毁时调用 unload()。
play() -> None
开始播放音频。
行为:
- 若尚未加载,则先调用
load() - 若已在播放状态,直接返回
- 否则调用
toggle_pause()并更新状态为'play'
pause() -> None
暂停播放。
行为:
- 若未加载,尝试加载
- 若已在暂停状态,不执行操作
- 否则调用
toggle_pause()并更新状态为'pause'
stop() -> None
停止播放,重置播放位置至开头。
行为:
- 如果正在播放,先暂停
- 将播放进度跳转至 0(
seek(0)) - 更新状态为
'stop' - 触发
on_stop回调(如果存在)
seek(pos: float) -> None
跳转到指定时间点(单位:秒)。
参数:
pos(float): 目标时间位置(绝对时间)
示例:
p.seek(30.0) # 跳转到第30秒
get_pos() -> float
获取当前播放时间(单位:秒)。
返回:
- 当前播放时间戳(PTS),若无播放器则返回
0
is_busy() -> bool
判断是否正在播放中。
返回:
True表示处于'play'状态且有有效播放器False表示暂停或停止
player_callback(selector: str, value: any)
内部回调函数,由 ffpyplayer 触发。
触发事件:
'quit': 播放器退出 → 调用close()清理资源'eof': 播放结束 → 调用_do_eos()
✅ 日志输出可用于调试。
_do_eos(*args) -> None
处理播放结束(End of Stream)事件。
行为:
- 若启用
loop,则跳回开头继续播放 - 否则调用
stop()结束播放
🎯 使用示例
基本使用
from audio_player import AudioPlayer
def on_audio_stopped():
print("音频已停止")
# 初始化播放器
player = AudioPlayer(
source="music.mp3",
autoplay=True,
loop=True,
on_stop=on_audio_stopped
)
# 控制播放
player.play()
time.sleep(5)
player.pause()
player.seek(10.0) # 跳转到第10秒
player.play()
# 查询位置
print(f"当前时间: {player.get_pos()}s")
# 停止
player.stop()
手动交互式控制(主程序示例)
运行脚本时传入音频路径:
python audio_player.py /path/to/audio.mp3
交互命令:
play— 开始播放pause— 暂停stop— 停止并归零quit— 退出程序
⚙️ 内部机制说明
播放器初始化选项 (ff_opts)
ff_opts = {'vn': True, 'sn': True}
vn=True: 忽略视频流(仅音频)sn=True: 启用字幕流(不影响播放)
元数据加载等待机制
使用 time.perf_counter() 最多等待 10 秒以获取 duration,避免因媒体分析过慢导致后续操作失败。
状态管理
通过 self.state 维护播放状态机,防止重复操作。
❗ 已知限制与注意事项
- 线程安全:未考虑多线程并发访问,建议在单线程环境中使用。
- 异常处理:缺少对无效文件路径、格式不支持等情况的捕获,需外部保障输入合法性。
- 资源释放:虽然有
__del__,但推荐显式调用unload()或及时删除引用。 - 性能:
load()中的循环等待可能导致短暂阻塞 UI(适用于非 GUI 场景)。 - 日志级别:固定为
'info',可通过扩展参数暴露配置。
🛠️ 扩展建议
- 添加音量控制接口(如
set_volume()) - 支持获取总时长
get_duration() - 引入事件系统替代硬编码回调
- 支持网络流媒体 URL
- 增加错误处理与异常通知机制
📄 许可与版权
本代码基于 MIT 或类似自由许可发布(具体取决于 ffpyplayer 的使用条款)。请遵守其开源协议。
文档版本:v1.0
最后更新:2025年4月5日