如何用html5下载视频播放器

7次阅读

html5 标签原生不支持下载,download属性仅对有效;可靠方案是用配合video.src动态获取链接,同源直接下载,跨域需fetch+blob构造url,并注意mime类型、文件后缀及服务端权限接口配合。

如何用html5下载视频播放器

html5 <video></video> 标签本身不支持“下载”功能

浏览器原生 <video></video> 播放器默认没有下载按钮,controls 属性只提供播放/暂停/音量等基础控件,不包含下载入口。这不是你配置错了,是规范如此——W3C 明确未将下载列为标准控制项。

常见错误现象:download 属性加在 <video></video> 上完全无效(它只对 <a></a> 生效);用 jsvideo.src 直接发起 GET 请求,结果返回 403 或跨域拒绝;或者误以为加了 crossorigin 就能触发下载,其实只是影响资源加载策略。

  • 真正可下载的前提:视频资源必须允许跨域(服务端返回 access-Control-Allow-Origin: *),且你有该资源的直链(不是动态 Token 签名或 referer 限制链接)
  • 如果视频来自第三方平台(如 YouTube、腾讯视频),它们的 src 是播放页或接口,不是视频文件地址,直接下载必然失败
  • 移动端 safari 对自动触发下载极其严格,即使满足条件,也常静默失败

<a download></a> 绕过限制最可靠

核心思路:不操作 <video></video>,而是把视频地址塞进一个隐藏的 <a></a> 标签,再用 JS 触发点击。这是目前兼容性最好、行为最可控的方式。

实操要点:

立即学习前端免费学习笔记(深入)”;

  • download 属性只在同源 URL 下生效;若视频是跨域资源,需先用 fetch + Blob 构造本地 URL,再赋给 a.href
  • 避免直接写死路径,优先从 video.currentSrcvideo.src 动态取值,兼容 <source></source> 切换场景
  • Safari 15.4+ 才支持 Blob URL 的 download,旧版需降级为打开新标签页(window.open(url)

简短示例:

const video = document.querySelector('video'); const link = document.createElement('a'); link.download = 'my-video.mp4';  // 同源情况(最简单) if (video.src.startsWith(window.location.origin)) {   link.href = video.src;   link.click(); }  // 跨域情况(需 fetch) else {   fetch(video.src)     .then(r => r.blob())     .then(blob => {       link.href = URL.createObjectURL(blob);       link.click();       URL.revokeObjectURL(link.href); // 及时释放     }); }

服务端配合才能解决「带权限」视频下载

如果你的视频受登录态、时间戳签名、IP 限制等保护,前端 JS 拿到的 video.src 往往是临时有效链接。此时直接下载会因签名过期或 header 缺失而失败。

必须的服务端改动:

  • 提供一个专用下载接口(如 /api/video/download?id=123),由后端校验权限后,以 Content-Disposition: attachment 响应流式转发视频
  • 禁止前端暴露原始视频 URL;所有下载请求走这个接口,由后端透传必要的认证信息(如 cookie 或 bearer token)
  • 注意大文件响应超时问题,nginx/apache 需调高 proxy_read_timeout 或启用 X-Accel-Redirect

别忽略 MIME 类型和文件后缀

用户点下载后打不开,大概率不是代码问题,而是服务端没返回正确的 Content-Type,或前端没指定合理后缀。

  • MP4 视频应返回 video/mp4,否则 chrome 可能拒绝下载或保存为无扩展名文件
  • <a download="xxx"></a> 中的文件名最好带后缀(如 "clip.mp4"),否则 Safari 默认存为 unknown
  • Blob 构造时,务必传入正确 type:new Blob([data], {type: 'video/mp4'}),否则 URL.createObjectURL() 生成的链接可能被识别为 text/plain

复杂点在于:同一段视频可能有多种编码格式(H.264/AV1)、容器(MP4/WebM),服务端返回的 MIME 和实际内容不一致时,下载后的文件大概率无法播放——这得靠服务端日志和 ffprobe 校验,前端基本无解。

text=ZqhQzanResources