PythonIDE Docs
中文
简体中文

music_player

队列式原生音乐播放器、锁屏控制和播放恢复。

队列式原生音乐播放器:维护当前歌曲、播放队列、播放模式、进度、错误状态、锁屏 Now Playing、控制中心按钮和上次播放恢复。

边界music_player 播放你自己的 URL / 本地音频队列;music 是 Apple Music / MusicKit;avplayer 是低层单媒体播放器;now_playing 只发布元数据。播放、切歌、恢复和系统控制属于副作用,放在按钮回调、页面初始化或用户确认流程里,不要在 AppUI body() 中反复调用。

#模块概览

说明
导入import music_player
适合做什么音乐 MiniApp、歌单播放器、搜索结果播放、后台音乐播放
不适合做什么Apple Music 资料库控制、短音效、AppUI 内嵌视频
状态归属宿主全局播放器服务
系统集成可选 Now Playing、控制中心 / 锁屏按钮、后台音频
恢复restore() 恢复上次队列、当前歌曲、进度和播放模式

#快速开始

python
import music_player

songs = [
    {
        "title": "Demo Track",
        "artist": "PythonIDE",
        "url": "https://example.com/demo.mp3",
        "artwork_url": "https://example.com/cover.jpg",
    }
]

music_player.set_queue(songs, start_index=0)
music_player.play()
print(music_player.state())

如果队列里的歌曲已经带有真实音频 URL,可以让宿主提前准备后面的几首,降低下一曲等待:

python
music_player.set_queue(songs, start_index=0, autoplay=True, preload_count=3)
music_player.prefetch_next(count=3)
preload_count / prefetch_next() 只预加载已经有 url 的音频。搜索平台 ID、聚合源 ID 或需要签名换链的歌曲,应先在你的 MiniApp 后台解析成真实 URL,再交给 music_player

如果不想显示锁屏卡片或接管控制中心按钮,在播放前关闭:

python
music_player.configure(
    now_playing=False,
    remote_commands=False,
    background=False,
)

#AppUI 示例

UI 完全由你自己写,播放器只提供能力:

python
import json
import appui
import music_player

songs = [
    {
        "title": "Night Demo",
        "artist": "PythonIDE",
        "url": "https://example.com/night.mp3",
        "artwork_url": "https://example.com/night.jpg",
    },
    {
        "title": "Morning Demo",
        "artist": "PythonIDE",
        "url": "https://example.com/morning.mp3",
    },
]

state = appui.State(
    title="未播放",
    artist="",
    status="ready",
    elapsed="0:00",
    mode="sequence",
)


def handle_player_event(payload):
    data = json.loads(payload or "{}")
    current = data.get("current") or {}
    state.title = current.get("title") or current.get("name") or "未播放"
    state.artist = current.get("artist") or ""
    state.status = data.get("state", "ready")
    seconds = int(data.get("elapsed") or 0)
    state.elapsed = f"{seconds // 60}:{seconds % 60:02d}"


music_player.on_event(
    handle_player_event,
    events=["ready", "play", "pause", "current", "ended", "progress", "remote_command"],
)


def load_and_play():
    music_player.configure(now_playing=True, remote_commands=True, background=True)
    music_player.set_queue(songs, start_index=0)
    music_player.play()


def toggle_mode():
    next_mode = "repeat_all" if state.mode == "sequence" else "shuffle" if state.mode == "repeat_all" else "sequence"
    state.mode = next_mode
    music_player.set_play_mode(next_mode)


def body():
    return appui.NavigationStack(
        appui.VStack([
            appui.Text(state.title).font("title2").bold(),
            appui.Text(state.artist or "—").foreground_color("secondaryLabel"),
            appui.Text(f"{state.status} · {state.elapsed}").font("caption"),
            appui.HStack([
                appui.Button("上一首", action=music_player.previous),
                appui.Button("播放", action=load_and_play).button_style("bordered_prominent"),
                appui.Button("暂停", action=music_player.pause),
                appui.Button("下一首", action=music_player.next),
            ], spacing=10),
            appui.Button(f"模式: {state.mode}", action=toggle_mode),
        ], spacing=14)
        .padding()
        .navigation_title("音乐播放器")
    )


