SSE 实时订阅——比轮询更优雅的播放器状态获取
为什么不用轮询
如果每 1 秒向 /status 接口发一次 HTTP GET 请求来获取播放器状态,这种方式叫「轮询(Polling)」。轮询有几个问题:
- 资源浪费:大部分时间播放器状态没变化,白白发了一堆请求。
- 延迟:最快也要等 1 秒才能感知到状态变化。
- 请求风暴:如果多个客户端同时轮询,会对本地服务造成不必要的压力。
洛雪音乐提供了 SSE(Server-Sent Events,服务器推送事件)接口来解决这个问题。
SSE 是什么
SSE 是 HTTP 协议上的一种单向推送机制:
- 客户端发起一个普通的 HTTP GET 请求。
- 服务器不立即返回响应,而是保持连接。
- 每当播放器状态发生变化时,服务器主动推送新的状态数据到这个连接。
- 数据格式是简单的纯文本事件流。
相比 WebSocket,SSE 更轻量,用起来更简单——普通的 curl 命令就能测试。
订阅接口
GET /subscribe-player-status
地址完整形式:
http://127.0.0.1:23330/subscribe-player-status
可以带 filter 参数只订阅关心的字段:
GET /subscribe-player-status?filter=status,name,lyricLineText
事件格式
服务器推送的数据是纯文本,格式如下:
event: status
data: "playing"
event: name
data: "交换余生"
event: singer
data: "林俊杰"
event: lyricLineText
data: "阴天的空气里"
每条推送由 event: 行和 data: 行组成。不同事件对应播放器的不同字段。
推送的事件类型
| event 名称 | 说明 |
|---|---|
| status | 播放器状态变化(playing / paused / error / stoped) |
| name | 当前歌曲名 |
| singer | 艺术家 |
| albumName | 专辑名 |
| duration | 歌曲总时长 |
| progress | 播放进度 |
| playbackRate | 播放速率 |
| picUrl | 封面图片 URL |
| lyricLineText | 当前播放歌词文本 |
| lyricLineAllText | 包含翻译、罗马音等扩展歌词的完整文本 |
| lyric | 当前歌曲 LRC 歌词 |
| collect | 收藏状态变化 |
| volume | 音量变化 |
| mute | 静音状态变化 |
使用示例
curl 测试
# -N 参数禁用缓冲,实时看到推送内容
curl -N http://127.0.0.1:23330/subscribe-player-status
打开这条命令后,终端会一直输出。每次播放器状态变化时(切歌、暂停、歌词滚动),都会推送新的事件到终端。
Python 脚本
import requests
def handle_sse():
url = "http://127.0.0.1:23330/subscribe-player-status"
resp = requests.get(url, stream=True)
current_event = None
for line in resp.iter_lines(decode_unicode=True):
if line.startswith("event:"):
current_event = line[6:].strip()
elif line.startswith("data:"):
data = line[5:].strip()
if current_event == "lyricLineText":
print(f"当前歌词:{data}")
elif current_event == "status":
print(f"播放器状态:{data}")
handle_sse()
JavaScript 浏览器端
const source = new EventSource("http://127.0.0.1:23330/subscribe-player-status");
source.onmessage = (event) => {
// event.data 是 JSON 字符串或纯文本
console.log(event.data);
};
source.addEventListener("lyricLineText", (event) => {
console.log("当前歌词:", event.data);
});
source.close(); // 停止订阅
典型应用场景
- 桌面小组件 / Web Widget:实时显示当前播放的歌曲名和歌词。
- 智能家居面板:通过本地网络控制电脑上的洛雪音乐,同时获取实时状态显示在面板上。
- 歌词显示扩展:独立于洛雪音乐的外部歌词窗口,通过 SSE 获取实时歌词行。
- 多端状态同步:自己写的轻量同步服务,不需要用洛雪音乐的同步功能,通过 SSE 监控状态变化。
注意事项
- 订阅连接会一直保持,直到客户端主动关闭或网络断开。
- 客户端断开后可以立即重新连接,SSE 协议支持自动重连。
- 多个客户端可以同时订阅,互不影响。
- 仍然只建议在本机(127.0.0.1)上使用,不要对外开放到公网。
相关阅读
- 开放 HTTP API —— 轮询方式的接口,适合只偶尔查一次的场景。
- 开放 API 播放器控制 —— 配合 SSE 的状态推送,控制接口可以远程操作播放。