
Compartir:
Antiguo defensor de los desarrolladores de Vonage, donde su función era apoyar a la comunidad tecnológica local de Londres. Es un experimentado organizador de eventos, jugador de mesa y padre de un precioso perrito llamado Moo. También es el principal organizador de You Got This, una red de eventos sobre las habilidades básicas necesarias para una vida laboral feliz y saludable.
Utiliza una pantalla verde en Javascript con Vonage Video
Tiempo de lectura: 4 minutos
Al crear un editor de Vonage Video, la transmisión puede provenir directamente de una cámara de usuario, de un elemento <video> o un elemento HTML <canvas> elemento. Una vez que los píxeles se dibujan en el lienzo, se pueden manipular fácilmente antes de utilizarlos en una sesión de Video API.
En este tutorial, aprenderás a eliminar una pantalla verde y sustituirla por una nueva imagen personalizada que podrás incluir en tus videollamadas.
Overview of the project components
Para que el proyecto funcione se necesitan varios componentes. En primer lugar, un elemento <video> tomará una secuencia de la cámara del usuario. En cada fotograma, el contenido del elemento Video se dibujará en un lienzo, donde haremos un bucle a través de los píxeles para eliminar los que sean verdes. En un segundo lienzo, dibujaremos la imagen de fondo de sustitución y, a continuación, superpondremos los píxeles no verdes del primer lienzo.
Con nuestra salida deseada en un lienzo, podemos utilizar el lienzo como fuente para un editor de la Video API de Vonage, que podemos utilizar en nuestras sesiones de vídeo con amigos.
Si desea ver el código terminado, puede encontrarlo en https://github.com/nexmo-community/video-green-screen
Marcado de andamios
Cree una nueva carpeta de proyecto seguida de un nuevo archivo index.htmlpoblando este archivo con el siguiente código:
<!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>
También necesitará la imagen que desea reemplazar su pantalla verde dentro de la carpeta del proyecto. Este tutorial utilizará uno de los degradados de la marca Vonage. Después de obtener los contextos del lienzo, carga la imagen:
const backgroundImage = new Image()
backgroundImage.src = 'vonage-gradient.png' Obtener Video de Webcam
Establece la <video> a la transmisión de la cámara web del usuario. Este fragmento elegirá la cámara predeterminada:
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => { v1.srcObject = stream })
Cree una función process() vacía. Una vez que el dispositivo de vídeo del usuario esté listo y 'reproduciendo', ejecuta la función cada fotograma:
v1.addEventListener('play', () => {
setInterval(process, 0)
})
function process() {
}
Dibujar una secuencia de Video en el lienzo
Actualización process():
function process() {
c1Ctx.drawImage(v1, 0, 0, 320, 240)
c2Ctx.drawImage(backgroundImage, 0, 0, 320, 240)
}Actualice su página y debería ver su elemento <video> su primer elemento <canvas> con una imagen duplicada, y el segundo <canvas> con la nueva imagen de fondo. El objetivo es conseguir cualquier píxeles no verdes en la parte superior del fondo en el segundo lienzo.
Bucle de píxeles
En un lienzo, toda la imagen representada en una única matriz larga de píxeles. Aunque inicialmente creas que nuestra imagen de 320x240 tendrá 76.800 entradas en la matriz, te equivocarías.
canvas pixels
Cada píxel visible se compone de cuatro elementos de matriz: uno para su valor rojo, otro para el verde, otro para el azul y el último para establecer su opacidad. Estos valores son importantes a medida que construimos y utilizamos el bucle.
Obtenga la matriz de píxeles de este fotograma dentro de la función process() y construye el bucle:
const frame = c1Ctx.getImageData(0, 0, 320, 240)
const pixels = frame.data
for(let i=0; i<pixels.length; i+=4) {
}Observe que el contador está configurado para incrementarse en 4. Cada vez que se ejecute este bucle, i será el índice de la matriz del valor rojo del siguiente píxel visible.
Comprender HSL
Antes de eliminar los píxeles verdes, me gustaría presentarte el formato de color Tono Saturación Luminosidad (HSL).
Hue is a color wheel, sauturation is the amount of grey, lightness is a scale of black to whitePuedes pensar en el matiz como en una rueda de colores, y utilizar la posición en la rueda para especificar un color, de 0 a 360. La "gama" verde puede variar según la persona, pero de 90 a 200 funciona bien para mí. La "gama" verde puede ser diferente para cada persona, pero de 90 a 200 me funciona bien.
Sin embargo, al leer y escribir píxeles en un archivo <canvas> debe utilizar el formato de color rojo, verde y azul (RGB). En la parte inferior de su <script>añada esta función RGBToHSL() función proporcionada en Trucos CSS
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]
} Hacer transparentes los píxeles verdes
Dentro del bucle process() obtenga los valores RGB y HSL de cada píxel y establezca los píxeles verdes como transparentes:
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
}Después del bucle, actualiza la imagen del lienzo:
frame.data = pixels
c1Ctx.putImageData(frame, 0, 0)Usted puede encontrar que 90 y 200 necesita actualizarse, dado el color de tu pantalla y la iluminación.
The first canvas has no background - appearing white
Dibujar los píxeles restantes en el fondo de sustitución
Por cada píxel que quede en el primer lienzo, dibújalo en el segundo. Después de la sentencia if en el bucle process() añada una else condición:
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)
}En x y y son los píxeles visuales, por lo que el valor i debe dividirse por 4.
The second canvas now has the non-removed pixels
Incluir Canvas en la sesión de Video API
Crea un nuevo proyecto en tu Panel de Video de Vonage. Una vez creado, desplázate hasta Herramientas del proyecto y crea una nueva sesión enrutada. Toma el ID de sesión y crea un nuevo token.
En la parte superior de su <script>crea tres nuevas variables con los datos del cuadro de mandos del proyecto:
const sessionId = 'YOUR_SESSION_ID'
const apiKey = 'YOUR_PROJECT_API_KEY'
const token = 'YOUR_TOKEN'A continuación, copie la etiqueta <script> de la página página del Client SDK de la Video API de Vonage y colócala sobre tu etiqueta <script> existente.
En la parte inferior de tu etiqueta <script> obtén tu sesión básica de la Video API de Vonage inicializada y publícala desde el segundo lienzo:
// 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")
}) Ocultar elementos
En <video> y <canvas> son necesarios para que esto funcione, pero probablemente no quieras que sean visibles en tu página web. En su <head>añade el siguiente CSS para ocultarlos:
<style>
#v1, #c1, #c2 { display: none }
</style> ¿Cuáles serán sus antecedentes?
Esperamos que esta entrada del blog te haya resultado útil y que ahora puedas crear fondos personalizados a tu antojo. Aunque nos hemos centrado en las pantallas verdes, cualquier manipulación a nivel de píxel se puede hacer con el mismo enfoque.
Para llevar esto más lejos, puede optar por proporcionar a los usuarios controles que modifiquen los valores HSL que están "dentro del rango" a sustituir, o un selector de archivos para cambiar la imagen.
Puede encontrar el proyecto final en https://github.com/nexmo-community/video-green-screen
Como siempre, si necesitas ayuda, no dudes en ponerte en contacto con nosotros en la Slack de la comunidad de desarrolladores de Vonage. Esperamos verte allí.
Compartir:
Antiguo defensor de los desarrolladores de Vonage, donde su función era apoyar a la comunidad tecnológica local de Londres. Es un experimentado organizador de eventos, jugador de mesa y padre de un precioso perrito llamado Moo. También es el principal organizador de You Got This, una red de eventos sobre las habilidades básicas necesarias para una vida laboral feliz y saludable.