We all know that the Video TAB allows videos to play in web pages, somewhat replacing Flash. Today we introduce several application scenarios of Video on web pages: variable speed playback, real-time drawing of Video streaming to canvas.

This is the 19th day of my participation in the August Wenwen Challenge.More challenges in August

Variable speed playback

First of all, let’s introduce speed play.

This is actually a built-in function of the browser Video TAB, and does not require developers to do any other Settings or development.

Grammar: videoElement playbackRate = value; 1 indicates normal speed, greater than 1 indicates acceleration, and less than 1 indicates slow speed.

<video src="./video.mp4" controls></video>

var video = document.querySelector("video");
console.log(video.playbackRate);// Get the video playback rate
video.playbackRate = 0.5;// Play at 0.5 speed (slow)
video.playbackRate = 2;// 2 speed playback (speed up)
Copy the code

Draw video streams to canvas in real time

In fact, Canvas provides the ability to draw video content onto canvas.

Here’s an example: The user clicks a button to get the current video image frame data and draws it onto a canvas of the same size.

<button onclick="getCurFrame()">Gets the currently playing video frame</button>
<video src="./video.ogv" controls></video>
<canvas></canvas>
<script>
    var video = document.querySelector('video');
    var canvas = document.querySelector('canvas');

    // Get the width and height of the video when the first frame of the video is loaded
    video.onloadeddata = () = >{
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
    }
    function getCurFrame(){
        const ctx = canvas.getContext('2d');
        ctx.drawImage(video,0.0)}</script>
Copy the code

Let’s improve the code a little bit and let the program draw in real time:

function getCurFrame(){
    setTimeout(getCurFrame,0)
    const ctx = canvas.getContext('2d');
    ctx.drawImage(video,0.0)
}
getCurFrame()
Copy the code

We can see that the image on the right canvas is updated in real time, just as the video on the left is playing.

Now we want to replace the light background of the video with a red one. How do we do that? Let’s think about this:

  • Each time we draw, we take the image pixels and replace the light background pixels with the ones we want
  • The new data is then drawn to the canvas

We just need to add a few lines of code:

let frame = ctx.getImageData(0.0, canvas.width, canvas.height);
// Get the pixel length, each pixel rGBA occupies four positions.
const l = frame.data.length / 4;
for (let i = 0; i < l; i++) {
    let r = frame.data[i * 4 + 0];
    let g = frame.data[i * 4 + 1];
    let b = frame.data[i * 4 + 2];
    // Light background pixels. We'll change it to red RGB (255,0,0)
    if (g > 100 && r > 100 && b < 43){
        frame.data[i*4 + 0] = 255;
        frame.data[i*4 + 1] = 0;
        frame.data[i*4 + 2] = 0; }}// Redraw the processed frame to the canvas
ctx.putImageData(frame, 0.0);
Copy the code

The effect is as follows:

Record the canvas drawing process and save it

We have converted the video to canvas drawing process, so how to save this process as a new video file?

// Use the Canvas captureStream method and the media recording object MediaRecorder
var stream = canvas.captureStream();
var recorder = new MediaRecorder(stream, { mimeType: 'video/webm' });
var data = [];
recorder.ondataavailable = function (event) {
    if(event.data && event.data.size) { data.push(event.data); }}; recorder.onstop =() = > {
    // Create a binary object and download it locally with the A tag
    var url = URL.createObjectURL(new Blob(data, { type: 'video/webm' }));
    const a  = document.createElement("a");
    a.href = url;
    a.download = "video.webm"
    a.click();
    window.URL.revokeObjectURL(url);
};
video.onplay = () = >{
    // Start recording
    recorder.start();
}
video.onended = () = >{
    // End recording
    recorder.stop();
}
Copy the code

After opening the downloaded file, I found an embarrassing problem:

  • There’s no audio. This is understandable (because only the footage is recorded)
  • I found that the video progress bar could not be dragged. Please refer to the article. Here I use a solution of the open source community
const videoDuration = 1000*20;//(ms单位)
recorder.onstop = () = > {
    const buggyBlob = new Blob(data, { type: 'video/webm' });
    ysFixWebmDuration(buggyBlob, videoDuration, function(fixedBlob) {
        var url = URL.createObjectURL(fixedBlob);
        const a  = document.createElement("a");
        a.href = url;
        a.download = "video.webm"
        a.click();
        window.URL.revokeObjectURL(url);
    });
};
Copy the code

The last

Thanks for reading!