Skip to content

Instantly share code, notes, and snippets.

@prof3ssorSt3v3
Created January 12, 2019 23:06
Show Gist options
  • Select an option

  • Save prof3ssorSt3v3/efcf21c32b1d15e20fa48f57139776a2 to your computer and use it in GitHub Desktop.

Select an option

Save prof3ssorSt3v3/efcf21c32b1d15e20fa48f57139776a2 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML Canvas Video</title>
<style>
video{
border: 4px solid cornflowerblue;
}
canvas{
border: 4px solid gold;
}
img{
border: 4px solid red;
}
section{
padding: 1rem;
font-size: 30px;
font-family: Arial, Helvetica, sans-serif;
}
</style>
</head>
<body>
<section id="vid">
<ol>
<li>How to do a frame grab from video on to canvas.</li>
<li>How to convert the frame grab to greyscale.</li>
<li>How to extract a binary image from the canvas.</li>
<li>How to load the binary image into an image element.</li>
<li>How to upload the binary image via fetch.</li>
<li>How to use the binary image as the poster for a new video element.</li>
</ol>
<!-- autoplay requires muted attribute in Chrome -->
<!--
remote = https://github.com/prof3ssorSt3v3/media-sample-files/blob/master/lion-sample.mp4?raw=true
local = ./lion-sample.mp4
-->
<video id="player" muted >
<source src="./lion-sample.mp4" type="video/mp4" />
</video>
</section>
<section id="can">
<canvas id="canvas"></canvas>
</section>
<section id="image"></section>
<script>
const grabScreen = () =>{
let player = document.getElementById('player')
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
canvas.width = player.videoWidth;
canvas.height = player.videoHeight;
//grab a frame from the video
ctx.drawImage(player, 0, 0);
//convert to grayscale image
//ONLY WORKS IF image is not tainted by CORS
let imgdata = ctx.getImageData(0,0, canvas.width, canvas.height);
let len = imgdata.data.length;
//width * height * 4 = length of the array
for(let i=0; i<len; i=i+4){
let red = imgdata.data[i];
let green = imgdata.data[i+1];
let blue = imgdata.data[i+2];
//let lum = .2126 * red + .7152 * green + .0722 * blue;
let lum = (red + green + blue)/3;
imgdata.data[i] = lum;
imgdata.data[i+1] = lum;
imgdata.data[i+2] = lum;
}
//update what is displayed on the canvas.
ctx.putImageData(imgdata, 0, 0);
//export as image file to be uploaded or saved
let blob = canvas.toBlob((blob) => {
//this code runs AFTER the Blob is extracted
let fd = new FormData();
fd.append('field-name', blob, 'image-filename.png');
let req = new Request('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: fd
})
fetch(req)
.then(response=>response.json())
.then(data=>{
console.log('response from server after uploading the image');
})
.catch(err=>{
console.log(err.message);
});
//load the blob into the image tag
let img = document.createElement('img');
let url = URL.createObjectURL(blob);
img.addEventListener('load', (ev)=>{
console.log('image from createObjectURL loaded');
//player.pause(); //stop the video playing if desired
//let vid = document.createElement('video');
//vid.poster = url;
//document.body.appendChild(vid);
//clear memory used to create object url
//this will make it impossible to download the image with a right click
//window.URL.revokeObjectURL(url);
})
img.src = url; //use the canvas binary png blob
document.getElementById('image').appendChild(img);
}, 'image/png'); //create binary png from canvas contents
}
//MEDIA EVENTS
//https://developer.mozilla.org/en-US/docs/Web/Events#Media_events
document.addEventListener('DOMContentLoaded', ()=>{
let player = document.getElementById('player');
player.addEventListener('canplay', (ev)=>{
console.log('canplay', ev.target.videoWidth, ev.target.videoHeight);
console.log(ev.target.clientWidth, ev.target.clientHeight);
console.log(ev.target.currentSrc, ev.target.duration, ev.target.currentTime);
player.addEventListener('click', (ev)=>{
//click the video to grab a screenshot and display in the canvas
grabScreen();
})
});
player.addEventListener('canplaythrough', (ev)=>{
//this is our own autoplay
console.log('Enough loaded to play through whole video');
player.play();
});
player.addEventListener('load', (ev)=>{
//video has loaded entirely
console.log('video loaded');
});
player.addEventListener('error', (err)=>{
console.log('Failed to load video', err.message);
})
})
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment