
Partager:
Ancien Developer Advocate pour Vonage, où son rôle était de soutenir la communauté technologique locale à Londres. Il est un organisateur d'événements expérimenté, un joueur de jeux de société et le père d'un adorable petit chien appelé Moo. Il est également l'organisateur principal de You Got This - un réseau d'événements sur les compétences de base nécessaires pour une vie professionnelle heureuse et saine.
Utiliser un écran vert en Javascript avec Vonage Video
Temps de lecture : 4 minutes
Lors de la création d'un éditeur Video de Vonage, le flux peut provenir directement d'une caméra d'utilisateur, d'un élément <video> ou d'un élément HTML <canvas> ou d'un élément HTML. Une fois que les pixels sont dessinés sur le canevas, ils peuvent être facilement manipulés avant d'être utilisés dans une session Video API.
Dans ce tutoriel, vous apprendrez à supprimer un écran vert et à le remplacer par une nouvelle image personnalisée que vous pourrez inclure dans vos appels vidéo.
Overview of the project components
Plusieurs éléments sont nécessaires pour faire fonctionner le projet. Tout d'abord, un <video> prend un flux de données provenant de la caméra de l'utilisateur. À chaque image, le contenu de l'élément Video sera dessiné sur un canevas, où nous passerons en boucle les pixels pour supprimer ceux qui sont verts. Sur un second canevas, nous dessinerons l'image d'arrière-plan de remplacement, puis nous superposerons les pixels non verts du premier canevas.
Avec la sortie souhaitée sur un canevas, nous pouvons utiliser le canevas comme source pour un éditeur Video API de Vonage, que nous pouvons utiliser dans nos sessions vidéo avec des amis.
Si vous souhaitez consulter le code final, vous pouvez le trouver à l'adresse suivante https://github.com/nexmo-community/video-green-screen
Balisage de l'échafaudage
Créez un nouveau dossier de projet suivi d'un nouveau fichier index.htmlEn utilisant le code suivant, vous pouvez remplir ce fichier :
<!DOCTYPE html>
<html>
<head></head>
<body>
<video id="v1" width="320" height="240" autoplay></video>
<canvas id="c1" width="320" height="240"></canvas>
<canvas id="c2" width="320" height="240"></canvas>
<div id="opentok-publishers"></div>
<div id="opentok-subscribers"></div>
<script>
// Create references to the video and canvas elements
const v1 = document.getElementById('v1')
const c1 = document.getElementById('c1')
const c2 = document.getElementById('c2')
// Get canvas context
const c1Ctx = c1.getContext('2d')
const c2Ctx = c2.getContext('2d')
</script>
</body>
</html>
Vous aurez également besoin de l'image qui remplacera votre écran vert dans le dossier du projet. Ce tutoriel utilisera l'un des gradients de la marque dégradés de la marque Vonage. Après avoir obtenu les contextes du canevas, chargez l'image :
const backgroundImage = new Image()
backgroundImage.src = 'vonage-gradient.png' Obtenir la Video de la Webcam
Définir la source de l'élément <video> à la source de la webcam de l'utilisateur. Cet extrait sélectionnera la caméra par défaut :
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => { v1.srcObject = stream })
Créer une fonction process() vide. Une fois que le dispositif vidéo de l'utilisateur est prêt et "en cours de lecture", exécutez la fonction à chaque image :
v1.addEventListener('play', () => {
setInterval(process, 0)
})
function process() {
}
Dessiner un flux Video sur le canevas
Mise à jour process():
function process() {
c1Ctx.drawImage(v1, 0, 0, 320, 240)
c2Ctx.drawImage(backgroundImage, 0, 0, 320, 240)
}Rafraîchissez votre page, et vous devriez voir votre élément <video> votre premier élément <canvas> avec une image dupliquée, et votre deuxième <canvas> avec la nouvelle image d'arrière-plan. L'objectif est de faire en sorte que tous les pixels non verts se trouvent au-dessus de l'arrière-plan dans le deuxième canevas.
Boucle à travers les pixels
Dans un canevas, l'image entière est représentée par un seul long tableau de pixels. Bien que vous puissiez penser au départ que notre image 320x240 aura 76 800 entrées dans le tableau, vous vous trompez.
canvas pixels
Chaque pixel visible est constitué de quatre éléments de tableau - un pour sa valeur rouge, un pour le vert, un pour le bleu et le dernier pour définir son opacité. Ces valeurs sont importantes pour la construction et l'utilisation de la boucle.
Obtenez le tableau de pixels de cette image à l'intérieur de la fonction process() et construire la boucle :
const frame = c1Ctx.getImageData(0, 0, 320, 240)
const pixels = frame.data
for(let i=0; i<pixels.length; i+=4) {
}Notez que le compteur est configuré pour s'incrémenter de 4. Chaque fois que cette boucle s'exécute, i sera l'indice du tableau de la prochaine valeur rouge du pixel visible.
Comprendre HSL
Avant de supprimer les pixels verts, j'aimerais vous présenter le format de couleur Hue Saturation Lightness (HSL).
Hue is a color wheel, sauturation is the amount of grey, lightness is a scale of black to whiteVous pouvez considérer la teinte comme une roue chromatique et utiliser la position sur la roue pour spécifier une couleur, de 0 à 360. La "gamme" de verts peut être différente pour chaque personne, mais pour moi, la fourchette de 90 à 200 fonctionne bien.
Cependant, lors de la lecture et de l'écriture de pixels dans un <canvas> vous devez utiliser le format de couleur Rouge Vert Bleu (RVB). Tout en bas de votre <script>ajoutez la fonction RGBToHSL() fonction fournie sur CSS Tricks
function RGBToHSL(r, g, b) {
r /= 255; g /= 255; b /= 255;
let cmin = Math.min(r,g,b),
cmax = Math.max(r,g,b),
delta = cmax - cmin,
h = 0, s = 0, l = 0;
if (delta == 0) h = 0;
else if (cmax == r) h = ((g - b) / delta) % 6;
else if (cmax == g) h = (b - r) / delta + 2;
else h = (r - g) / delta + 4;
h = Math.round(h * 60);
if (h < 0) h += 360;
l = (cmax + cmin) / 2;
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
s = +(s * 100).toFixed(1);
l = +(l * 100).toFixed(1);
return [h, s, l]
} Rendre les pixels verts transparents
Dans la boucle process() récupère les valeurs RVB et HSL de chaque pixel, et rend les pixels verts transparents :
const [r, g, b] = [pixels[i], pixels[i+1], pixels[i+2]]
const [h, s, l] = RGBToHSL(r, g, b)
if(h > 90 && h < 200) {
pixels[i+3] = 0
}Après la boucle, l'image de la toile est mise à jour :
frame.data = pixels
c1Ctx.putImageData(frame, 0, 0)Vous pouvez constater que 90 et 200 a besoin d'être mis à jour, compte tenu de la couleur de votre écran et de l'éclairage.
The first canvas has no background - appearing white
Dessiner les pixels restants sur l'arrière-plan de remplacement
Pour chaque pixel restant dans le premier canevas, dessinez-le sur le second. Après l'instruction if dans la boucle process() ajoutez une condition else condition :
if(h > 90 && h < 200) {
pixels[i+3] = 0
} else {
c2Ctx.fillStyle = `rgba(${r}, ${g}, ${b}, 1)`
const x = (i/4) % 320
const y = Math.floor((i / 4) / 320)
c2Ctx.fillRect(x, y, 1, 1)
}Les x et y sont les pixels visuels, de sorte que la valeur i doit donc être divisée par 4.
The second canvas now has the non-removed pixels
Inclure le canevas dans la session Video API
Créez un nouveau projet dans votre tableau de bord Video de Vonage. Une fois créé, faites défiler vers le bas jusqu'à Outils de projet et créez une nouvelle session acheminée. Prenez l'ID de la session et créez un nouveau jeton.
En haut de votre <script>créez trois nouvelles variables avec les données du tableau de bord du projet :
const sessionId = 'YOUR_SESSION_ID'
const apiKey = 'YOUR_PROJECT_API_KEY'
const token = 'YOUR_TOKEN'Ensuite, copiez la balise <script> de la page Video API Client SDK de Vonage et placez-la au-dessus de votre balise <script> existante.
Au bas de votre balise <script> initialisez votre session Video API de base et publiez-la à partir du deuxième canevas :
// Initialize session
const session = OT.initSession(apiKey, sessionId)
// Create publisher
const publisher = OT.initPublisher("opentok-publishers", {
videoSource: c2.captureStream().getVideoTracks()[0],
width: 320,
height: 240
})
// Once connected to session, publish the publisher
session.connect(token, () => {
session.publish(publisher)
})
// Show other users' streams
session.on('streamCreated', event => {
session.subscribe(event.stream, "opentok-subscribers")
}) Cacher les éléments
Les <video> et <canvas> sont nécessaires pour que cela fonctionne, mais vous ne voulez probablement pas qu'ils soient visibles dans votre page web. Dans votre <head>ajoutez la feuille de style CSS suivante pour les masquer :
<style>
#v1, #c1, #c2 { display: none }
</style> Quels seront vos antécédents ?
Nous espérons que ce billet vous a été utile et que vous pouvez désormais créer des arrière-plans personnalisés à votre guise. Bien que nous nous soyons concentrés sur les écrans verts, toute manipulation au niveau du pixel peut être réalisée avec la même approche.
Pour aller plus loin, vous pouvez choisir de fournir aux utilisateurs des contrôles qui modifient les valeurs HSL qui sont "dans la plage" à remplacer, ou un sélecteur de fichier pour modifier l'image.
Vous trouverez le projet final à l'adresse suivante https://github.com/nexmo-community/video-green-screen
Comme toujours, si vous avez besoin d'aide, n'hésitez pas à nous contacter dans le Slack de la communauté des développeurs de Vonage. Communauté des développeurs de Vonage Slack. Nous espérons vous y voir.
Partager:
Ancien Developer Advocate pour Vonage, où son rôle était de soutenir la communauté technologique locale à Londres. Il est un organisateur d'événements expérimenté, un joueur de jeux de société et le père d'un adorable petit chien appelé Moo. Il est également l'organisateur principal de You Got This - un réseau d'événements sur les compétences de base nécessaires pour une vie professionnelle heureuse et saine.