禁用投屏需三层措施:html层加disablepictureinpicture和controlslist="nodownload noremoteplayback",服务端禁accept-ranges: bytes,系统级镜像则需drm。

video 标签加 disablePictureInPicture 属性就行
浏览器原生支持防投屏,不需要 JS 介入或第三方库。关键就一个布尔属性:disablePictureInPicture,加在 <video></video> 标签上即可禁用画中画(Pip),而画中画是多数投屏链路的前置步骤——禁了 Pip,主流桌面/移动端浏览器(Chrome、Edge、Safari 16.4+、Firefox 109+)的“投屏到此设备”功能基本就失效了。
注意:这不是 100% 拦截所有投屏方式(比如系统级屏幕镜像、录屏软件仍可捕获),但对普通用户点击右键“投射”或地址栏投屏按钮已足够有效。
-
<video disablepictureinpicture controls></video>—— 最简写法,属性存在即生效 - 若需动态控制,可用 JS:
videoEl.disablePictureInPicture = true(注意不是 setAttribute) - Safari 要求同时设置
webkit-playsinline和playsinline,否则可能忽略该属性
必须配合 controlslist="nodownload noremoteplayback"
单靠 disablePictureInPicture 不够——用户仍可能通过右键菜单下载、或用手机远程播放(AirPlay / Chromecast 后台通道)。controlslist 是 Chrome/Edge 的扩展属性,能隐藏原生控件里的敏感项:
-
noremoteplayback直接禁用 AirPlay / Cast 按钮(iOS Safari 也认这个) -
nodownload隐藏下载图标(虽不能阻止开发者工具里扒资源,但挡掉大部分小白用户) - 写法:
<video controlslist="nodownload noremoteplayback" disablepictureinpicture></video> - 注意:Firefox 不支持
controlslist,但它的投屏入口本就较弱;Safari 对noremoteplayback支持良好
服务端要关掉 Accept-Ranges: bytes 才真防拖拽
前端属性只是障眼法。如果视频是 HTTP Range 请求可分段加载(即响应头含 Accept-Ranges: bytes),用户用 DevTools 抓到 URL 后,仍可通过 curl 或 IDM 拖拽下载整片。真正防住得动服务端:
- 静态资源服务器(如 Nginx)配置中移除或禁用
add_header Accept-Ranges bytes; - 或让后端返回视频时显式设响应头:
Accept-Ranges: none - 此时浏览器只能顺序加载,无法跳播、也无法用工具断点续传下载
- 代价:进度条拖拽失效,快进/快退变成重新请求整个文件(影响体验,需权衡)
别信 oncontextmenu 或 preload="none" 这类伪方案
有人试过禁右键、关预加载来“防投屏”,实际无效:
-
oncontextmenu="return false"只拦网页右键,不影响地址栏投屏按钮、系统快捷键(Win+K)、或手机下拉菜单里的投屏开关 -
preload="none"仅推迟加载,不改变视频可被发现和投射的本质 - 用
object或iframe包一层 video?现代浏览器照样识别内部媒体流,投屏照常 - 真正起效的只有:浏览器认可的原生媒体控制属性 + 服务端传输策略
防投屏没有银弹。能做的就是三层卡位:HTML 层用 disablePictureInPicture 和 controlslist 关掉入口,服务端用 Accept-Ranges: none 切断分片能力,剩下系统级镜像和录屏,前端无解——得靠 DRM,那已是另一个量级的事了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











