如何在加载HTML5视频时制作加载图像?

发布于 2025-01-01 13:45:18 字数 272 浏览 1 评论 0 原文

由于视频播放器加载mp4视频需要时间,HTML5是否支持在加载视频时播放“正在加载”标志?

在此处输入图像描述

由于我的asp.net应用程序是移动页面,因此需要用户单击视频才能播放视频(android、iphone不支持自动播放)。所以,我不能将“正在加载”标志制作为海报,否则用户会对此感到困惑。我想在用户单击 iPad 上的播放按钮时显示加载徽标。

谢谢

As it takes time for the video player to load the mp4 video, does HTML5 support playing a "loading" logo when loading the video ?

enter image description here

Since my asp.net apps is a mobile page, it needs the user to click on the video to play the video (android, iphone not support autoplay). So, I cannot make a "loading" logo as poster, otherwise, the user will be confused about it. I want to display a loading logo when user click play button on iPad.

thanks

Joe

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

倾城°AllureLove 2025-01-08 13:45:18

我花了很长时间才真正弄清楚如何做到这一点,但我将在这里分享它,因为我终于找到了一种方法!仔细想想,这很荒谬,因为加载是所有视频都必须做的事情。您可能认为他们在创建 html5 视频标准时会考虑到这一点。

我认为应该有效(但不会)的最初理论是,

  1. 通过 js 和 css 加载时添加加载背景图像到视频,
  2. 准备播放时删除

简单,对吧?问题是,当设置源元素或设置 video.src 属性时,我无法显示背景图像。天才/幸运的最后一击是发现(通过实验)如果海报被设置为某种东西,背景图像将不会消失。我使用的是假海报图像,但我想它也可以与透明的 1x1 图像一起使用(但为什么担心有另一个图像)。因此,这可能是一种 hack,但它有效,而且我不必向我的代码添加额外的标记,这意味着它可以在我使用 html5 视频的所有项目中工作。

HTML

<video controls="" poster="data:image/gif,AAAA">
    <source src="yourvid.mp4"
</video>

CSS(使用 JS 加载应用于视频的类)

video.loading {
  background: black url(/images/loader.gif) center center no-repeat;
}

JS

  $('#video_id').on('loadstart', function (event) {
    $(this).addClass('loading');
  });
  $('#video_id').on('canplay', function (event) {
    $(this).removeClass('loading');
    $(this).attr('poster', '');
  });

这对我来说非常适合,但仅在 mac 上的 chrome 和 safari 中进行了测试。如果有人发现错误或改进,请告诉我!

It took me a way too long to actually figure out how to do this, but I'm going to share it here because I FINALLY found a way! Which is ridiculous when you think about it, because loading is something that all videos have to do. You'd think they would have taken this into account when creating the html5 video standard.

