Dette er oppfølgeren til bloggposten om ASCII. Der kan du lese om hvordan webteknologi kan gjøre om pikslene i et bilde til ASCII og emojier.

Nå tar vi det et steg videre, og bruker webcam-APIet i nettleseren for å gjøre en strøm av bilder om til en strøm av emojier 👻👻👻

¶Demotid

Før jeg forklarer hvordan det funker, la oss se på det ferdige produktet.

¶Hvordan funker det?

En video er bare en sekvens med bilder. Fra den forrige bloggposten så vet vi hvordan vi gjør pikslene i et enkelt bilde til emojier. Det eneste vi trenger å gjøre er:

  1. Be om tilgang til webkamera
  2. Ved jevne mellomrom, ta et bilde fra webkamera-strømmen
  3. Tegne det bildet til et canvas-element
  4. Bruke canvas-APIet til å lese ut pikseldata, akkurat som i forrige bloggpost

Tilgang til webkamera

For å lese en videostrøm fra et webkamera, så bruker vi mediaDevices-APIet i nettleseren. Det er godt støtta på tvers av alle nettlesere og gir oss mulighet til å be om tilgang til brukerens audio- og videoenheter.

Å starte en videostrøm kan gjøres på følgende måte:

const stream = await navigator.mediaDevices.getUserMedia({
  audio: false,
  video: true
});

Da vil brukeren bli bedt om å godkjenne at siden får tilgang til et kamera. APIet tilbyr flere muligheter for å tilpasse hvilken enhet du vil ha tilgang til, f.eks kan du lett be om kameraet som peker fremover eller bakover på en mobiltelefon. For våres formål i denne bloggposten så holder vi det enkelt, men her er det altså masse rom for tilpasning.

For å starte videoen så trenger vi et video-element på siden.

<video style="display:none"
       playsinline 
       muted />

Vi bryr oss ikke om å se den faktiske videostrømmen, så den gjemmer vi med display:none. Attributtet playsinline betyr at videoen spiller i siden, istedenfor fullscreen. Merk at på Safari så vil ikke videoen spille med mindre video-elementet er innenfor skjermen, så der må du jukse litt med CSS for å tvinge elementet til å alltid være innenfor viewporten.

Deretter tar vi kamera-strømmen og sender til et video-element på siden:

videoElement = document.querySelector('video');
videoElement.srcObject = stream;
await videoElement.play();

Ta et bilde fra strømmen

Her bruker vi canvas-APIet til å lese ut et bilde. Der kan vi bruke context.drawImage() som tar en CanvasImageSource som input. Det kan være et bilde, men det kan også være et video-element.

type CanvasImageSource = 
  HTMLOrSVGImageElement | 
  HTMLVideoElement | 
  HTMLCanvasElement | 
  ImageBitmap;

Så da gjør vi bare:

const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
context.drawImage(videoElement, 0, 0, width, height)

Hente ut pikseldata fra videobildet

Ã… hente ut alle pikslene i bildet blir da:

const imageData = context.getImageData(0, 0, width, height)

Dette kan vi så konvertere til emojier på akkurat samme måte som jeg viste i forrige bloggpost.

Verre var det ikke. Webteknologi slutter aldri å overraske!

¶Del 3?

Videomoji er morro, men det kan bli enda bedre. Det neste jeg skal gjøre er å mappe alle emojiene som finnes til fargen de best passer til. Da får vi en videostrøm med farger!

Hvis du vil prøve dette ut på egenhånd, så kan du lese kildekoden her