
本文介绍通过 blob url + mediasource api 实现视频资源防直接下载的实用方案,虽无法 100% 防止录屏或抓包,但可有效屏蔽右键保存、地址栏输入、开发者工具篡改 controls 属性等常见盗链行为。
本文介绍通过 blob url + mediasource api 实现视频资源防直接下载的实用方案,虽无法 100% 防止录屏或抓包,但可有效屏蔽右键保存、地址栏输入、开发者工具篡改 controls 属性等常见盗链行为。
在 Web 视频分发场景中,仅靠 controls="false" 或 controlslist="nodownload" 并不能真正阻止用户下载视频——这些属性纯属客户端提示,可被开发者工具轻易绕过(如手动添加 controls 属性、删除 controlslist、甚至直接访问
✅ 推荐方案:使用 URL.createObjectURL() + MediaSource
核心思路是:不将原始视频 URL 暴露在 HTML 中,而是通过 JavaScript 动态获取视频二进制数据(如通过 fetch),将其注入 MediaSource 对象,再生成一个仅在当前页面生命周期内有效的 Blob URL。该 URL 形如 blob:https://example.com/xxxx-xxxx-xxxx,无法被外部访问,也无法通过网络面板直接复用下载(除非完整捕获所有分片并拼接)。
以下为完整实现示例:
<video id="securePlayer" width="800" height="450" preload="none"></video>
<script>
const video = document.getElementById('securePlayer');
const mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', async () => {
const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.64001f"');
try {
// 替换为你的实际视频接口(建议后端做鉴权 & 分片)
const response = await fetch('/api/video/stream?token=xxx');
const reader = response.body.getReader();
let chunks = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
}
const allBytes = new Uint8Array(
chunks.reduce((acc, chunk) => acc + chunk.length, 0)
);
let offset = 0;
chunks.forEach(chunk => {
allBytes.set(chunk, offset);
offset += chunk.length;
});
sourceBuffer.appendBuffer(allBytes);
sourceBuffer.addEventListener('updateend', () => {
mediaSource.endOfStream();
});
} catch (err) {
console.error('视频加载失败:', err);
video.controls = true; // 降级显示原生控件便于调试
}
});
</script>⚠️ 注意事项:
立即学习“前端免费学习笔记(深入)”;
- 服务端必须支持流式响应(Content-Type: video/mp4 + Transfer-Encoding: chunked)且开启 CORS;
- MediaSource 仅支持特定容器与编码格式(推荐 MP4 + H.264/AAC),需确保服务端输出符合规范;
- fetch 获取的原始数据需完整拼接为 Uint8Array 后传入 appendBuffer(),不可直接传递 Blob 或 ArrayBuffer(部分浏览器兼容性问题);
- 此方案不阻止高级用户通过 Network 面板抓取分片请求,因此建议配合 Token 鉴权、IP 限速、Referer 校验及短期有效期 URL 等后端策略;
- 移动端 Safari 对 MediaSource 支持有限(iOS 15.4+ 才完全支持 MSE),生产环境需做降级处理(如 fallback 到加密 HLS)。
❌ 不推荐的“伪防护”方式(务必避免)
- 仅设置 controlslist="nodownload":Chrome 会隐藏下载按钮,但用户仍可通过右键 → “另存为” 或修改 DOM 恢复下载入口;
- 使用 vid.controls = false + 自定义 UI:无法阻止用户在控制台执行 vid.src = 'original.mp4';
- 将视频 base64 编码嵌入 src:导致首屏加载极慢、内存暴涨,且 base64 字符串仍可被复制解码。
? 总结
没有绝对不可下载的前端视频方案——所有客户端资源均可被有心人获取。但通过 Blob URL + MediaSource 可显著提升盗取门槛:它让视频脱离静态资源路径,切断直接引用链,并迫使攻击者必须逆向整个流式加载逻辑。真正的安全应是“前后端协同防御”:前端负责混淆与体验隔离,后端承担身份核验、行为审计与动态密钥分发。将视频视为服务而非文件,才是可持续的内容保护起点。











