javascript中的HTML5视频完整预加载

Posted

技术标签:

【中文标题】javascript中的HTML5视频完整预加载【英文标题】:HTML5 video full preload in javascript 【发布时间】:2012-03-25 20:26:51 【问题描述】:

我有一个高质量的视频,我不能压缩太多,因为它将成为大量图像分析的基础,其中每一帧都将被重新绘制到画布中,然后进行操作。

我正在尝试在播放之前预加载整个内容,因为我无法让视频停止、缓冲和继续播放。是否有我可以收听的事件表明整个视频在我开始播放之前已经预加载?

这是我在 JS/jQuery 中的做法:

this.canvas            = this.el.find("canvas")[0];
this.video             = this.el.find("video")[0];
this.ctx               = this.canvas.getContext("2d");
this.video.autoplay    = false;

this.video.addEventListener("play",this.draw)
this.video.addEventListener("timeupdate",this.draw)
this.video.addeventlistener("ended",this.trigger("complete",this))

【问题讨论】:

【参考方案1】:

这将在 javascript 中加载整个视频

var r = new XMLHttpRequest();
r.onload = function() 
    myVid.src = URL.createObjectURL(r.response);
    myVid.play();
;
if (myVid.canPlayType('video/mp4;codecs="avc1.42E01E, mp4a.40.2"')) 
    r.open("GET", "slide.mp4");

else 
    r.open("GET", "slide.webm");


r.responseType = "blob";
r.send();

【讨论】:

应该这样做!我仍然没有测试,但这正是我想要的。非常感谢。 "canplaythrough" 并不能真正解决我的问题。而且我不确定如何将您的问题视为已接受 @kroe 只需单击此答案旁边的勾号即可。 似乎我的视频播放器在暂停之前仍然只占用一定比例的下载量。在我的情况下,它预加载了大约 38-40%,然后等待视频开始播放,然后将文件的其余部分滴入其中。是否有解决方法来下载整个文件? 这个方法肯定会用 JavaScript 下载整个视频。使用 fiddler 或 chrome 中的网络选项卡检查您的网络流量以确保。其他所有方法都失败了,请使用 jplayer 或 popcorn.org 或 videojs 之类的库【参考方案2】:

canplaythrough 是当下载了足够的数据可以在没有缓冲的情况下播放时应该触发的事件。

来自 Opera 团队的优秀资源(虽然现在可能有点过时)Everything you need to know about html5 video and audio

如果加载成功,无论是使用 src 属性还是使用源元素,然后在下载数据时,都会触发进度事件。当加载了足够的数据以确定视频的尺寸和持续时间时,将触发 loadedmetadata 事件。当加载了足够的数据以呈现帧时,将触发 loadeddata 事件。当加载了足够多的数据以播放一小段视频时,将触发 canplay 事件。当浏览器确定它可以在不停止下载更多数据的情况下播放整个视频时,会触发canplaythrough 事件;如果视频具有自动播放属性,这也是视频开始播放的时间。

此处提供“canplaythrough”支持矩阵:https://caniuse.com/mdn-api_htmlmediaelement_canplaythrough_event

您可以通过将load 元素绑定到相同的函数来绕过支持限制,因为它将触发这些限制。

【讨论】:

这完全支持吗? 知道大多数 HTML5 视频规范已经由主要供应商实施,可能不是。 谢谢。不过需要注意的是,Safari 浏览器不执行“canplaythrough”事件。因此,您应该使用“canplay”代替它确实会触发。但似乎有点随机,总是触发的唯一事件是 Safari 上的“loadeddata”。 areweplayingyet 的链接失效了,您是否已经在 ios 设备上通过load 事件实现了一个工作版本? Canplaythrough 是一个神话。它根本不起作用,尤其是在 Firefox 中。【参考方案3】:
    使用 fetch 下载视频 将响应转换为 blob 从 blob 创建一个对象 URL(例如 blob:http://localhost:8080/df3c4336-2d9f-4ba9-9714-2e9e6b2b8888)
async function preloadVideo(src) 
  const res = await fetch(src);
  const blob = await res.blob();
  return URL.createObjectURL(blob);

用法:

const video = document.createElement("video");
video.src = await preloadVideo("https://example.com/video.mp4");

【讨论】:

这不是预加载。这只会将它从远程服务器获取到磁盘。 “预加载”是指将视频(或图像)加载到内存中 这满足了作者问题的约束。虽然这在技术上不是“预加载”,但它会将视频加载到一个 blob 中(在页面的生命周期内存储在用户的机器上),并防止出现视频缓冲或停止问题。【参考方案4】:

希望对你有帮助

var xhrReq = new XMLHttpRequest();
xhrReq.open('GET', 'yourVideoSrc', true);
xhrReq.responseType = 'blob';

xhrReq.onload = function() 
    if (this.status === 200) 
        var vid = URL.createObjectURL(this.response);
        video.src = vid;
    

xhrReq.onerror = function() 
    console.log('err' ,arguments);

xhrReq.onprogress = function(e)
    if(e.lengthComputable) 
        var percentComplete = ((e.loaded/e.total)*100|0) + '%';
        console.log('progress: ', percentComplete);
    

xhrReq.send();

然后,如果您的视频 src 有另一个域,您必须处理 CORS。

【讨论】:

【参考方案5】:

到目前为止,我们找到的最可靠的解决方案是播放它并等待缓冲区完全加载。

这意味着如果视频很长,您将不得不等待几乎所有视频长度。

这不酷,我知道。

想知道是否有人想出了一些其他神奇可靠的方法(最好使用 PreloadJS 之类的东西,当不支持 HTML5 视频时,它会自动回退到 flash)。

【讨论】:

【参考方案6】:

你可以使用这个不错的插件: https://github.com/GianlucaGuarini/jquery.html5loader 在其 API 中有一个 onComplete 事件,当插件完成加载所有源时触发

【讨论】:

【参考方案7】:

这行得通吗?

video.onloadeddata = function()
  video.onseeked = function()
    if(video.seekable.end(0) >= video.duration-0.1)
      alert("Video is all loaded!");
     else 
      video.currentTime=video.buffered.end(0); // Seek ahead to force more buffering
    
  ;
  video.currentTime=0; // first seek to trigger the event
;

【讨论】:

以上是关于javascript中的HTML5视频完整预加载的主要内容,如果未能解决你的问题,请参考以下文章

javascript中的完整预加载音频

播放和预加载视频之间的 HTML5 优先级

仅跨浏览器 HTML5 视频预加载海报

HTML5 视频卡顿/运行不流畅/缓冲和预加载

可以在 iOS 设备上强制 HTML5 视频预加载吗?

如何在 HTML 5 中为音频、视频、css、图像创建预加载器?