网站播放BLOB视频触发VIDEOJS ERROR(CODE:4)的原因与解决方案
问题:MP4转Blob后VideoJS无法播放,报错MEDIA_ERR_SRC_NOT_SUPPORTED
控制台错误信息
VIDEOJS: ERROR: (CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED) The media could not be loaded, either because the server or network failed or because the format is not supported.
相关代码
HTML按钮代码
<a class="btn btn-hover videoID" onclick="enableVideoJS();" data-fancybox="" data-type="video" data-src="blob:https://mywebsite.com/7007535b-a807-4e28-b62b-2274cc9f6f34" href="javascript:;"><i class="fa fa-play mr-1" aria-hidden="true"></i>Watch Show</a>
VideoJS渲染后的视频元素
<video class="vjs-tech" autoplay="" controlslist="nodownload" disablepictureinpicture="true" poster="" id="vjs-play19_html5_api" tabindex="-1"> <source src="blob:https://mywebsite.com/7007535b-a807-4e28-b62b-2274cc9f6f34" type="video/mp4"></video>
当前JavaScript代码
// Grab all videoID class URL in DOM - Currently 6 videos with Class of videoID let attributes = $(".videoID").map(function () { return $(this).attr("data-src"); }).get(); // Output array to console console.log(attributes); // // Console shows URLS converted to BLOB from video/mp4 // // Array(6) // 0: "blob:https://mywebsite.com/63d21c8d-5950-42a0-a46d-9eb4d61046e6" // 1: "blob:https://mywebsite.com/6ce5a525-e0c4-4a52-ae6a-16298072ba68" // 2: "blob:https://mywebsite.com/4f4cf9b8-2699-4936-82de-d5226a2b98de" // 3: "blob:https://mywebsite.com/fe6683c7-0865-4d47-8575-bc6a5ecadf8d" // 4: "blob:https://mywebsite.com/01b7ee54-ff4d-4bc7-bd2a-1331a71cce27" // 5: "blob:https://mywebsite.com/7007535b-a807-4e28-b62b-2274cc9f6f34" // Create blob looping through attributes length - in this case is 6 video URLS for (let i=0; i < attributes.length; i++){ let url = URL.createObjectURL( new Blob([attributes[i]], { "type" : "video\/mp4; codecs=\"avc,aac\"" }) ); // Update source with blob URL, writing over current values attributes[i] = url; $(".videoID").attr("data-src", attributes[i]); }
问题根源
你当前的代码逻辑完全错误:你把原始的Blob URL字符串当成了视频二进制数据,重新包装成了新的Blob对象,这相当于把一段文本(原Blob地址)当成了视频文件内容,浏览器自然无法识别成有效的MP4格式,因此触发了格式不支持的错误。
正确解决方案(隐藏源URL)
方案1:MediaSource API流式加载(推荐大文件)
你的视频体积在300MB-1.2GB,直接生成Blob会占用大量内存,更适合用MediaSource实现流式加载,同时隐藏真实URL:
- 修改HTML,将真实视频URL存入
data-original-src:
<a class="btn btn-hover videoID" data-fancybox="" data-type="video" data-original-src="真实MP4文件URL" href="javascript:;"><i class="fa fa-play mr-1" aria-hidden="true"></i>Watch Show</a>
- 替换原有JS逻辑,绑定点击事件实现流式加载:
$(".videoID").click(async function(e) { e.preventDefault(); const originalVideoUrl = $(this).data("original-src"); const videoElement = document.getElementById("vjs-play19_html5_api"); const mediaSource = new MediaSource(); videoElement.src = URL.createObjectURL(mediaSource); mediaSource.addEventListener("sourceopen", async function() { // 注意:这里的codecs要和你的视频实际编码匹配,可通过ffmpeg查看 const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E, mp4a.40.2"'); const response = await fetch(originalVideoUrl); const reader = response.body.getReader(); while(true) { const { done, value } = await reader.read(); if (done) break; sourceBuffer.appendBuffer(value); // 等待缓冲区更新完成,避免溢出 await new Promise(resolve => sourceBuffer.addEventListener("updateend", resolve, { once: true })); } mediaSource.endOfStream(); // 触发VideoJS播放逻辑 enableVideoJS(); }); });
方案2:正确生成Blob(适合小文件)
如果一定要用Blob,必须先下载视频的二进制数据,再包装成Blob,而不是把URL字符串包装:
// 批量处理所有视频按钮 $(".videoID").each(async function() { const $btn = $(this); const originalUrl = $btn.data("original-src"); // 下载视频二进制数据 const response = await fetch(originalUrl); const videoBlob = await response.blob(); // 生成有效的Blob URL const blobUrl = URL.createObjectURL(videoBlob); // 更新按钮的data-src $btn.data("src", blobUrl); });
关键注意事项
- 确保视频编码是浏览器支持的标准MP4编码(H.264/AVC视频 + AAC音频),可以用
ffmpeg -i 你的视频文件.mp4命令查看编码信息 - 如果视频和网站不同域,服务器必须配置CORS,允许你的网站跨域请求视频文件
- 大视频优先用MediaSource流式加载,避免内存占用过高导致浏览器崩溃
内容的提问来源于stack exchange,提问作者CraigJem10
相关产品推荐
相关产品推荐

