html5视频和音频缓存问题

2024-02-08

我编写了一个自定义媒体预加载器,它使用了一系列XMLHttpRequests在显示我的内容之前加载大量媒体ng2 app。利益相关者要求所有媒体都下载在full在使用该应用程序之前。

 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();
    })
}

它工作得很好,并成功加载到我提供给它的所有媒体中。

我只有 1 个问题,即Chrome,当我引用一个<video> or <audio>它已经预先加载,它不会从缓存中提取它,而是从服务器重新下载它。(IE9甚至从缓存中提取)


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>

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

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


这里有两张屏幕截图,一张来自 Chrome,一张来自 Edge,显示了开发工具的网络活动(两者都在启动前重置了缓存)...

Chrome enter image description here

Edge enter image description here

我注意到的主要区别是,在渲染内容(预加载后)时,浏览器之间的请求状态不同。但为什么会这样呢?

I found this SO https://stackoverflow.com/questions/18422517/html5-video-buffered-attribute-features2013 年的帖子指出:

视频的缓冲方式取决于浏览器的实现,因此可能会因浏览器的不同而有所不同。

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

这就是这里发生的事情吗?如果是这样,有谁知道如何解决此问题,以便 chrome 始终尝试从缓存中提取视频?


不确定缓存问题是否是 chrome 错误,但你所做的对我来说似乎很奇怪。

You are 预加载你的媒体,或者实际上,完全下载,但随后将 mediaElement 设置为原始源。

When we load media through a mediaElement (<audio> or <video>), the browser will make range https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/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 https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/206 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.

但既然你已经下载了完整的文件,为什么不设置你的 mediaElementsrc到这个下载的文件?

// 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

工作示例:(这会在我的 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>

或者使用 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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

html5视频和音频缓存问题 的相关文章

随机推荐