html5视频&音频缓存问题 [英] html5 video & audio cache issue

查看:1427
本文介绍了html5视频&音频缓存问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了一个自定义媒体预加载器,它使用一系列 XMLHttpRequests 在显示我的 ng2应用程序之前加载大量媒体。 code>。这是一个利益相关者的要求,所有媒体在使用应用程序之前都是以完整版下载的。

 私人loadFile(媒体:任何){
返回新的承诺(函数(解析,拒绝){
var错误:布尔=假;

// for .videos){
// TODO:检查如何加载.....
//console.log(\"Now加载视频>>,media,media.hasOwnProperty(path ));


//标准XHR加载图像
var request = new XMLHttpRequest();
request.open(GET,(<任何>媒体).path);
request.responseType ='blob';

//请求加载时,检查它是否成功
request.onload =() => {
if(request.status === 200){
resolve(request.response);
}
else
//如果失败,用呃拒绝承诺ror消息
reject(错误('媒体没有成功载入;错误代码:'+ request.statusText));
};

//如果发生错误
request.onerror =()=> {
//同时处理整个请求未能以
开头的情况//这可能是网络错误,所以用适当的消息拒绝承诺
reject(Error('出现网络错误。'));
};

request.onreadystatechange = function(){
if(request.readyState == 4){
console.log(Load Complete>>,media, from,request.status); //另一个回调
}
};

//进度加载器的每个节拍
request.onprogress = data =>的console.log(数据);

//发送请求
request.send();
})
}

它在所有媒体

当我参考< / strong>时,我只有1个问题出现在 Chrome 中。视频> <音频> ,这是预先加载的,它不会从缓存中提取,而是重新下载它来自服务器。 (IE9甚至从缓存中拉出)





任何音频和视频元素将始终从服务器重新下载。 ..

 < video width =640pxheight =autocontrols autoplay preload =auto> 
< source src =./ app / assets / video / Awaiting%20Video%20Master.movtype =video / mp4/>
< / video>

< audio controls autoplay preload =auto>
< source src =./ app / assets / audio / 1_2_4_audio1.mp3type =audio / mp3/>
< / audio>

这将始终从缓存中加载...



< img src =./ app / assets / images / BTFG-BOLD_Fundamentals.png/>






这里有2个屏幕截图,一个来自chrome,另一个来自边缘,显示了开发工具的网络活动(两者都在启动之前重置了缓存) p>

Chrome



边缘



我注意到的主要区别在于请求当呈现内容时(浏览器预加载),浏览器的状态是不同的。但为什么会出现这种情况?



我发现这个SO 帖子从2013年开始,其中指出:


视频如何缓冲取决于浏览器实施,因此可能会有所不同浏览器到浏览器。

各种浏览器可以使用不同的因素来决定保留还是放弃部分缓冲区。旧分段,磁盘空间,内存和性能是典型的因素。


这是在这里发生的事情吗?如果是这样,有没有人知道一种方法来解决这个问题,以便铬总是试图从视频缓存中拉视频?

确定缓存问题是否是一个铬错误,但你对我做的事情看起来真的很奇怪。



您是预载媒体,或者实际上,完全下载,然后将mediaElement设置为原始源。



当我们通过mediaElement(< audio> < video> ),浏览器将使 range 请求,即它不会下载完整的文件,但只有它需要不间断地播放它。

这就是为什么你得到 206部分内容 回复。这也可能是为什么chrome不认为它是相同的请求,因此不再使用缓存我不确定它是否为chrome错误



但是既然你已经下载完整的文件,为什么不把你的mediaElement的 src 设置为这个下载的文件?

  //因为您将hr reponseType设置为blob'` 
mediaElement.src = URL.createObjectURL(request 。响应);
//当加载
时不要忘记URL.revokeObjectURL(mediaElement.src)



$ b

