Воспроизведение видео BLOB в Canvas - PullRequest
0 голосов
/ 07 апреля 2020

Как воспроизвести видеоблок в Canvas?

HTML:

<canvas id="canvas" ></canvas>

JS:

var canvas = document.querySelector("#canvas")
mediaRecorder.ondataavailable = function(e) {
    if (e.data.size > 0) {
       var blob = e.data; // webm video blob chunk
       // how to play this blob into a canvas
    }
}

Другой вариант использования

setInterval(function(){
   if(frames.length > 0) {
      var webmBlob = Whammy.fromImageArray(frames, frameRate); // webm video
      // render webm video blob into Canvas
   }
}, 1000);

1 Ответ

1 голос
/ 07 апреля 2020

То, что выводит ваш MediaRecorder ondataavailable, это не видеоблок, это всего лишь фрагмент видеофайла. За исключением самого первого, он не может быть воспроизведен один, вам нужно объединить его со всеми предыдущими фрагментами, которые были записаны до этого момента.

const chunks = [];
recorder.ondatavailable = (evt) => {
  chunks.push( evt.data ); // store all the chunks
  play( new Blob( chunks ) ); // concatenate all the chunks to as single Blob
};

Затем для воспроизведения видео, используемого в качестве BLOB-объекта , вам нужно создать URL, указывающий на этот BLOB-объект, это делается с помощью метода URL.createObjectURL().

Теперь, чтобы нарисовать его на холсте, вы должны пройти через элемент , на котором вы установим src для blob: URI, который мы создали до:

(async () => {

  const source = document.createElement( 'video' );
  source.crossOrigin = "anonymous";
  source.muted = true;
  source.src = "https://upload.wikimedia.org/wikipedia/commons/a/a4/BBH_gravitational_lensing_of_gw150914.webm";
  console.log('loading, please wait');
  await source.play();
  
  const player = document.createElement( 'video' );
  player.muted = true;
  const output = document.getElementById( 'output' );
  const ctx = output.getContext( '2d' );
  
  const stream = (source.captureStream && source.captureStream()) || source.mozCaptureStream();
  const recorder = new MediaRecorder( stream );
  const chunks = [];
  recorder.ondataavailable = (evt) => {
    console.clear();
    chunks.push( evt.data );
    play( new Blob( chunks ) );
  };

  console.clear();
  console.log('buffering, please wait 5s');
  recorder.start( 5000 ); // 5s per chunk
  
  source.addEventListener( 'ended', (evt) => recorder.stop() );
  
  function play( blob ) {

    if( player.paused ) {
      drawing = true;
      player.addEventListener( 'loadedmetadata', (evt) => {
        output.width = player.videoWidth;
        output.height = player.videoHeight;
        requestAnimationFrame( loop );
      }, { once: true } );
    }
    player.src = URL.createObjectURL( blob );
    player.play();

  }
  function loop() {
    ctx.drawImage( player, 0, 0 );
    if( !player.paused ) {
      requestAnimationFrame( loop );
    }
  }
  
})().catch( console.error );
<canvas id="output"></canvas>

Но учтите, что это на самом деле не обычное дело ...

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

const chunks = [];
recorder.ondatavailable = (evt) => {
  chunks.push( evt.data ); // store all the chunks
};
recorder.onstop = (evt) => { // only when the recording is entirely done
  play( new Blob( chunks ) ); // concatenate all the chunks to as single Blob
};

Но если вы действительно хотите нарисовать это видео на холсте в режиме реального времени, просто сделайте это и не используйте MediaRecorder в все:

(async () => {

  const source = document.createElement( 'video' );
  source.crossOrigin = "anonymous";
  source.muted = true;
  source.src = "https://upload.wikimedia.org/wikipedia/commons/a/a4/BBH_gravitational_lensing_of_gw150914.webm";
  console.log('loading, please wait');
  await source.play();
  console.clear();
  
  const player = document.createElement( 'video' );
  player.muted = true;
  const output = document.getElementById( 'output' );
  const ctx = output.getContext( '2d' );
  
  const stream = (source.captureStream && source.captureStream()) || source.mozCaptureStream();

  player.addEventListener( 'loadedmetadata', (evt) => {
    output.width = player.videoWidth;
    output.height = player.videoHeight;
    requestAnimationFrame( loop );
  }, { once: true } );
  player.srcObject = stream;
  player.play();

  function loop() {
    ctx.drawImage( player, 0, 0 );
    if( !source.paused ) {
      requestAnimationFrame( loop );
    }
  }
  
})().catch( console.error );
<canvas id="output"></canvas>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...