从 HTML5 Video 到 MSE、DASH 与 Shaka Player
在早期的前端视频开发中,<video> 标签几乎可以承担所有播放任务:设置 src、控制播放、暂停、倍速即可。然而,在一个更贴近真实视频网站的视频播放器实现中,例如构建一个类似 Bilibili 的小型项目,会很快遇到 <video> 的天然限制:
- 大文件加载慢
- 无法按需分片加载
- 难以支持自适应码率
- 不支持多清晰度无缝切换
- 在 Electron + Web 环境中容易受平台解码能力影响
- DRM、直播、长视频跳转等能力有限
这类问题在中大型平台已经有成熟的解决方案,核心技术包括 MSE(Media Source Extensions)、DASH(Dynamic Adaptive Streaming over HTTP)、MPD(DASH 的清单文件格式) 以及配套的播放器库 Shaka Player。
在构建小型 Bilibili 项目时,引入这些技术能让播放器具备更专业、更现代化的能力。
1. 为什么不能继续用 <video>?
1.1 Buffer 加载模式的局限
<video> 的默认行为是串流拉取整个 MP4 文件,这导致:
- 初始加载慢
- 跳转到后面片段时需要重新请求头部数据
- 清晰度切换要重新加载整个视频
- 播放过程无法自适应网络波动
对一个类似 Bilibili 的平台来说,用户操作非常频繁:跳转、倍速、清晰度切换,这意味着必须支持更高的灵活性。
1.2 无法满足现代流媒体需求
现代视频网站普遍使用 分片化格式(fragmented MP4 / TS) 和 自适应码率(ABR)。
这些都需要浏览器控制视频缓冲区,而 <video> 做不到。
这时就要靠 MSE。
2. MSE:现代流媒体的关键能力
MSE(Media Source Extensions) 是浏览器提供的一组 API,用来让 JavaScript 在运行时手动向 <video> 的缓冲区塞数据。
其核心是:
MSE 允许应用自行维护播放器缓冲区,从而实现分片拉取、动态插入、网络自适应控制等能力。
2.1 MSE 能实现什么?
- 通过 XHR / Fetch 分片拉取视频
- 按需向 SourceBuffer 推入数据
- 根据网络情况调整清晰度
- 直播持续往缓冲区注入新切片
- 利用浏览器提供的解码能力播放不同格式(mp4, webm, ts)
于是,播放器的控制权从 <video> 转移到应用层。
2.2 MSE 本身并不负责所有功能
MSE 只是一个“底层能力”。
如果要构建一个完整播放器,还需要:
- 清晰度逻辑
- 码率切换
- 缓冲管理
- MP4/TS 解析
- DRM
- 直播时延优化
- 音视频轨道管理
手写这些成本极高,因此行业中更常使用 DASH + MPD + 播放器库(如 Shaka)。
3. DASH 与 MPD:自适应流媒体的行业标准
3.1 DASH 是什么?
DASH(Dynamic Adaptive Streaming over HTTP) 是视频分片传输的一套协议规范。
核心思想是:
- 将一个视频切成几十到数百个小片段(1–6 秒)
- 每个片段有多种码率和分辨率
- 播放器根据网络实时选择合适的片段
- 整个过程基于 HTTP,不需要额外协议
这就是常说的 **自适应码率 (ABR)**。
3.2 MPD:DASH 的“清单文件”
要播放 DASH,就需要一个 MPD(Media Presentation Description)文件。
MPD 文件包含:
- 视频的所有清晰度
- 每个片段的时长和 URL
- 直播窗口信息
- 编码参数
- DRM 信息
- 多音轨、多字幕信息
简而言之:
MPD = 视频播放的“地图 + 目录”。
一个类似 Bilibili 的项目需要清晰度多版本管理,MPD 正好解决了视频资源描述问题。
4. Shaka Player:企业级流媒体播放框架
许多库都支持 MSE(hls.js, dash.js, Video.js)。
但在一个结合 Web 与 Electron 的小型视频网站项目中,Shaka Player 是更稳妥的选择,原因包括:
4.1 全平台支持
- Web
- Electron
- 原生 DRM
- DASH / HLS 自动兼容
- 完整 MSE 控制
4.2 原生支持 DRM(Widevine)
无需额外插件,直接支持:
- Widevine
- PlayReady
对于 Electron 视频平台,这非常重要,因为 Chrome 内核本身就是 DRM 的最佳宿主环境。
4.3 不依赖第三方转码库
Shaka 不需要浏览器原生支持 HLS,它能把 HLS 转成 MSE 可播放的格式。
4.4 API 粒度高
适合深度定制播放器(弹幕同步、倍速、进度管理、清晰度切换等)。
5. 将这些技术应用到个人 Bilibili 项目中
项目目标:
构建一个 Web + Electron 的小型 Bilibili 客户端,支持 DASH、清晰度切换、视频分片加载,并实现可靠的播放体验。
下面将整个技术路线完整结合起来。
5.1 资源准备:将视频切成 DASH 分片并生成 MPD
一般流程:
使用 FFmpeg 或转码服务生成:
- 多码率视频(240P/480P/720P/1080P)
- 分片(segment)
生成 MPD 文件
将所有资源放在 CDN 或服务器可访问位置
5.2 播放端架构:Electron + Web + Shaka Player
播放器流程:
1 | CDN / 服务器 |
Shaka 负责:
- 读取 MPD
- 选择合适的视频分片
- 进行 ABR
- 控制 MSE buffer
- 支持清晰度切换 + 码率切换
- DRM 解密(如果使用)
应用只需要:
- 调用 Shaka API
- 提供 UI(播放按钮、清晰度列表等)
5.3 为什么这种结构适合一个“个人 Bilibili”项目?
稳定的 DASH 播放能力
普通 <video> 无法支持分片、清晰度列表、码率自适应。
方便扩展
未来可以扩展:
- 直播
- DRM
- 多音轨
- 弹幕同步
- 预加载策略优化
- 缓冲区监控
Shaka 提供 API 完全满足。
Web + Electron 统一开发
Electron 使用 Chromium 内核,兼容 MSE 和 DRM 标准,是开发播放器的绝佳环境。