Shaka Player v2.3 升级到 v2.5:完整 API 变更指南与迁移实战
【免费下载链接】shaka-playerJavaScript player library / DASH & HLS client / MSE-EME player项目地址: https://gitcode.com/GitHub_Trending/sh/shaka-player
本文是基于 Shaka Player 官方升级文档 docs/upgrades/upgrade-v2.3-to-v2.5.md 编写的深度指南,系统梳理从 v2.3 升级到 v2.5 过程中所有破坏性 API 变更、废弃字段与新增能力,并结合当前仓库源码验证每个变更点的实际实现。阅读完成后,你可以对照本文逐项排查自己的应用代码,完成插件、网络层、离线存储、字幕渲染等模块的平滑迁移。
一、v2.5 带来了什么:新特性总览
Shaka v2.5 相比 v2.3 引入了大量新能力,其中多数新特性都影响应用侧的集成方式:
- 官方 UI 库:提供可定制、可样式化的视频控件,通过加载
dist/shaka-player.ui.js使用,完整教程见 docs/tutorials/ui.md; - Demo 应用全新改版,服务工作者(PWA)能力增强;
- FairPlay DRM 支持;
- iOS 与 Safari 上的原生 HLS 支持;
- 单文件(非清单)内容播放支持;
- 切换流时网络请求可被中止(配合新的可中止网络 API);
- SMPTE-TT 字幕的部分支持,以及 TTML / VTT 区域(Region)的完整支持;
- CEA 隐藏字幕支持;
- DASH 直播流的漂移容忍(默认开启);
- PlayReady 许可证 URL 解析(
ms:laurl); - HLS 中 Widevine SAMPLE-AES 支持;
- 新增配置字段可忽略清单中的
minBufferTime; - 无需 Player 实例即可进行离线存储;
- 清空缓冲区新增安全余量(safe margin)参数;
- 构造
Player时不再强制要求传入 video 元素; Fetch优于XHR被优先选用(可用时);- 直播流可以从直播边缘的负偏移处开始播放。
这些新特性中,凡是涉及 API 签名变化的,都会影响存量应用。从下一节开始,我们按主题逐一拆解所有破坏性变更。
二、Extern 命名空间变更:shakaExtern→shaka.extern
如果你的项目使用 Closure Compiler,必须知道 v2.5 将外部类型(externs)的命名空间从shakaExtern改成了shaka.extern。插件接口、清单类型等所有引用都必须同步更新,否则编译期类型检查会失败。
从当前仓库源码可以看到,externs/shaka/namespace.js 中正是以shaka.extern = {};的形式声明该命名空间,后续所有externs/shaka/*.js中的插件与数据类型都挂载在此命名空间下。
迁移示例(以网络过滤器为例):
// v2.3: /** * @param {shaka.net.NetworkingEngine.RequestType} type * @param {shakaExtern.Request} request * @return {!Promise} */ function myFilter(type, request) { /* ... */ } // v2.5: /** * @param {shaka.net.NetworkingEngine.RequestType} type * @param {shaka.extern.Request} request * @return {!Promise} */ function myFilter(type, request) { /* ... */ }三、Player.load()/Storage.store()工厂参数改为 MIME 类型
v2.5 将Player.load()与Storage.store()的可选Factory参数改为MIME 类型字符串。Factory参数已被标记为废弃,并将在 v3.0 移除。任何已注册的解析器(parser)都可以通过其注册的 MIME 类型被引用。
// v2.3: player.load('foo.mpd', /* startTime= */ 0, /* factory= */ shaka.dash.DashParser); // v2.5: player.load('foo.mpd', /* startTime= */ 0, /* mimeType= */ 'application/dash+xml');这一变更让调用方不再需要关心具体解析器类,只需声明媒体类型(如application/dash+xml、application/x-mpegurl),由 Player 内部按 MIME 类型路由到对应解析器,为后续新增格式提供了更干净的扩展点。详细签名见shaka.Player#load(当前实现位于 lib/player.js)。
四、getManifestUri()重命名为getAssetUri()
由于 v2.5 开始支持非清单内容(如单文件播放),Player.getManifestUri()被重命名为Player.getAssetUri(),旧方法废弃并将在 v3.0 移除。
// v2.3: const uri = player.getManifestUri(); // v2.5: const uri = player.getAssetUri();该新方法在当前源码中已被广泛使用,例如 lib/cast/cast_proxy.js 在同步 Cast 会话状态时调用this.localPlayer_.getAssetUri(),lib/ads/svta_ad_manager.js 也用它判断当前资产 URI。可以推断,凡是依赖旧getManifestUri()的应用逻辑(包括自定义 Ad 管理器、Cast 集成等)都应同步迁移。
五、文本解析插件(TextParser)API 变更
v2.5 对TextParser插件 API 有两处破坏性调整,v2.5 没有为此提供向后兼容,所有应用自定义的文本解析插件必须更新:
segmentStart可为空:shakaExtern.TextParser.TimeContext的segmentStart属性现在允许为null。当信息不可用时(例如 HLS 场景),你的插件会收到null值,必须做好空值处理。Region 结构升级为
shaka.text.CueRegion类:产出字幕区域(region)信息的文本解析插件,必须改用新的shaka.text.CueRegion类。新结构能够更精确地同时表达 TTML 与 VTT 的 region 语义(包括定位、尺寸、书写模式等属性)。
参考接口shaka.extern.TextParser.TimeContext与shaka.text.CueRegion(当前实现见 lib/text/cue_region.js)。
六、文本显示插件(TextDisplayer)API 变更:Cue 结构重塑
TextDisplayer消费的Cue对象在 v2.5 中同样发生结构性变化,应用自定义的 TextDisplayer 插件也必须更新,且无向后兼容:
CueRegion结构变化:与 TextParser 的变更配套,更准确地表示 TTML / VTT region;Cue.writingDirection拆分:拆分为Cue.writingMode与Cue.direction两个独立字段,用于修复此前对这两个属性(如横排/竖排书写模式、文字方向)处理的 bug;- 新增
Cue.backgroundImage:允许在 Cue 上携带背景图。
参考接口shaka.extern.Cue与shaka.extern.CueRegion(当前定义见 externs/shaka/text.js)。
七、NetworkingEngine:request()返回可中止操作对象
v2.3 中shaka.net.NetworkingEngine.request()直接返回 Promise;v2.5 起返回shakaExtern.IAbortableOperation实例(内部包含一个 Promise)。旧 API 在 v2.5 中已被移除,所有通过NetworkingEngine发起应用层请求的代码必须更新。
// v2.3: const response = await player.getNetworkingEngine().request(type, request); // v2.5: const operation = player.getNetworkingEngine().request(type, request); // The operation can also be aborted on some condition. onSomeCondition(() => { operation.abort(); }); // Use operation.promise to get the response. const response = await operation.promise;这一变化直接支撑了前文提到的“切换流时可中止网络请求”能力:StreamingEngine在切换更优码率流时,可以提前 abort 正在进行的旧请求。当前 lib/net/networking_engine.js 中request(type, request, context)方法正是这一新 API 的实现入口。
八、网络协议插件(Scheme Plugin)三连变更
网络协议插件的 API 在 v2.4 与 v2.5 中连续演进,所有应用自定义的 scheme 插件必须更新,旧 API 在 v2.5 中已移除:
v2.4:返回值改为
IAbortableOperation。建议使用工具类shaka.util.AbortableOperation封装(返回 Promise 并携带 abort 逻辑);同时新增参数用于标识请求类型。v2.4:新增请求类型参数。插件签名变为
(uri, request, requestType)。v2.5:新增进度回调参数
progressUpdated。该回调只在分段请求(segment request)时提供,因此插件必须处理回调未提供的情况。若忽略该回调,带宽估算的收敛速度会变慢,且StreamingEngine将无法提前中止请求去切换更优的流。在可行的情况下,建议自定义插件尽量上报进度。
三段演进对应的完整示例:
// v2.3: function mySchemePlugin(uri, request) { return new Promise((resolve, reject) => { // ... }); } shaka.net.NetworkingEngine.registerScheme('foo', mySchemePlugin); // v2.4 (IAbortableOperation + requestType): function mySchemePlugin(uri, request, requestType) { let rejectCallback = null; const promise = new Promise((resolve, reject) => { rejectCallback = reject; // Use this if you have a need for it. Ignore it otherwise. if (requestType == shaka.net.NetworkingEngine.RequestType.MANIFEST) { // ... } else { // ... } // ... }); const abort = () => { // Abort the operation. // ... // Reject the Promise. rejectCallback(new shaka.util.Error( shaka.util.Error.Severity.RECOVERABLE, shaka.util.Error.Category.NETWORK, shaka.util.Error.Code.OPERATION_ABORTED)); }; return new shaka.util.AbortableOperation(promise, abort); } shaka.net.NetworkingEngine.registerScheme('foo', mySchemePlugin); // v2.5 (新增 progressUpdated 回调): function mySchemePlugin(uri, request, requestType, progressUpdated) { /// ... if (progressUpdated) { progressUpdated(/* timeElapsedMilliseconds= */ currentTime - lastTime, /* bytesLoaded= */, loaded - lastLoaded, /* byteRemaining= */, contentLength - loaded); lastTime = currentTime; lastLoaded = loaded; } /// ... } shaka.net.NetworkingEngine.registerScheme('foo', mySchemePlugin);注册接口的当前签名可在 lib/net/networking_engine.js 中确认:static registerScheme(scheme, plugin, priority, progressSupport = false)—— 第四个参数progressSupport即用于声明插件是否支持进度上报,默认false。进度回调类型参考shaka.extern.ProgressUpdated与shaka.extern.SchemePlugin。
九、网络过滤器新增请求类型:RequestType.TIMING
v2.5 引入了新的请求类型shaka.net.NetworkingEngine.RequestType.TIMING,用于 DASH 解析器中的时间同步请求。此前这类请求使用MANIFEST类型。若你的网络过滤器按请求类型区分处理逻辑,可选择性使用这一新类型来更精确地识别时间同步请求。
十、离线存储(Offline Storage)配置重构
v2.5 中shaka.offline.Storage.configure()改为接收完整的Player配置对象,而不是独立的 Storage 配置。原先位于 Storage 配置下的三个字段trackSelectionCallback、progressCallback、usePersistentLicense全部移入offline字段内。旧字段位置已废弃,将在 v3.0 移除。
三种迁移写法:
// v2.4: storage.configure({ trackSelectionCallback: myTrackSelectionCallback, }); // v2.5 —— 方式一:独立 Storage 配置 const storage = new shaka.offline.Storage(); storage.configure({ offline: { trackSelectionCallback: myTrackSelectionCallback, }, }); // v2.5 —— 方式二:与 Player 共享配置 const storage = new shaka.offline.Storage(player); player.configure({ offline: { trackSelectionCallback: myTrackSelectionCallback, }, }); // v2.5 —— 方式三:两参数 configure() const storage = new shaka.offline.Storage(player); player.configure('offline.trackSelectionCallback', myTrackSelectionCallback);新结构让离线存储直接复用 Player 的配置体系。当前 lib/offline/storage.js 中正是从config.offline.usePersistentLicense读取持久化许可证开关,印证了offline字段在存储流程中的实际使用位置。
同时,v2.5 新增Storage.removeEmeSessions()方法,用于清理并释放未被干净释放的离线 EME 会话,应用可按需调用。当前实现位于 lib/offline/storage.js,其内部通过startOperation_包装执行。
十一、Manifest 解析插件:PresentationTimeline 方法调整
shaka.media.PresentationTimeline的 API 发生变化,使用以下方法的ManifestParser插件必须更新:
setAvailabilityStart()重命名为setUserSeekStart();notifySegments()参数变化:不再接收“周期开始时间 + 引用数组”,而是接收“引用数组 + 布尔值isFirstPeriod”。
// v2.3: timeline.setAvailabilityStart(100); timeline.notifySegments(segmentList, /* periodStart= */ 0); // v2.5: timeline.setUserSeekStart(100); timeline.notifySegments(segmentList, /* isFirstPeriod= */ true);在 lib/media/presentation_timeline.js 中可以找到setUserSeekStart(time)的实现;notifySegments(references)的当前签名见 lib/media/presentation_timeline.js。isFirstPeriod布尔值用于标识这是否为清单解析过程中的第一个周期(period),使时间线能正确处理多周期清单的边界。
十二、attach()/detach():Player 与视频元素的解耦
v2.5 起,构造Player时不再强制要求传入 video 元素,并新增Player.attach()与Player.detach()方法用于管理 Player 与视频元素的挂载关系。这一改动支持了更灵活的生命周期管理:例如在广告预加载、多视频元素切换等场景下,可以先构造 Player 再按需挂载视频。当前实现位于 lib/player.js(attach(mediaElement, initializeMediaSource = true))与 lib/player.js(detach(keepAdManager = false, isSwitchingContent = false)),内部的加载流程(如 lib/player.js)也已基于 attach 重新组织。
十三、迁移检查清单
完成 v2.3 → v2.5 升级前,请逐项核对以下改动点:
| 变更主题 | 关键动作 | 破坏性 |
|---|---|---|
| 命名空间 | shakaExtern→shaka.extern(Closure Compiler 项目) | 必须 |
load()/store()工厂参数 | 改为 MIME 类型字符串 | 旧参数废弃(v3.0 移除) |
getManifestUri() | 改用getAssetUri() | 旧方法废弃(v3.0 移除) |
| TextParser 插件 | 处理segmentStart=null;改用CueRegion | 必须,无兼容 |
| TextDisplayer 插件 | writingDirection拆分;CueRegion变化;新增backgroundImage | 必须,无兼容 |
NetworkingEngine.request() | 返回IAbortableOperation,用operation.promise取响应 | 必须,旧 API 已移除 |
| Scheme 插件 | 返回IAbortableOperation;新增requestType与progressUpdated | 必须,旧 API 已移除 |
| 请求类型 | 新增RequestType.TIMING(DASH 时间同步) | 可选 |
| 离线存储配置 | 三个回调/开关移入offline字段 | 旧位置废弃(v3.0 移除) |
| PresentationTimeline | setUserSeekStart();notifySegments()新参数 | 必须(ManifestParser 插件) |
升级思路建议:优先处理标为“必须、无兼容”的四类插件接口(TextParser、TextDisplayer、Scheme 插件、ManifestParser),随后迁移网络层调用与离线存储配置,最后替换废弃方法。对于尚未用到的可选能力(如TIMING请求类型、removeEmeSessions()),可以按需渐进采用。若需跨多个大版本继续升级,可结合仓库内 docs/upgrades 目录下的其他升级文档(如 upgrade-v2.4-to-v2.5.md、upgrade-v2.5-to-v3.0.md)衔接后续版本的变化。
【免费下载链接】shaka-playerJavaScript player library / DASH & HLS client / MSE-EME player项目地址: https://gitcode.com/GitHub_Trending/sh/shaka-player
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考