appui.run(body, state=state)

#歌曲字段

每首歌至少需要 url

字段说明
url音频 URL、本地路径或 file://
title / name歌曲标题
artist / singer艺术家
album专辑名
duration可选时长;真实时长准备好后以播放器为准
artwork_path本地封面路径
artwork_url / cover / pic远程封面 URL,宿主会缓存后用于 Now Playing
id业务侧歌曲 ID,可用于你的列表选中状态

#API 参考

#配置

configure(now_playing=None, remote_commands=None, background=None, persist=None, auto_advance=None, progress_interval=None, can_next=None, can_previous=None)

参数说明
now_playing是否同步锁屏 / 控制中心元数据
remote_commands是否响应系统播放、暂停、上一首、下一首、seek
background是否配置后台播放音频会话
persist是否保存队列、进度和播放模式
auto_advance播放结束后是否按模式自动切歌
progress_interval进度事件间隔,最小 0.25 秒
can_next / can_previous覆盖系统按钮可用状态

#队列

API说明
set_queue(songs, start_index=0, play_mode=None, autoplay=False, preload_count=0)替换队列并加载当前歌曲;preload_count 会预备后面 N 首已解析 URL
queue()返回 {queue, current_index, count}
current()返回当前歌曲
add(song, play_next=False, autoplay=False)追加或插到下一首
remove(index)删除歌曲
move(from_index, to_index)移动歌曲
clear()停止并清空队列
prepare(song, index=None)预备一首已有真实 url 的歌曲,降低之后切到它时的加载时间
prefetch_next(count=3)按当前队列和播放模式预备后面几首
preload_state()返回预加载池状态:countpreload_countitems

#播放

API说明
play()播放当前歌曲
pause()暂停
toggle()播放 / 暂停切换
stop()停止并回到 0 秒
next()下一首
previous()上一首;当前进度超过 3 秒时先回到开头
seek(seconds)跳转
set_play_mode(mode)sequence / repeat_all / repeat_one / shuffle
set_volume(volume)0.0–1.0
set_rate(rate)0.25–3.0

#状态与恢复

API说明
state()返回完整状态:stateplayingcurrentqueueelapseddurationerror
restore(autoplay=False)恢复上次队列和进度,默认不自动播放

#事件

on_event(callback, events=None) 订阅事件。callback 可以是 Python 函数或 callback id;函数收到 JSON 字符串。

常用事件:

事件说明
ready当前歌曲可播放
play / pause / stop播放状态变化
current / queue当前歌曲或队列变化
ended当前歌曲结束
progress进度更新
preload发起预加载
prepared某首预加载歌曲已准备好
item_failed某首预加载歌曲准备失败
seek跳转
error播放错误
restore恢复完成
remote_command锁屏 / 控制中心按钮触发
python
import json
import music_player

def on_player_event(payload):
    event = json.loads(payload)
    print(event["event"], event.get("state"), event.get("elapsed"))

music_player.on_event(on_player_event, events=["play", "pause", "remote_command"])

#和相关模块的分工

需求用哪个
自己的音乐队列、锁屏按钮、后台播放music_player
播放单个 URL 音频 / 视频avplayer
AppUI 内嵌视频控件appui.PlayerController + appui.VideoPlayer
只发布锁屏标题 / 封面 / 进度now_playing
Apple Music 资料库 / MusicKitmusic
短音效sound
大文件后台下载background_download

#常见错误

错误写法后果修正
body()set_queue()play()刷新时反复重载和播放放到按钮回调或一次性初始化
music 播放自己的 MP3 URL模块不匹配music_playeravplayer
每个页面自己维护队列页面关闭后状态容易散music_player.state() / restore()
不处理 error 事件网络或格式失败时 UI 卡住订阅 error 并显示失败状态
不想锁屏显示但没配置控制中心出现播放器卡片播放前 configure(now_playing=False, remote_commands=False)

#预期效果

运行后,歌曲队列由宿主全局播放器维护;关闭页面再恢复时可通过 restore() 找回上次队列和进度。启用系统集成时,锁屏和控制中心会显示歌曲信息,并把系统按钮回调给 miniapp。