工作示例:(在我的FF上触发一个奇怪的错误...)
$ b

  function loadVideo(url){return new Promise((resolve,reject)=> {//这里我们完全下载let request = new XMLHttpRequest(); request.responseType ='blob'; request.onload =(evt)=> resolve(request.response); request.onerror = reject; request.open('GET',url); request.send();}) (blob)=> new Promise((resolve,reject)=> {resolve(URL.createObjectURL(blob)); //直接返回blobURL}));} loadVideo('https://dl.dropboxusercontent。 com / s / bch2j17v6ny4ako / movie720p.mp4').then(blobUrl => {// now it载入的document.body.className ='loaded';让vid = document.querySelector('video'); vid.src = blobUrl; //我们只需将我们的mediaElement的src设置为此blobURL vid.onload =()=> URL.revokeObjectURL(blobUrl); })。catch((err)=> console.log(err));  

  video {display:none; } .loaded p {display:none; } .loaded video {display:unset; }  

< p> loading .. please wait< / p>< video controls>< / video>

与获取API:



function loadVideo(url) (返回访存(url).then(resp => resp.blob()).then(blob => URL.createObjectURL(blob));} loadVideo('https://dl.dropboxusercontent.com/s/ (blobUrl => {//现在加载了document.body.className ='loaded'; let vid = document.querySelector('video'); vid.src = blobUrl; //我们只需将我们的mediaElement的src设置为此blobURL vid.onload =()=> URL.revokeObjectURL(blobUrl);})。catch((err)=> console.log(err));

  video {display:none;}。loaded p {display:none;}。loaded video {display:unset;}   

< / video>


I've written a custom media preloader which uses a series of XMLHttpRequests to load large amounts of media prior to displaying my ng2 app. It is a stakeholder requirement that all media is downloaded in full prior to use of the app.

 private loadFile(media: any) {
    return new Promise(function (resolve, reject) {
        var error: boolean = false;

        //for (var media of media.videos) {
        //TODO: Check how this loads.....
        //console.log("Now Loading video >> ", media, media.hasOwnProperty("path"));


        // Standard XHR to load an image
        var request = new XMLHttpRequest();
        request.open("GET", (<any>media).path);
        request.responseType = 'blob';

        // When the request loads, check whether it was successful
        request.onload = () => {
            if (request.status === 200) {
                resolve(request.response);
            }
            else
                // If it fails, reject the promise with a error message
                reject(Error('Media didn\'t load successfully; error code:' + request.statusText));
        };

        // If an error occurs
        request.onerror = () => {
            // Also deal with the case when the entire request fails to begin with
            // This is probably a network error, so reject the promise with an appropriate message
            reject(Error('There was a network error.'));
        };

        request.onreadystatechange = function () {
            if (request.readyState == 4) {
                console.log("Load Complete >> ", media, "from", request.status); // Another callback here
            }
        };

        // Every tick of the progress loader
        request.onprogress = data => console.log(data);

        // Send the request
        request.send();
    })
}

It works great and successfully loads in all the media that I feed it.

I only have 1 issue and that is in Chrome, when I reference a <video> or <audio> which has been pre-loaded,, it doesn't pull it from the cache, it instead re-downloads it from the server. (IE9 even pulls from cache)


Any audio and video elements will always re-download from the server...

<video width="640px" height="auto" controls autoplay preload="auto">
    <source src="./app/assets/video/Awaiting%20Video%20Master.mov" type="video/mp4"/>
</video>

<audio controls autoplay preload="auto">
    <source src="./app/assets/audio/1_2_4_audio1.mp3" type="audio/mp3" />
</audio>

This will always load from cache...

<img src="./app/assets/images/BTFG-BOLD_Fundamentals.png" />


Here are 2 screenshots, one from chrome and one from edge showing the network activitiy from the dev tools (both had their caches reset prior to launch)...

Chrome

Edge

The main difference that I notice is the request status is different between browsers when it comes to rendering the content (post preloading). But why is this the case?

I found this SO post from 2013 which states that:

How video is buffered is browser implementation dependent and therefor may vary from browser to browser.

Various browsers can use different factors to determine to keep or to discard a part of the buffer. Old segments, disk space, memory and performance are typical factors.

Is this what is happening here? And if so, does anyone know a way to fix this so that chrome always attempts to pull the videos from cache?

解决方案

Not sure if the caching issue is a chrome bug, but what you do seems really odd to me.

You are preloading your media, or actually, downloading it entirely, but then set the mediaElement to the original source.

When we load media through a mediaElement (<audio> or <video>), the browser will make range requests, i.e, it won't download the full file, but only what it needs to play without interruption.
That's why you get 206 Partial content responses. It's also probably why chrome doesn't recognize it as being the same requests, and hence doesn't use the cache once again I'm not sure if it's a chrome bug or not.

But since you already did download the full file, why don't you set your mediaElement's src to this downloaded file ?

// since you are setting the hr reponseType to `'blob'`
mediaElement.src = URL.createObjectURL(request.response);
// don't forget to URL.revokeObjectURL(mediaElement.src) when loaded

Working example : (which triggers a weird bug on my FF...)

function loadVideo(url) {
  return new Promise((resolve, reject) => { // here we download it entirely
      let request = new XMLHttpRequest();
      request.responseType = 'blob';
      request.onload = (evt)=>resolve(request.response);
      request.onerror = reject;
      request.open('GET', url);
      request.send();
    }).then((blob)=> 
    	new Promise((resolve, reject)=>{
    		resolve(URL.createObjectURL(blob)); // return the blobURL directly
    		})
    	);

}

loadVideo('https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4')
  .then(blobUrl => { // now it's loaded
    document.body.className = 'loaded';
    let vid = document.querySelector('video');
    vid.src = blobUrl; // we just set our mediaElement's src to this blobURL
    vid.onload = () => URL.revokeObjectURL(blobUrl);
  }).catch((err) => console.log(err));

video{
  display: none;
  }
.loaded p{
  display: none;
  }
.loaded video{
  display: unset;
  }

<p>loading.. please wait</p>
<video controls></video>

Or with the fetch API :

function loadVideo(url) {
  return fetch(url)
    .then(resp => resp.blob())
    .then(blob => URL.createObjectURL(blob));
}

loadVideo('https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4')
  .then(blobUrl => { // now it's loaded
    document.body.className = 'loaded';
    let vid = document.querySelector('video');
    vid.src = blobUrl; // we just set our mediaElement's src to this blobURL
    vid.onload = () => URL.revokeObjectURL(blobUrl);
  }).catch((err) => console.log(err));

video {
  display: none;
}
.loaded p {
  display: none;
}
.loaded video {
  display: unset;
}

<p>loading.. please wait</p>
<video controls></video>

这篇关于html5视频&amp;音频缓存问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