09 · 媒体会话与传输
本章定义宿主如何把 05 的资源引用变成图片、字幕和可播放媒体。 数据模型描述“资源是什么”,本章约定“由谁请求、怎样传输、何时刷新”。这些机制由宿主统一实现。
1. 会话与资源归属
宿主接到 ImageRef、Stream 或字幕轨时,将其登记为媒体会话中的资源,并返回界面可直接使用的本地地址。
本地地址的具体传输方式由平台实现决定,可以使用应用协议或本地 HTTP 服务;必须通过实际播放器验证,
不能假定五端播放器都能读取同一种自定义协议。会话 ID 是不透明引用,不把请求头和密钥拼进地址。
每个资源记录以下内部信息,插件不需要填写:
- 资源提供者:返回该资源的数据源或解析器插件 ID、代码修订及站点线路快照。
- 原始地址、最终地址、显式请求头、提供者默认头、Cookie 罐归属与字节变换。
- 播放会话另存作品/频道、分集、播放列表、各阶段线路选择和解析链,供刷新重用。
数据源返回的图片、字幕、直接流属于数据源;解析器返回的流、字幕属于解析器。
HLS/DASH 清单引用的子资源继承清单提供者及变换配置,不因 CDN 域名变化而改变提供者。
插件变换始终调用所属资源提供者的 transformResource,不能因为入口来自数据源就调用错插件。
提供者请求环境按 05 §7.4 合并,自动 Cookie 按目标 URL 匹配。
显式 Cookie、Authorization 只在与原资源 URL 同源的子请求或重定向中保留;跳转到其他 origin 时移除,
不能在后续跳转又从默认头重新加回来。其他头继续按传输规则处理。资源请求的 Set-Cookie 写回提供者的罐。
会话持有资源描述不等于常驻 JS 运行时。静态请求头、代理与原生 AES 变换不需要加载插件; 需要插件变换或刷新时由宿主按需恢复运行时。会话释放后取消其任务并回收资源引用;共享资源仍有其他使用者时保留。
2. 解析器结果合并
- 数据源的
resolvePlayback或live.resolve返回page流后,宿主选定一个解析器。 - 宿主将页面地址及有效的非凭据请求头交给解析器;不转交源的 Cookie 罐、Authorization、显式 Cookie 或存储。 传入的 Referer 等头供解析器使用,不自动成为其全部后续媒体请求的默认头。
- 解析器返回的流替换当前选择的 page 候选;其他源流仍可作为候选。解析器不得继续返回 page。
- 数据源字幕与解析器字幕合并,各自保持归属;相同 URL、相同提供者且有效请求配置相同的轨可去重。 多条 default 时以当前解析器的首条 default 优先,否则使用源的首条 default。
- 当前解析器返回的 durationSec、resumeSec、skip 优先,未给出则沿用源值;本地进度始终优先于 resumeSec。 有效期取当前链路各阶段已声明 expiresAt 的最早值,不把其他未选中候选流的有效期混入。
源线路与解析器线路的 ID 不属于同一命名空间。宿主内部用“阶段 + 插件 ID + 原始 serverId”记录选择, 界面显示源线路与解析器线路各自的标签;调用时只把原始 ID 传给对应阶段,不把解析器 serverId 传给数据源。 指定解析器不可用时明确提示;用户重新选择后才改变解析链,不静默换成不同实现。
一次播放解析动作共享总预算,默认 20 秒,上限 60 秒,按入口数据源的 playback 预算设定。 每个阶段还受其自身预算约束,调用解析器不能重置总计时;用户主动进行解析器选择不占插件执行预算, 但离开页面会取消整个动作。网页交互暂停规则仍按 04 §12。
3. 普通媒体与 HLS/DASH
没有变换的 progressive 资源必须支持流式代理,不把整个视频读入内存:
- 按播放器需要转发 GET/HEAD 与 Range/If-Range,并保留正确的 200/206/416 语义。
- 转发或正确重算 Content-Type、Content-Length、Content-Range、Accept-Ranges;不得固定伪造为 200 或 bytes。
- 上游忽略 Range 时按其实际响应处理,不把完整响应标记为局部响应;离开播放及时取消上游传输。
HLS 代理必须处理主清单与媒体清单,至少覆盖子播放列表、音频/字幕清单、分片、KEY/SESSION-KEY、MAP, 以及支持低延迟播放时的 PART/PRELOAD-HINT。所有 URI 以该清单重定向后的最终地址解析, 再改写为会话资源地址;保留原有查询参数,不能自行把父清单签名猜测追加到所有子资源。 保留 BYTERANGE、MEDIA-SEQUENCE、DISCONTINUITY 等影响播放的语义。每个子资源继续执行网络规则。
标准 HLS AES-128 按播放器支持处理,宿主负责代理密钥;这与资源传输前的自定义字节变换是两回事,不能重复解密。 清单处理顺序为:取得字节 → 必要的 playlist 变换 → 按最终 URL 解析并改写 URI → 交给播放器。 MAP 初始化段按 segment 配置处理,KEY 按 key 配置处理。
DASH 为可选特性 format.dash:只有播放器、MPD 子资源寻址和宿主代理都可用时才声明。
实现必须覆盖所接受的 MPD 形式的 BaseURL、初始化段、媒体分段与范围请求;无法处理时报告 UNSUPPORTED,
不能声明支持后把带专用头的子资源留给播放器直接跨域请求。音轨能力以设备实际可播放的清单为准。
4. 字节变换与范围请求
1.0 的变换以完整资源为单位,原生 AES 和 plugin 变换都不得直接作用于任意截断后的密文字节。 可变换资源为有界的图片、播放列表、密钥、媒体分片及初始化段;不支持整个 progressive 视频变换。 插件变换的完整参数与结果分别受 8 MiB 上限约束,原生变换也须设置有界资源读取预算。
需要对变换后资源请求局部字节时,宿主先取完整待变换资源、执行变换,再对输出切片并计算范围响应头。 缓存键必须区分提供者代码修订、请求环境、变换 name/state/key/iv 和输入资源,不能只按 URL 缓存。 超出预算或无法确定完整变换边界时明确报错,不默默改为对密文局部解密。
对 HLS BYTERANGE,条目所标识的上游字节区间就是待变换资源边界:先取完整区间,再变换。 只有该区间自身可独立解码时才可使用变换;1.0 不支持跨多个区间共享密码状态的算法。 本地地址必须区分这些区间,并移除或重写清单中的原始 BYTERANGE,使播放器不会在解密输出上再套一次密文偏移。 无法做到时返回 UNSUPPORTED。
5. 有效期与播放恢复
- 对活跃播放/下载会话,在最早 expiresAt 到期前按宿主策略刷新;没有声明有效期时,401/403、 地址失效等可恢复取流失败也可触发一次刷新。取消、明确内容下架和网络离线不触发无限刷新。
- 刷新从入口数据源开始,以 reason: "refresh" 调用
media.resolvePlayback或live.resolve, 再按新 page 地址执行选定解析器,解析器也收到 reason: "refresh"。两阶段都不得返回已知过期缓存。 解析器指定或主机改变导致路由不再适用时重新选择;需要用户选择时暂停播放并显示入口。 - 同一会话只运行一个刷新任务,其他请求等待其结果。新链路成功后原子替换会话中的资源映射, 失效的旧资源请求不继续无限重试;播放器需要重载时保存当前播放位置再恢复。
- 点播以当前本地位置为准,不重复使用上游 resumeSec 覆盖;直播恢复到可用直播位置。
- 一轮故障最多自动刷新一次;仍失败则按配置尝试其他播放线路或提示用户重试/换源。 不同候选线路每轮至多尝试一次,AUTH_REQUIRED、AUTH_EXPIRED、CONTENT_LOCKED 不自动轮询撞线。 下载只在容器与范围连续性允许时续传,否则重启当前文件或提示失败,不能拼接不兼容字节。
6. 调度与生命周期
API、交互式播放和下载分别排队;当前播放优先,图片不能占满分片队列,预取与下载让位于前台播放。 具体速率、并发、缓存大小属于宿主策略;主机 Retry-After 冷却及网络规则适用于全部队列。 取消一个共享资源的等待者不应中断其他会话仍使用的传输。
普通空闲卸载后,会话仍可用相同插件修订恢复变换与刷新。停用、移除、更新插件,或修改其设置、站点线路时, 宿主先停止依赖它的会话并提示重新播放,再取消调用、替换代码/请求环境及重建; 不把新插件环境悄悄应用到旧会话。检查更新、查看日志与清缓存本身不停止播放。 历史、收藏与各来源进度独立保存,不因会话结束而删除。
7. 跨端验收与后台行为
“同一 JS 运行时”只保证语言与 API 语义一致,不保证所有设备解码同一种媒体。
hg.env.media 必须反映当前播放路径可用的能力;不能仅凭系统解码器名称声明 WebView 能播放。
HLS 与可播放的 progressive 是核心播放路径,DASH、ASS 渲染、后台播放、后台下载按平台实际支持处理。
至少验证:带头图片、Cookie 媒体、HLS 多级清单与密钥、MP4 拖动、字幕、地址刷新、取消, 以及确实声明的 DASH/分片变换。每个目标平台都要验证从本地会话地址到实际播放器的完整链路。
应用进入后台时,宿主可在平台许可范围内保留活跃媒体会话,按需调用插件刷新、变换或回报进度。 没有媒体任务时不运行插件;系统真正挂起进程后不承诺 JS、网络或定时器继续执行。 恢复时重建必要运行时、检查会话有效期后再续播,不以持续后台执行为协议前提。