繁体   English   中英

如何使用HTML5 canvas标签显示视频

[英]How do I display a video using HTML5 canvas tag

我想使用包含播放暂停功能的画布显示视频,该功能允许用户通过单击画布来切换播放,我还想在视频暂停时在视频上方绘制一个叠加层。 如何在javascript中完成?

画布可用于显示来自各种来源的视频。 本示例说明如何将视频加载为文件资源,显示它并在屏幕播放/暂停切换上添加简单的单击。

只是一张图片

就画布而言,视频只是图像。 您可以像绘制任何图像一样绘制它。 区别在于视频可以播放并具有声音。

获取画布和基本设置

// It is assumed you know how to add a canvas and correctly size it.
var canvas = document.getElementById("myCanvas"); // get the canvas from the page
var ctx = canvas.getContext("2d");
var videoContainer; // object to hold video and associated info

创建和加载视频

var video = document.createElement("video"); // create a video element
video.src = "urlOffVideo.webm"; 
// the video will now begin to load.
// As some additional info is needed we will place the video in a
// containing object for convenience
video.autoPlay = false; // ensure that the video does not auto play
video.loop = true; // set the video to loop.
videoContainer = {  // we will add properties as needed
     video : video,
     ready : false,   
};

与图像元素不同,视频不必完全加载即可在画布上显示。 视频还提供了许多额外的事件,可用于监视视频的状态。

在这种情况下,我们希望知道何时可以播放视频。 oncanplay意味着已经加载了足够的视频以播放其中的一些视频,但可能还不足以播放到最后。

video.oncanplay = readyToPlayVideo; // set the event to the play function that 
                                  // can be found below

另外,您可以使用oncanplaythrough ,当加载了足够多的视频时,它将触发,从而可以播放到最后。

video.oncanplaythrough = readyToPlayVideo; // set the event to the play function that
                                         // can be found below

只能使用canPlay事件之一,不能同时使用两者。

可以播放事件(相当于图片加载)

function readyToPlayVideo(event){ // this is a referance to the video
    // the video may not match the canvas size so find a scale to fit
    videoContainer.scale = Math.min(
                         canvas.width / this.videoWidth, 
                         canvas.height / this.videoHeight); 
    videoContainer.ready = true;
    // the video can be played so hand it off to the display function
    requestAnimationFrame(undateCanvas);
}

显示中

视频将不会在画布上播放。 您需要为每个新框架绘制它。 由于很难知道确切的帧速率以及何时发生帧速率,最好的办法是将视频显示为以60fps的速度运行。 如果帧速率较低,则w将同一帧渲染两次。 如果帧速率较高,则看不到多余的帧,因此我们将其忽略。

video元素只是一个图像元素,可以像绘制任何图像一样进行绘制,您可以缩放,旋转,平移视频,对其进行镜像,淡入淡出,对其进行裁剪和仅显示部分,并使用全局合成模式第二次绘制两次添加效果,如变亮,屏幕等。

function updateCanvas(){
    ctx.clearRect(0,0,canvas.width,canvas.height); // Though not always needed 
                                                     // you may get bad pixels from 
                                                     // previous videos so clear to be
                                                     // safe
    // only draw if loaded and ready
    if(videoContainer !== undefined && videoContainer.ready){ 
        // find the top left of the video on the canvas
        var scale = videoContainer.scale;
        var vidH = videoContainer.video.videoHeight;
        var vidW = videoContainer.video.videoWidth;
        var top = canvas.height / 2 - (vidH /2 ) * scale;
        var left = canvas.width / 2 - (vidW /2 ) * scale;
        // now just draw the video the correct size
        ctx.drawImage(videoContainer.video, left, top, vidW * scale, vidH * scale);
        if(videoContainer.video.paused){ // if not playing show the paused screen 
            drawPayIcon();
        }
    }
    // all done for display 
    // request the next frame in 1/60th of a second
    requestAnimationFrame(updateCanvas);

}

基本播放暂停控制

现在,我们已经加载并显示了视频,我们需要的只是播放控件。 我们将其作为单击切换在屏幕上播放。 当视频正在播放并且用户单击时,视频暂停。 暂停后,点击继续播放。 我们将添加使视频变暗并绘制播放图标(三角形)的功能

function drawPayIcon(){
     ctx.fillStyle = "black";  // darken display
     ctx.globalAlpha = 0.5;
     ctx.fillRect(0,0,canvas.width,canvas.height);
     ctx.fillStyle = "#DDD"; // colour of play icon
     ctx.globalAlpha = 0.75; // partly transparent
     ctx.beginPath(); // create the path for the icon
     var size = (canvas.height / 2) * 0.5;  // the size of the icon
     ctx.moveTo(canvas.width/2 + size/2, canvas.height / 2); // start at the pointy end
     ctx.lineTo(canvas.width/2 - size/2, canvas.height / 2 + size);
     ctx.lineTo(canvas.width/2 - size/2, canvas.height / 2 - size);
     ctx.closePath();
     ctx.fill();
     ctx.globalAlpha = 1; // restore alpha
}    

现在播放暂停事件

function playPauseClick(){
     if(videoContainer !== undefined && videoContainer.ready){
          if(videoContainer.video.paused){                                 
                videoContainer.video.play();
          }else{
                videoContainer.video.pause();
          }
     }
}
// register the event
canvas.addEventListener("click",playPauseClick);

摘要

使用画布播放视频非常容易,实时添加效果也很容易。 但是,格式,播放和搜索方式存在一些限制。 MDN HTMLMediaElement是获得对视频对象的完整引用的地方。

