apppublic/aidocs/audioplayer.md
2025-10-05 11:23:33 +08:00

6.8 KiB
Raw Blame History

AudioPlayer 技术文档

基于 ffpyplayer 的 Python 音频播放器类,支持加载音频文件、播放控制(播放/暂停/停止)、循环播放、音量调节和事件回调等功能。


📦 概述

AudioPlayer 是一个轻量级的音频播放器封装类,利用 ffpyplayer 库实现对本地音频文件的播放控制。该类提供了简洁的接口用于常见操作,如播放、暂停、跳转、循环等,并支持自定义事件处理。


🧩 依赖库

  • ffpyplayer: 多媒体播放后端(基于 FFmpeg
  • time: 用于时间相关操作
pip install ffpyplayer

⚠️ 注意:ffpyplayer 在某些平台上可能需要手动编译或安装预构建版本。


🧱 类定义

class AudioPlayer(source=None, autoplay=False, loop=False, on_stop=None)

初始化一个音频播放器实例。

参数说明:

参数 类型 默认值 描述
source strNone None 音频文件路径(可选,在初始化时设置或后续通过 set_source() 设置)
autoplay bool False 是否在加载音频后自动开始播放
loop bool False 是否启用循环播放模式
on_stop callableNone 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 callableNone 停止播放时触发的用户回调函数
cmds list (预留)命令队列(当前未使用)

📚 方法说明

set_source(source: str)

设置音频源并立即加载。

参数:

  • source (str): 音频文件路径

行为:

  • 更新 self.source
  • 调用 load() 加载新资源

load() -> None

加载当前 source 指定的音频文件。

逻辑流程:

  1. 若无 source,直接返回。
  2. 卸载已有播放器(调用 unload())。
  3. 创建新的 MediaPlayer 实例,配置选项:
    • vn=True: 禁用视频流
    • sn=True: 启用字幕流(不影响音频)
  4. 使用 callbackloglevel='info'
  5. 等待最多 10 秒获取音频元数据(尤其是 duration
  6. 初始暂停播放器以准备控制
  7. 设置音量
  8. autoplay=True,则调用 play()

⚠️ 注意:此方法包含阻塞等待(最大 10s用于确保能读取到音频时长信息。


unload() -> None

释放当前播放器资源,重置状态。

效果:

  • 清空 player
  • 设置状态为 'stop'
  • 重置 quitted 标志

__del__()

析构函数,确保对象销毁时调用 unload()


play() -> None

开始播放音频。

行为:

  • 若尚未加载,则先调用 load()
  • 若已在播放状态,直接返回
  • 否则调用 toggle_pause() 并更新状态为 'play'

pause() -> None

暂停播放。

行为:

  • 若未加载,尝试加载
  • 若已在暂停状态,不执行操作
  • 否则调用 toggle_pause() 并更新状态为 'pause'

stop() -> None

停止播放,重置播放位置至开头。

行为:

  • 如果正在播放,先暂停
  • 将播放进度跳转至 0seek(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 维护播放状态机,防止重复操作。


已知限制与注意事项

  1. 线程安全:未考虑多线程并发访问,建议在单线程环境中使用。
  2. 异常处理:缺少对无效文件路径、格式不支持等情况的捕获,需外部保障输入合法性。
  3. 资源释放:虽然有 __del__,但推荐显式调用 unload() 或及时删除引用。
  4. 性能load() 中的循环等待可能导致短暂阻塞 UI适用于非 GUI 场景)。
  5. 日志级别:固定为 'info',可通过扩展参数暴露配置。

🛠️ 扩展建议

  • 添加音量控制接口(如 set_volume()
  • 支持获取总时长 get_duration()
  • 引入事件系统替代硬编码回调
  • 支持网络流媒体 URL
  • 增加错误处理与异常通知机制

📄 许可与版权

本代码基于 MIT 或类似自由许可发布(具体取决于 ffpyplayer 的使用条款)。请遵守其开源协议。


文档版本v1.0
最后更新2025年4月5日