播放与代理
播放问题经常发生在客户端、SyncTV、Provider 和上游媒体服务器的边界。Provider 明确返回播放信息和上游 header,客户端按播放结果执行;底层 proxy 不猜测客户端 header。
- 客户端请求房间当前播放或指定媒体的播放信息。
- SyncTV 根据房间状态、媒体、用户、Provider 凭据和客户端能力生成
Playback。 - Provider 返回一个或多个
PlaybackInfo,每个模式包含 URL、format、header、字幕、过期时间和 metadata。 - 客户端选择合适模式:直连、proxy、转码、HLS、FLV 或字幕 URL。
- URL 过期、媒体切换、Provider 凭据变化或客户端能力变化后,客户端重新获取播放信息。
| 模式 | 适合场景 | 风险 |
|---|---|---|
| 直连 | 客户端能访问上游,并能设置必要 header | 浏览器限制 header、CORS、暴露上游地址 |
| SyncTV proxy | 上游只能被服务端访问,或需要服务端统一 header/凭据 | SyncTV 承担带宽和延迟,需规划容量 |
| Provider 转码或变体 | 上游提供多清晰度、多编码或字幕 | 客户端必须按能力选择,不能固定第一个 URL |
| 直播 HLS/FLV | RTMP 推流转播放 | 多副本需要 HLS backend 或 publisher proxy |
Alist 播放 URL 可能绑定特定 User-Agent。Bilibili 常依赖 User-Agent、Referer、Cookie 和 Range。直连与代理表现不一致时,对比 Provider 返回给客户端的 header 与代理发往上游的 header;客户端受浏览器限制时选择代理 URL。
播放线路策略
Section titled “播放线路策略”每个 Provider 负责解释 PlaybackProxyMode、判断认证信息暴露风险,并在生成 PlaybackResult 时决定具体线路。Auto 的结果可以随 Provider、媒体类型和媒体变体变化。外层 API 负责找到 Provider 并透传策略结果。
| 配置模式 | Provider 生成行为 |
|---|---|
Auto |
Provider 根据每个媒体变体的 URL、header、签名和会话要求选择实际模式 |
Prefer |
生成代理与直连线路,默认选择代理 |
Only |
只生成代理线路 |
DirectPrefer |
生成直连与代理线路,默认选择直连 |
DirectOnly |
只生成直连线路 |
Auto 以认证信息保护为主要规则:公开资源使用 DirectPrefer;认证 header、URL 认证参数、签名 URL 和 Provider 会话使用 Only。Provider 可以为协议、转码或服务端传输需求返回更严格的结果。Bilibili 视频、PGC 和直播使用签名资源,因此 Auto 返回 Only。NAS 和云盘来源依赖 Provider 会话,因此 Auto 返回 Only。Direct URL 会逐项检查媒体、字幕和弹幕资源,混合来源可以同时包含公开直连变体和受保护代理变体。
Provider 在请求上游资源前计算线路选择。只代理模式跳过直连 URL 获取或直连变体构建,只直连模式跳过代理资源构建。这个顺序减少上游请求、签名生成、转码准备和缓存写入。
客户端使用 POST /api/providers/playback-proxy-policy 查询具体 DiscoveredSource。响应包含:
supported_modes:该来源支持的表单选项。current_mode:来源当前保存的配置。auto_policies:每个媒体变体的 Auto 实际模式和原因。
客户端根据响应动态生成选择器和提示,也可以对已保存来源查询同一策略。Provider 新增媒体变体时同步更新策略返回值和播放生成测试。
Playback-provider 资源约定
Section titled “Playback-provider 资源约定”每个 Provider 管理自己生成的播放资源,包括媒体、字幕、普通弹幕、实时弹幕、缩略图、HLS playlist 与 segment、DASH manifest 与子资源,以及直播 FLV 或 HLS 资源。
Provider 资源 URL 使用以下路径:
/api/playback-providers/{roomId}/{provider}/...路径中的房间 ID 属于签名 claim。签名播放查询包含 sig、uid 和 exp。重写后的 HLS 资源还包含已签名的 targetUrl。DASH 资源路由在路径中携带签名字段,上游资源查询保持独立。这个布局保留上游查询,并让公开路径只保留一个房间标识。
Provider service 决定资源路由、上游 URL、header、直连或代理投递方式,以及 playlist 重写规则。HTTP 与 gRPC adapter 调用同一个 room actor 业务操作。共享传输层负责流式转发、Range、重定向、超时和缓存行为。
PlaybackDanmaku.delivery 告诉客户端每个弹幕资源的加载方式。DOCUMENT 使用静态文档加载器。EVENT_STREAM 使用实时事件流加载器。客户端根据这个字段选择加载器。
客户端选择策略
Section titled “客户端选择策略”客户端应根据环境和能力选择播放结果:
| 客户端条件 | 处理 |
|---|---|
浏览器不能设置 Referer 或自定义 header |
优先选择 proxy URL |
| 原生客户端可设置 header 且能访问上游 | 可使用直连 URL |
| 移动端不支持某些 codec/container | 在 PlaybackClientProfile 中声明能力,选择转码或兼容模式 |
URL 有 expires_at |
到期前重新获取播放信息 |
| 字幕有独立 header | 使用字幕 URL 自带 header;proxy 字幕时 header 会合并 |
直播传输协商
Section titled “直播传输协商”客户端通过 PlaybackClientProfile.supported_live_transports 声明播放器支持的直播传输。当前协议定义 PLAYBACK_LIVE_TRANSPORT_HLS 和 PLAYBACK_LIVE_TRANSPORT_FLV。Provider 在请求上游播放信息前选择传输,并让上游请求参数、PlaybackMedia.format 和实际 URL 保持一致。
| 客户端配置 | 当前声明 | Provider 结果 |
|---|---|---|
| Web | HLS | 请求 HLS 上游资源,返回 m3u8 媒体 |
| 原生桌面和移动端 | FLV | 请求 HTTP-FLV 上游资源,返回 flv 媒体 |
| 旧客户端或空列表 | HLS 默认能力 | 按 HLS 兼容路径生成播放信息 |
直播 Provider 将最终传输类型写入播放缓存键。HLS 和 FLV 使用独立缓存条目,因此客户端能力变化会触发对应上游资源生成。新增直播 Provider 或传输类型时,需要同时覆盖能力选择、上游参数、返回 format、缓存隔离和客户端实际播放测试。
Range 与 slice cache
Section titled “Range 与 slice cache”媒体 seek 通常依赖 HTTP Range:
Range: bytes=1048576-2097151SyncTV proxy slice cache 的边界:
- 只缓存可 Range 切片的媒体字节。
- 不做 full-body cache。
- 上游不支持 Range 时直接 bypass。
- 文件后端可以跨进程重启保留数据,但没有跨进程共享索引或分布式锁。
- 多副本可以用共享存储,但不要把 slice cache 当作强一致分布式缓存。
Provider 可以为确定不支持 Range 的小型资源选择 full-response cache,例如字幕和静态弹幕。首次响应会记录状态、Content-Length 和内容类型等 metadata;只有状态成功且声明大小不超过 16 MiB 时才进入全量缓存并使用填充锁。未知大小、超限或其他不可缓存响应仍直接流式返回,大小限制不限制向客户端转发的数据量;后续请求根据 metadata 直接 bypass,避免让不会被缓存的资源串行请求。
配置细节见 Proxy slice cache。
播放信息和 Realtime
Section titled “播放信息和 Realtime”新客户端使用 Realtime 资源观察订阅播放信息:
playbackState:当前播放位置、状态和版本。playback:当前媒体的播放 URL、headers、字幕和过期时间。
断线重连时,重新获取 playbackState,并用当前 playbackClientProfile 观察 playback。播放信息是当前播放源可直接交给播放器使用的数据,生命周期跟随其中的 URL。
完整协议见 Realtime 协议。
P2P 媒体分发
Section titled “P2P 媒体分发”原生客户端可以在播放同步设置中动态开启 P2P 媒体分发。符合条件的点播 PlaybackMedia 会包含 p2p_delivery;客户端通过 WebRTC DataChannel 从同一房间、同一资源 swarm 的其他观众获取媒体分片,并保留原始 HTTP 地址作为回退路径。
| 项目 | 行为 |
|---|---|
| 资源范围 | Provider 为静态点播资源生成房间隔离的 swarm;直播省略 p2p_delivery |
| 媒体格式 | 客户端根据所选 PlaybackMedia.format 处理普通文件、HLS 和 DASH |
| 直连与代理 | Provider 确认两种模式字节一致时,两者使用同一个 swarm |
| 权限 | 房间成员或游客需要 use_p2p_media |
| 动态开关 | 关闭后客户端离开 swarm、停止 P2P 连接并继续通过 HTTP 播放 |
| 本地缓存 | 可选择 64、128、256、512 或 1024 MiB,默认 128 MiB;最近使用的分片可跨播放会话复用,连续 10 分钟未访问后自动过期 |
播放器的 P2P 指标展示已连接 Peer、总下载和上传速度、HTTP 下载、P2P 下载与上传、累计流量、缓存大小及命中率。Peer 暂时不可用、ICE 连接失败或分片传输超时时,播放请求会自动使用来源 HTTP。
WebRTC 和直播
Section titled “WebRTC 和直播”WebRTC 和直播不是普通点播 proxy:
| 能力 | 边界 |
|---|---|
| WebRTC | 为语音聊天和 P2P 媒体分发提供独立会话,依赖 ICE/STUN/TURN 配置及对应的 use_voice_chat、use_p2p_media 权限 |
| RTMP 推流 | 推流入口,通常由主播或房间管理员使用 |
| HTTP-FLV | 低延迟直播播放路径,受长连接和客户端慢速读取影响 |
| HLS | playlist/segment 文件路径,多副本需要本地 proxy、共享文件或 S3 backend |
WebRTC 配置见 WebRTC 配置,直播见 直播配置。
| 现象 | 可能层级 | 检查 |
|---|---|---|
| 播放器立刻 403 | Provider 凭据或 header | Provider 返回 header、上游状态码 |
| seek 后失败 | Range 或 slice cache | 上游 Accept-Ranges、Content-Range、proxy 日志 |
| 只有浏览器失败 | CORS 或 header 限制 | 选择 proxy,检查浏览器 Network |
| 只有代理失败 | SyncTV 到上游网络或 header | 服务端网络、DNS、proxy header |
| 多副本直播偶发失败 | HLS 存储模型 | publisher 节点、共享存储、S3 或 gRPC proxy |
| 播放 URL 一段时间后失效 | expires_at |
订阅或重新拉取播放信息 |