Javascript Tutorial to Add Live Webcam Filter Effects to Video Using WebRTC API in Browser Full Project For Beginners

 

 

Welcome folks today in this blog post we will be adding live webcam filter effects to video using webrtc api in javascript. All the full source code of the application is shown below.

 

 

 

 

Get Started

 

 

 

In order to get started you need to make an index.html file and copy paste the following code

 

 

 

index.html

 

 

 

<div class="photobooth">
    <div class="controls">
      <button onClick="takePhoto()">Take Photo</button>
      <button class="filter" data-filter="1">Red Filter</button>
      <button class="filter" data-filter="2">RGB Split Filter</button>
      <button class="filter" data-filter="0">Remove Filter</button>
 <div class="rgb">
        <label for="rmin">Red Min:</label>
        <input type="range" min=0 max=255 name="rmin">
        <label for="rmax">Red Max:</label>
        <input type="range" min=0 max=255 name="rmax">
        <br>
        <label for="gmin">Green Min:</label>
        <input type="range" min=0 max=255 name="gmin">
        <label for="gmax">Green Max:</label>
        <input type="range" min=0 max=255 name="gmax">
        <br>
        <label for="bmin">Blue Min:</label>
        <input type="range" min=0 max=255 name="bmin">
        <label for="bmax">Blue Max:</label>
        <input type="range" min=0 max=255 name="bmax">
      </div>
    </div>
 
    <canvas class="photo"></canvas>
    <video class="player"></video>
    <div class="strip"></div>
  </div>

  <audio class="snap" src="http://wesbos.com/demos/photobooth/snap.mp3" hidden></audio>

 

 

 

And now make a style.css file and copy paste the following code

 

 

style.css

 

 

html {
  box-sizing: border-box;
}

*, *:before, *:after {
  box-sizing: inherit;
}

html {
  font-size: 10px;
  background:#ffc600;
}

.photobooth {
  background:white;
  max-width:150rem;
  margin: 2rem auto;
  border-radius:2px;
}

/*clearfix*/
.photobooth:after {
  content: '';
  display: block;
  clear: both;
}

.photo {
  width:100%;
  float:left;
}

.player {
  position: absolute;
  top:20px;
  right: 20px;
  width:200px;
}

/*
  Strip!
*/

.strip {
  padding:2rem;
}
.strip img {
  width:100px;
  overflow-x: scroll;
  padding:0.8rem 0.8rem 2.5rem 0.8rem;
  box-shadow:0 0 3px rgba(0,0,0,0.2);
  background:white;
}

.strip a:nth-child(5n+1) img { transform: rotate(10deg); }
.strip a:nth-child(5n+2) img { transform: rotate(-2deg); }
.strip a:nth-child(5n+3) img { transform: rotate(8deg); }
.strip a:nth-child(5n+4) img { transform: rotate(-11deg); }
.strip a:nth-child(5n+5) img { transform: rotate(12deg); }



button {
  position: relative;
  margin: 10px auto;
  margin-left: 10px;
  padding: 10px;
  width: 150px;

  overflow: hidden;

  border-width: 0;
  outline: none;
  border-radius: 2px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .6);
  
  background-color: #2ecc71;
  color: #ecf0f1;
  
  transition: background-color .3s;
}

button:hover, button:focus {
  background-color: #27ae60;
}

button > * {
  position: relative;
}

button:before {
  content: "";
  
  position: absolute;
  top: 50%;
  left: 50%;
  
  display: block;
  width: 0;
  padding-top: 0;
    
  border-radius: 100%;
  
  background-color: rgba(236, 240, 241, .3);
  
  -webkit-transform: translate(-50%, -50%);
  -moz-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  -o-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

button:active:before {
  width: 120%;
  padding-top: 120%;
  
  transition: width .2s ease-out, padding-top .2s ease-out;
}

/* Styles, not important */
*, *:before, *:after {
  box-sizing: border-box;
}

 

See also  Javascript Tutorial to Search,Filter and Sort HTML Table Rows in Browser Full Tutorial For Beginners

 

 

And now make a script.js file and copy paste the following code

 

 

script.js

 

 

 

console.clear();

const video = document.querySelector('.player');
const canvas = document.querySelector('.photo');
const ctx = canvas.getContext('2d');
const strip = document.querySelector('.strip');
const snap = document.querySelector('.snap');
const filterBtn = [...document.querySelectorAll('.filter')];
let interval;

function getVedio(){
  navigator.mediaDevices.getUserMedia({video: true, audio: false})
  .then(localMediaStream => {
    console.log(localMediaStream)
    video.srcObject = localMediaStream;
    // video.src = window.URL.createObjectURL(localMediaStream);
    video.play();
  })
  .catch(err =>
    console.error('Oops')
  )
};

function paintToCanvas(){
  const width = video.videoWidth;
  const height = video.videoHeight;
  let filterType = this.dataset.filter || 0;
  console.log(this.dataset, 'hi', filterType);
  
  canvas.width = width;
  canvas.height = height;
  
  clearInterval(interval);

  return interval = setInterval(() => {
    ctx.drawImage(video, 0, 0, width, height);
    // take the pixels out
    
    let pixels = ctx.getImageData(0, 0, width, height);
    // pixels 內最底部的陣列每四個為一組,分別代表 RGBA 的數值,一組結束後會接著排下一組
    
    // mess with them
    if(filterType == 1){
      pixels = redEffect(pixels);  
    } else if(filterType == 2){
      pixels = rgbSplit(pixels);
    } else {
      
    }
   
    // ctx.globalAlpha = 0.8;

    // pixels = greenScreen(pixels);
    // put them back
    ctx.putImageData(pixels, 0, 0);
  },16);
}

function takePhoto(){
  // 播放快門聲
  snap.currentTime = 0;
  snap.play();
  
  // 獲得 canvas 內的 data
  const data = canvas.toDataURL('image/jpeg');
  const link = document.createElement('a');
  link.setAttribute('download', 'hello');
  link.innerHTML = `<image src="${data}" alt="Hi">`;
  strip.insertBefore(link, strip.firstChild);
  
}

function redEffect(pixels) {
  for (let i = 0; i < pixels.data.length; i+=4) {
    pixels.data[i + 0] = pixels.data[i + 0] + 100; // RED
    pixels.data[i + 1] = pixels.data[i + 1] - 50; // GREEN
    pixels.data[i + 2] = pixels.data[i + 2] * 0.5; // Blue
  }
  return pixels;
}

function rgbSplit(pixels) {
  for (let i = 0; i < pixels.data.length; i+=4) {
    pixels.data[i - 150] = pixels.data[i + 0]; // RED
    pixels.data[i + 500] = pixels.data[i + 1]; // GREEN
    pixels.data[i - 550] = pixels.data[i + 2]; // Blue
  }
  return pixels;
}

getVedio();
video.addEventListener('canplay', paintToCanvas);
filterBtn.map(node => node.addEventListener('click', paintToCanvas));

Leave a Reply