My original theory that I thought should have worked (but wouldn't) was this

  1. Add loading bg image to video when loading via js and css
  2. Remove when ready to play

Simple, right? The problem was that I couldn't get the background image to show when the source elements were set, or the video.src attribute was set. The final stroke of genius/luck was to find out (through experimentation) that the background-image will not disappear if the poster is set to something. I'm using a fake poster image, but I imagine it would work as well with a transparent 1x1 image (but why worry about having another image). So this makes this probably a kind of hack, but it works and I don't have to add extra markup to my code, which means it will work across all my projects using html5 video.

HTML

<video controls="" poster="data:image/gif,AAAA">
    <source src="yourvid.mp4"
</video>

CSS (loading class applied to video with JS)

video.loading {
  background: black url(/images/loader.gif) center center no-repeat;
}

JS

  $('#video_id').on('loadstart', function (event) {
    $(this).addClass('loading');
  });
  $('#video_id').on('canplay', function (event) {
    $(this).removeClass('loading');
    $(this).attr('poster', '');
  });

This works perfectly for me but only tested in chrome and safari on mac. Let me know if anyone finds bugs and or improvements!

疧_╮線 2025-01-08 13:45:18

还有一个在加载视频时添加预加载器图像的简单解决方案:
HTML:

<video class="bg_vid" autoplay loop poster="images/FFFFFF-0.png">

海报是1px的透明图像。

CSS:

video {
    background-image: url(images/preload_30x30.gif);
    background-repeat: no-repeat;
    background-size: 30px 30px;
    background-position: center;
}

Also a simple solution to add a preloader image while loading the video:
HTML:

<video class="bg_vid" autoplay loop poster="images/FFFFFF-0.png">

the poster is a transparent image 1px.

CSS:

video {
    background-image: url(images/preload_30x30.gif);
    background-repeat: no-repeat;
    background-size: 30px 30px;
    background-position: center;
}
贩梦商人 2025-01-08 13:45:18

使用标签 id 海报

    <video controls="controls" poster="/IMG_LOCATION/IMAGENAME">

更多信息请参见 http://www.w3schools.com/html5/att_video_poster .asp

Use the tag id poster

    <video controls="controls" poster="/IMG_LOCATION/IMAGENAME">

More info can be found http://www.w3schools.com/html5/att_video_poster.asp

咿呀咿呀哟 2025-01-08 13:45:18

您可以使用 JavaScript 创建一个带有动画“加载”gif 的图像叠加层,仅在视频正在加载且未准备好播放时显示该图像叠加层。

您必须编写 JavaScript 来与 Media API 链接,以检测视频何时准备好播放等(这样您就可以再次隐藏图像),但这应该是可能的。

You could probably do it with JavaScript by creating an image overlay with an animated "loading" gif which you only display when the video is loading and is not ready to play.

You'd have to write JavaScript to link up with the Media API for detecting when the video is ready to play and so forth though (so you could hide the image again), but it should be possible.

記柔刀 2025-01-08 13:45:18

对于那些需要或喜欢仅使用 js 而不使用 css 的人
我们之所以被迫使用 css 背景而不是仅仅设置 GIF 作为视频海报,是因为 Safari 不会播放 GIF,只会显示 GIF 动画的第一帧。然而,我们希望能够通过不向用户显示静态框架来在每个平台上提供最佳的用户体验。

解决方法:

  • 步骤 1 将加载动画的每一帧保存为 jpg 或 png 或其他格式。
  • 步骤 2 提前获取图像并将其转换为 Base64 字符串,以确保它们始终准备就绪并立即显示。

3 帧动画示例,

let base64StringForVideoPosterFrame1;
let base64StringForVideoPosterFrame2;
let base64StringForVideoPosterFrame3;
getFile1(); // Start the fetch chain
function getFile1() {
  fetch("/images/video_poster_frames/video_poster_frame_1.png").then(response => response.blob()).then(blob => {
    const reader = new FileReader();
    reader.onload = () => {      base64StringForVideoPosterFrame1 = reader.result.split(',')[1];     };
    reader.readAsDataURL(blob);
  }).catch(error => { console.error('Problem with fetch:', error); }).finally(() => { getFile2(); });
}
function getFile2() {
  fetch("/images/video_poster_frames/video_poster_frame_2.png").then(response => response.blob()).then(blob => {
    const reader = new FileReader();
    reader.onload = () => {      base64StringForVideoPosterFrame2 = reader.result.split(',')[1];     };
    reader.readAsDataURL(blob);
  }).catch(error => { console.error('Problem with fetch:', error); }).finally(() => { getFile3(); });
}
function getFile3() {
  fetch("/images/video_poster_frames/video_poster_frame_3.png").then(response => response.blob()).then(blob => {
    const reader = new FileReader();
    reader.onload = () => {      base64StringForVideoPosterFrame3 = reader.result.split(',')[1];     };
    reader.readAsDataURL(blob);
  }).catch(error => { console.error('Problem with fetch:', error); }).finally(() => { setPosters(); });
}
    
let posters = [];
function setPosters() {
  posters = [
    'data:image/png;base64,'+base64StringForVideoPosterFrame1,
    'data:image/png;base64,'+base64StringForVideoPosterFrame2,
    'data:image/png;base64,'+base64StringForVideoPosterFrame3
  ];
}
  • 第 3 步 使用 setInterval 更改海报图像并以所需的帧速率播放动画

假设您的 HTML 中有 2 个视频,

// Note that you can extend this to cover every single video element by using getElementsByTagName("video")
const v1 = document.getElementById('video1');
const v2 = document.getElementById('video2');
// -

let currentPosterIndex = 0;
function changePoster() {
  v1.poster = posters[currentPosterIndex];
  v2.poster = posters[currentPosterIndex];
  currentPosterIndex = (currentPosterIndex + 1) % posters.length; // Loop back to the beginning every time we reach the end
}
// Change poster every 333 milliseconds
setInterval(changePoster, 333);

在 HTML 中

<video src="myVideo.fileExtension" onplaying="hideControls(this)" onwaiting="showControls(this)" preload="auto" poster="">No video support?</video>

<script type="text/javascript">
//We hide the video control buttons and the playhead when the video is playing (and is enjoyed by the viewer)
function hideControls(event){ event.controls=false; }
//If the video has to pause and wait for data download from the server we let controls be seen whenever the user hovers or taps on the video. This also makes the built-in loading animation of the browser appear e.g. the rotating circular shape and we give it a little delay (like 1 sec) because we don't want the controls to blink and the delayed show-up actually looks nicer.
function showControls(event){ setTimeout(()=>{ event.controls=true; },1000); }
</script>

为了使其更好,您可以使用 ontimeupdate 而不是 onplaying ,它会连续触发。
调整延迟时间以满足您的需要。

注意:如有必要,请检查您是否需要 playsinline 来处理视频 在 Safari 中正确自动播放

For those who need or prefer to do it with js only without using css:
The reason why we are forced to use css background instead of just setting a GIF as the video poster is because Safari will not play the GIF and will show only the first frame of the GIF animation. Yet we want to be able to offer the best UX on every platform by not showing the user a static frame.

The workaround:

  • STEP-1 Save each frame of your loading animation as jpg or png or another format.
  • STEP-2 Fetch your images in advance and convert them to base64 strings to guarantee that they are always ready and will immediately show.

Example with a 3 frame animation,

let base64StringForVideoPosterFrame1;
let base64StringForVideoPosterFrame2;
let base64StringForVideoPosterFrame3;
getFile1(); // Start the fetch chain
function getFile1() {
  fetch("/images/video_poster_frames/video_poster_frame_1.png").then(response => response.blob()).then(blob => {
    const reader = new FileReader();
    reader.onload = () => {      base64StringForVideoPosterFrame1 = reader.result.split(',')[1];     };
    reader.readAsDataURL(blob);
  }).catch(error => { console.error('Problem with fetch:', error); }).finally(() => { getFile2(); });
}
function getFile2() {
  fetch("/images/video_poster_frames/video_poster_frame_2.png").then(response => response.blob()).then(blob => {
    const reader = new FileReader();
    reader.onload = () => {      base64StringForVideoPosterFrame2 = reader.result.split(',')[1];     };
    reader.readAsDataURL(blob);
  }).catch(error => { console.error('Problem with fetch:', error); }).finally(() => { getFile3(); });
}
function getFile3() {
  fetch("/images/video_poster_frames/video_poster_frame_3.png").then(response => response.blob()).then(blob => {
    const reader = new FileReader();
    reader.onload = () => {      base64StringForVideoPosterFrame3 = reader.result.split(',')[1];     };
    reader.readAsDataURL(blob);
  }).catch(error => { console.error('Problem with fetch:', error); }).finally(() => { setPosters(); });
}
    
let posters = [];
function setPosters() {
  posters = [
    'data:image/png;base64,'+base64StringForVideoPosterFrame1,
    'data:image/png;base64,'+base64StringForVideoPosterFrame2,
    'data:image/png;base64,'+base64StringForVideoPosterFrame3
  ];
}
  • STEP-3 Use a setInterval to change the poster image and play the animation at your desired frame rate

Let's say there are 2 videos in your HTML,

// Note that you can extend this to cover every single video element by using getElementsByTagName("video")
const v1 = document.getElementById('video1');
const v2 = document.getElementById('video2');
// -

let currentPosterIndex = 0;
function changePoster() {
  v1.poster = posters[currentPosterIndex];
  v2.poster = posters[currentPosterIndex];
  currentPosterIndex = (currentPosterIndex + 1) % posters.length; // Loop back to the beginning every time we reach the end
}
// Change poster every 333 milliseconds
setInterval(changePoster, 333);

In your HTML

<video src="myVideo.fileExtension" onplaying="hideControls(this)" onwaiting="showControls(this)" preload="auto" poster="">No video support?</video>

<script type="text/javascript">
//We hide the video control buttons and the playhead when the video is playing (and is enjoyed by the viewer)
function hideControls(event){ event.controls=false; }
//If the video has to pause and wait for data download from the server we let controls be seen whenever the user hovers or taps on the video. This also makes the built-in loading animation of the browser appear e.g. the rotating circular shape and we give it a little delay (like 1 sec) because we don't want the controls to blink and the delayed show-up actually looks nicer.
function showControls(event){ setTimeout(()=>{ event.controls=true; },1000); }
</script>

To make it even better you could use ontimeupdate instead of onplaying which would fire continuously.
Adjust delay times to suit your needs.

Note: If necessary check whether you need playsinline to handle video autoplay correctly in Safari.

つ低調成傷 2025-01-08 13:45:18

我的解决方案是在 window.fbAsyncInit = function() 中添加以下内容:

var finished_rendering = function() {
    var el = document.querySelector('div#loading_msg');
    el.style.display="none";
}

FB.Event.subscribe('xfbml.render', finished_rendering);

Found: https://developers.facebook.com/docs/reference/javascript/FB.Event.subscribe/v2.12

My solution was to add the following inside of the window.fbAsyncInit = function():

var finished_rendering = function() {
    var el = document.querySelector('div#loading_msg');
    el.style.display="none";
}

FB.Event.subscribe('xfbml.render', finished_rendering);

Found: https://developers.facebook.com/docs/reference/javascript/FB.Event.subscribe/v2.12

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文