html5: показ видео внутри холста - PullRequest
35 голосов
/ 13 декабря 2010

возможно ли отобразить html5-видео как часть холста?

в основном так же, как вы рисуете изображение на холсте.

context.drawVideo(vid, 0, 0);

спасибо!

Ответы [ 4 ]

63 голосов
/ 13 декабря 2010
var canvas = document.getElementById('canvas');
var ctx    = canvas.getContext('2d');
var video  = document.getElementById('video');

video.addEventListener('play', function () {
    var $this = this; //cache
    (function loop() {
        if (!$this.paused && !$this.ended) {
            ctx.drawImage($this, 0, 0);
            setTimeout(loop, 1000 / 30); // drawing at 30fps
        }
    })();
}, 0);

Я полагаю, приведенный выше код является самообъяснительным. Если не опустить комментарий ниже, я попытаюсь объяснить несколько приведенных выше строк кода

Редактировать :вот онлайн пример, только для вас :) Демо

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var video = document.getElementById('video');

// set canvas size = video size when known
video.addEventListener('loadedmetadata', function() {
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;
});

video.addEventListener('play', function() {
  var $this = this; //cache
  (function loop() {
    if (!$this.paused && !$this.ended) {
      ctx.drawImage($this, 0, 0);
      setTimeout(loop, 1000 / 30); // drawing at 30fps
    }
  })();
}, 0);
<div id="theater">
  <video id="video" src="http://upload.wikimedia.org/wikipedia/commons/7/79/Big_Buck_Bunny_small.ogv" controls="false"></video>
  <canvas id="canvas"></canvas>
  <label>
    <br />Try to play me :)</label>
  <br />
</div>
26 голосов
/ 02 августа 2016

Использование холста для отображения видео

Отображение видео очень похоже на отображение изображения. Незначительные отличия связаны с событиями загрузки и тем фактом, что вам нужно визуализировать видео каждый кадр, иначе вы увидите только один кадр, а не анимированные кадры.

Демонстрация ниже имеет некоторые незначительные отличия от примера. Функция отключения звука (под видео нажмите кнопку отключения звука / звука для переключения звука) и некоторую проверку ошибок, чтобы поймать IE9 + и Edge, если у них нет правильных драйверов.

Сохранение текущих ответов.

Предыдущие ответы user372551 устарели (декабрь 2010 г.) и имеют недостатки в используемой технике рендеринга. Он использует setTimeout и скорость 33,333..ms, при которой setTimeout округляется до 33ms, это приводит к падению кадров каждые две секунды и может уменьшаться намного больше, если частота видеокадров выше 30. Использование setTimeout также представит созданный срез видео, поскольку setTimeout не может быть синхронизирован с оборудованием дисплея.

В настоящее время не существует надежного метода, который мог бы определять частоту кадров видео, если вы заранее не знаете частоту кадров видео, и вам следует отображать ее с максимально возможной частотой обновления экрана в браузерах. 60fps

Данный топовый ответ был для того времени (6 лет назад) лучшим решением, поскольку requestAnimationFrame не был широко поддержан (если вообще был), но requestAnimationFrame теперь является стандартным для основных браузеров и должен использоваться вместо setTimeout. уменьшить или удалить выпавшие кадры и предотвратить сдвиг.

Пример демо.

Загружает видео и устанавливает его на цикл. Видео не будет воспроизводиться, пока вы не нажмете на него. Повторное нажатие сделает паузу. Под видео есть кнопка отключения звука / звука. Видео по умолчанию отключено.

Обратите внимание на пользователей 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 in case the media load fails and a link to fix IE9+ and Edge support.
// Code by Blindman67.


// Original source has returns 404
// var mediaSource = "http://video.webmfiles.org/big-buck-bunny_trailer.webm";
// New source from wiki commons. Attribution in the leading credits.
var mediaSource = "http://upload.wikimedia.org/wikipedia/commons/7/79/Big_Buck_Bunny_small.ogv"

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>
<div style="font-size:small">Attribution in the leading credits.</div><br>

Доп. Холст

Использование холста для рендеринга видео дает вам дополнительные возможности для отображения и микширования в FX. На следующем рисунке показаны некоторые эффекты, которые вы можете получить, используя холст. Использование 2D API дает огромный спектр творческих возможностей.

Изображение, относящееся к ответу Исчезать видео холста от оттенков серого до цвета Video filters

См. Заголовок видео в демонстрационной версии выше для определения авторства контента в приведенном выше изображении.

14 голосов
/ 24 мая 2018

Я хотел бы предложить решение, которое использует более современный синтаксис и является менее подробным, чем уже предоставленные:

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const video = document.querySelector("video");

video.addEventListener('play', () => {
  function step() {
    ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
    requestAnimationFrame(step)
  }
  requestAnimationFrame(step);
})

Некоторые полезные ссылки:

0 голосов
/ 19 августа 2016

Вам необходимо обновить элемент видео currentTime, а затем нарисовать рамку на холсте.Не инициализируйте событие play () на видео.

Вы также можете использовать для отл.этот плагин https://github.com/tstabla/stVideo

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...