MediaSource本身不解密,仅向video元素输送加密媒体数据,解密由浏览器EME机制自动完成;需先初始化MediaKeys并绑定video,再通过SourceBuffer写入加密片段,由encrypted事件触发密钥请求与更新,实现加密流实时挂载。

MediaSource 接口本身不负责解密,它只负责将媒体数据(如 MP4、WebM 片段)以二进制形式喂给 <video> 元素。加密媒体流(如 AES-128 或 CENC 加密的 DASH/HLS)的解密工作由浏览器内置的 EME(Encrypted Media Extensions)机制完成,MediaSource 是其数据供给通道。实现“加密媒体流的解密与实时挂载”,本质是将 EME 与 MediaSource 协同使用:先建立加密上下文(MediaKeys),再通过 SourceBuffer 持续写入加密片段,由浏览器自动触发密钥获取与解密。
准备加密媒体环境(EME 初始化)
在创建 MediaSource 前,必须为 <video> 元素绑定支持的 MediaKeys 实例,否则后续写入加密内容会触发 encrypted 事件失败或直接报错。
- 调用
video.setMediaKeys(new MediaKeys(...)),其中MediaKeys需通过navigator.requestMediaKeySystemAccess()获取合法访问权限(指定 key system 如"com.widevine.alpha"或"com.microsoft.playready") - 确保视频元素已设置
crossOrigin="anonymous"(尤其当密钥服务器跨域时) - 监听
encrypted事件——该事件由浏览器在解析到加密头(如 PSSH box 或 HLS #EXT-X-KEY)时自动触发,携带初始化数据(initData)和类型(initDataType)
关联 MediaSource 与加密上下文
MediaSource 实例必须在 video.src 赋值前,且需确保其 mediaKeys 属性已被正确设置(现代浏览器要求 MediaSource 实例与 video 共享同一组 MediaKeys)。
- 创建
MediaSource后,立即赋值给video.src = URL.createObjectURL(mediaSource) - 在
mediaSource.sourceopen事件中,调用mediaSource.addSourceBuffer('video/mp4; codecs="avc1.640029"')(注意 MIME 类型需匹配实际流格式与编码) - 关键点:若未提前为 video 设置
mediaKeys,addSourceBuffer可能抛出InvalidStateError;若已设置但 key system 不兼容,写入加密数据时会触发error事件
处理加密初始化与密钥请求
当 SourceBuffer 接收含加密元数据的初始化段(init segment)时,浏览器会解析其中的 PSSH(PlayReady/Widevine)或 KID(CENC),并派发 encrypted 事件。你需要在此响应密钥请求。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
立即学习“前端免费学习笔记(深入)”;
- 在
video.addEventListener('encrypted', handler)中,用mediaKeys.createSession()创建会话,调用session.generateRequest(initDataType, initData) - 将生成的
message(通常是 license request)发送至密钥服务器;收到 license 响应后,调用session.update(licenseResponse) - 成功更新后,浏览器自动解密后续写入的加密媒体块(moof+mdat),无需手动干预解密逻辑
实时挂载加密片段(DASH/HLS 分段策略)
“实时挂载”指持续拉取、解析、写入加密的媒体分片(如 .mp4 init + chunk,或 WebM clusters),保持播放缓冲区不断供。
- 按时间线顺序 fetch 加密分片(建议使用
fetch().arrayBuffer()获取原始二进制) - 检查
sourceBuffer.updating === false且mediaSource.readyState === 'open'后,调用sourceBuffer.appendBuffer(arrayBuffer) - 对每个分片,确保其包含完整 moof(含 tenc box 指明加密参数)和 mdat;若缺失 init segment,需先 append init segment(仅一次)
- 可结合
sourceBuffer.buffered和video.currentTime实现自适应追播(如直播低延迟场景)
整个流程依赖浏览器原生 EME 解密能力,开发者只需正确串联事件流、管理密钥会话、按时序写入合规加密片段。不涉及 JS 层解密运算,也不需手动解析 AES 或 CENC 结构。


















