HTML5 video无原生防投屏接口,仅能通过disableRemotePlayback提示禁用远程播放(非强制),或结合服务端加密、动态水印、跨域限制等手段提高盗用成本。

HTML 视频本身没有「防投屏」接口。浏览器不提供阻止用户点击 Chrome 右上角 Cast 按钮、或禁用系统级投屏功能的 API —— 这是故意设计的安全限制,防止网页恶意干扰用户设备控制权。
你真正能干预的,只有两个层面:**不让视频被 Cast SDK 主动发现**,以及**让投屏后的内容不可用或无意义**。下面分场景说明怎么做。
为什么 video 标签加 disablePictureInPicture 不等于防投屏
这个属性只影响画中画(PiP),和 Chromecast / AirPlay / DLNA 等投屏协议完全无关。设了 disablePictureInPicture="true" 后,用户仍可正常点 Cast 按钮投整个标签页,视频照样出现在电视上。
常见错误现象:cast.framework.CastContext.getInstance() 返回 null 或静默失败,但页面里视频还在播——这说明 Cast SDK 没初始化成功,不是“防住了”,而是“根本没接入”。
实操建议:
- 若你没主动引入
cast_sender.js且没调用 Cast SDK,那默认就是“不可被 Cast SDK 控制”的状态,无需额外操作 - 若已接入 Cast SDK,想阻止特定视频被投,应在
CastSession建立后监听mediaStatus,并在服务端返回的媒体信息里设置contentProtection字段为"drm_required"(仅对自定义接收端生效) -
disableRemotePlayback="true"属性在部分 Android 浏览器中可隐藏 Cast 按钮,但 iOS Safari 和桌面 Chrome 完全无视它
真正有效的“软性防投屏”:服务端转流 + 内容混淆
当用户投的是整个页面(而非单个视频流),你能控制的只剩服务端输出。目标不是“禁止投”,而是让投出去的内容失去价值。
立即学习“前端免费学习笔记(深入)”;
实操建议:
- 用 HLS 方案时,在
.m3u8中启用 AES-128 加密,并确保 key URL 带有时效 token(如/key?exp=1734642000&sig=xxx),投屏端无法复用该 key - 对关键帧插入动态水印(时间戳+用户 ID),水印位置随播放进度偏移,靠前端 Canvas 绘制;投屏后水印仍在,但录屏/截屏即暴露身份
- 禁用服务端的
Access-Control-Allow-Origin: *,改为只允许你的主域名;这样即使用户用开发者工具复制src直接访问,也会因跨域被浏览器拦截 - 避免使用明文 RTMP/FLV 直播地址;若必须用,应在 Nginx 层做 referer 鉴权或 IP 白名单,防止地址泄露后被第三方拉流
移动端 WebView 场景下怎么限制投屏行为
Android WebView 默认开启 MediaRouter,iOS WKWebView 则默认屏蔽 AirPlay 按钮——但用户仍可通过系统级分享菜单投整个页面。
实操建议:
- Android:在
WebSettings中调用setMediaPlaybackRequiresUserGesture(true),强制所有播放需用户点击触发;再配合onShowCustomView拦截全屏请求,间接降低投屏意愿 - iOS:在 WKWebView 初始化时设置
allowsInlineMediaPlayback = false,并移除webkit-playsinline属性,使视频强制全屏;全屏状态下系统 AirPlay 按钮不可见(但非绝对可靠) - 更彻底的做法:在
video的play事件回调中,立即执行document.exitFullscreen()(如果刚进全屏),打断系统投屏入口的触发时机
src 后用 VLC 或 ffplay 直接拉流——这种行为任何前端手段都拦不住。防投屏的本质,是提高盗用成本,而不是追求技术上的“绝对禁止”。



