在画布上绘制图像后,您可以使用ctx.getImageData访问其中包含的像素。 或者,您可以使用canvas.toDataURL捕捉静止图像并下载。 (仅当视频来自受信任的来源并且没有污染画布时)。


请注意,如果视频有声音,则播放时也会播放声音。

祝您拍摄愉快。

使用画布显示视频

显示视频与显示图像几乎相同。 较小的差异与onload事件有关,而事实是您需要每帧渲染视频,否则您只会看到一个帧而不是动画帧。

下面的演示与示例有一些细微的差异。 静音功能(在视频下,单击静音/打开声音以切换声音),并进行一些错误检查以捕获IE9 +和Edge(如果它们没有正确的驱动程序)。 我本来会使用IE支持的另一种格式,但找不到属于公共领域的格式。

注意IE9 +和Edge的用户。 您可能无法播放视频格式WebM,因为它需要其他驱动程序来播放视频。 可以在tools.google.com上找到它们, 下载IE9 + WebM支持

 // This code is from the example document on stackoverflow documentation. See HTML for link to the example. // This code is almost identical to the example. Mute has been added and a media source. Also added some error handling incase the media load fails and a link to fix IE9+ and Edge suport. // Code by Blindman67. var mediaSource = "http://video.webmfiles.org/big-buck-bunny_trailer.webm"; var muted = true; var canvas = document.getElementById("myCanvas"); // get the canvas from the page var ctx = canvas.getContext("2d"); var videoContainer; // object to hold video and associated info var video = document.createElement("video"); // create a video element video.src = mediaSource; // the video will now begin to load. // As some additional info is needed we will place the video in a // containing object for convenience video.autoPlay = false; // ensure that the video does not auto play video.loop = true; // set the video to loop. video.muted = muted; videoContainer = { // we will add properties as needed video : video, ready : false, }; // To handle errors. This is not part of the example at the moment. Just fixing for Edge that did not like the ogv format video video.onerror = function(e){ document.body.removeChild(canvas); document.body.innerHTML += "<h2>There is a problem loading the video</h2><br>"; document.body.innerHTML += "Users of IE9+ , the browser does not support WebM videos used by this demo"; document.body.innerHTML += "<br><a href='https://tools.google.com/dlpage/webmmf/'> Download IE9+ WebM support</a> from tools.google.com<br> this includes Edge and Windows 10"; } video.oncanplay = readyToPlayVideo; // set the event to the play function that // can be found below function readyToPlayVideo(event){ // this is a referance to the video // the video may not match the canvas size so find a scale to fit videoContainer.scale = Math.min( canvas.width / this.videoWidth, canvas.height / this.videoHeight); videoContainer.ready = true; // the video can be played so hand it off to the display function requestAnimationFrame(updateCanvas); // add instruction document.getElementById("playPause").textContent = "Click video to play/pause."; document.querySelector(".mute").textContent = "Mute"; } function updateCanvas(){ ctx.clearRect(0,0,canvas.width,canvas.height); // only draw if loaded and ready if(videoContainer !== undefined && videoContainer.ready){ // find the top left of the video on the canvas video.muted = muted; var scale = videoContainer.scale; var vidH = videoContainer.video.videoHeight; var vidW = videoContainer.video.videoWidth; var top = canvas.height / 2 - (vidH /2 ) * scale; var left = canvas.width / 2 - (vidW /2 ) * scale; // now just draw the video the correct size ctx.drawImage(videoContainer.video, left, top, vidW * scale, vidH * scale); if(videoContainer.video.paused){ // if not playing show the paused screen drawPayIcon(); } } // all done for display // request the next frame in 1/60th of a second requestAnimationFrame(updateCanvas); } function drawPayIcon(){ ctx.fillStyle = "black"; // darken display ctx.globalAlpha = 0.5; ctx.fillRect(0,0,canvas.width,canvas.height); ctx.fillStyle = "#DDD"; // colour of play icon ctx.globalAlpha = 0.75; // partly transparent ctx.beginPath(); // create the path for the icon var size = (canvas.height / 2) * 0.5; // the size of the icon ctx.moveTo(canvas.width/2 + size/2, canvas.height / 2); // start at the pointy end ctx.lineTo(canvas.width/2 - size/2, canvas.height / 2 + size); ctx.lineTo(canvas.width/2 - size/2, canvas.height / 2 - size); ctx.closePath(); ctx.fill(); ctx.globalAlpha = 1; // restore alpha } function playPauseClick(){ if(videoContainer !== undefined && videoContainer.ready){ if(videoContainer.video.paused){ videoContainer.video.play(); }else{ videoContainer.video.pause(); } } } function videoMute(){ muted = !muted; if(muted){ document.querySelector(".mute").textContent = "Mute"; }else{ document.querySelector(".mute").textContent= "Sound on"; } } // register the event canvas.addEventListener("click",playPauseClick); document.querySelector(".mute").addEventListener("click",videoMute) 
 body { font :14px arial; text-align : center; background : #36A; } h2 { color : white; } canvas { border : 10px white solid; cursor : pointer; } a { color : #F93; } .mute { cursor : pointer; display: initial; } 
 <h2>Basic Video & canvas example</h2> <p>Code example from Stackoverflow Documentation HTML5-Canvas<br> <a href="https://stackoverflow.com/documentation/html5-canvas/3689/media-types-and-the-canvas/14974/basic-loading-and-playing-a-video-on-the-canvas#t=201607271638099201116">Basic loading and playing a video on the canvas</a></p> <canvas id="myCanvas" width = "532" height ="300" ></canvas><br> <h3><div id = "playPause">Loading content.</div></h3> <div class="mute"></div><br> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM