
Compartir:
Enrico es un antiguo miembro del equipo de Vonage. Trabajó como ingeniero de soluciones, ayudando al equipo de ventas con su experiencia técnica. Es un apasionado de la nube, las startups y las nuevas tecnologías. Es cofundador de una startup WebRTC en Italia. Fuera del trabajo, le gusta viajar y probar tantas comidas raras como sea posible.
Video + AI: Mejora de los flujos de vídeo con códigos QR y marcas de agua
Tiempo de lectura: 4 minutos
Este artículo se actualizó en mayo de 2025
Introducción
En la era digital actual, la mejora de las transmisiones de video se ha convertido en una práctica cada vez más popular, ya sea para la marca, la publicidad o para proporcionar información adicional de una manera no intrusiva. Esta publicación del blog tiene como objetivo mostrarte cómo agregar códigos QR y marcas de agua a una transmisión de video usando la Video API de Vonage.
Para lograrlo, aprovecharemos las posibilidades de la Media Processor API. Esta innovadora API permite personalizar los flujos de audio y vídeo integrando transformadores en el flujo. Más adelante exploraremos en detalle la API y sus posibles usos.
TL;DR: Si desea saltar por delante y obtener derecho a desplegarlo, usted puede encontrar todo el código de la aplicación en GitHub
Configuración del proyecto
Instalar Node y npm
Copiar el repositorio GitHub
Ejecutar
npm installEjecutar
npm run serve
API de procesadores multimedia
La librería Vonage Media Processor, disponible vía npm, es una poderosa herramienta que simplifica el uso de la API Insertable Streams para transformar pistas de video y audio. Para el propósito de esta entrada de blog, vamos a utilizar sólo los métodos de Video.
La biblioteca introduce dos clases principales:
MediaProcessor: Esta clase gestiona los transformadores y viene con un
setTransformers()para configurar los transformadores.MediaProcessorConnector: Esta clase requiere un objeto MediaProcessor para su constructor y es responsable de manejar las pistas de entrada y salida. Mientras que de la implementación de las pistas se encarga el cliente de Video JS de Vonage, tú sólo necesitas suministrar la instancia de MediaProcessorConnector. Puedes encontrar la documentación pertinente en https://developer.vonage.com/en/video/guides/media-processor/web
Pasemos ahora a la creación de los procesadores de Video para la función de Código QR y Marca de Agua.
Uso de códigos QR
Los códigos QR han encontrado numerosos usos en el mundo real. Pueden contener datos como URL, texto, etc., que pueden escanearse con la cámara de un smartphone. En un flujo de vídeo, los códigos QR pueden utilizarse por varias razones, como redirigir al usuario a una URL específica, mostrar texto específico del usuario, etc.
Imagine que organiza un seminario web en el que desea compartir enlaces útiles con sus espectadores. Si integras un código QR en tu retransmisión en directo, podrás dirigir sin esfuerzo a tu audiencia a estos enlaces, ofreciéndoles un método fácil y en tiempo real de acceder a contenido relevante.
Aplicación técnica
Estamos generando Códigos QR usando un transformador personalizado. Para generar el código QR, estamos utilizando una librería de terceros llamada QrCode. La URL para el código QR se toma como entrada del usuario. Utilizamos el qrCode de nuestro directorio transformers para crear y colocar el código QR en la secuencia de vídeo. Puede personalizar la posición y el tamaño del código QR.
// file add-qr-code.js
_createQrCodeWithBorder() {
// --- Step 1: Generate the base QR code using the library ---
// Create a temporary container DIV (required by qrcode.js)
// This div is never added to the document.
let tempQrContainer = document.createElement('div');
// Generate the QR code *without* internal padding/border from the lib
new QRCode(tempQrContainer, {
text: this.text,
width: this.qrWidth, // Use the data area width
height: this.qrHeight, // Use the data area height
colorDark: this.colorDark,
colorLight: this.colorLight, // Background of QR code itself
correctLevel: QRCode.CorrectLevel.H, // Or choose appropriate level
});
// qrcode.js generates either a <canvas> or an <img> inside the div.
// Prefer canvas if available.
const originalQrCanvas = tempQrContainer.querySelector('canvas');
const originalQrImg = tempQrContainer.querySelector('img');
if (!originalQrCanvas && !originalQrImg) {
throw new Error('QRCode library did not generate canvas or img element.');
}
// --- Step 2: Create the final canvas with the border ---
const finalCanvas = new OffscreenCanvas(this.finalWidth, this.finalHeight);
const finalCtx = finalCanvas.getContext('2d');
if (!finalCtx) {
throw new Error('Unable to create final QR CanvasRenderingContext2D');
}
// --- Step 3: Draw the border (background) and the QR code ---
// Fill the entire final canvas with the border color (usually white)
finalCtx.fillStyle = this.colorLight; // Use colorLight for the border
finalCtx.fillRect(0, 0, this.finalWidth, this.finalHeight);
// Draw the generated QR code (canvas or img) onto the center of the final canvas
const drawX = this.borderSize;
const drawY = this.borderSize;
if (originalQrCanvas) {
finalCtx.drawImage(
originalQrCanvas,
drawX,
drawY,
this.qrWidth,
this.qrHeight
);
} else {
// If it generated an image, draw the image
finalCtx.drawImage(
originalQrImg,
drawX,
drawY,
this.qrWidth,
this.qrHeight
);
}
// No need for the temporary div anymore
tempQrContainer = null; // Let garbage collection handle it
console.log('QR Code with border generated successfully.');
return finalCanvas; // Return the canvas with the border
}
async transform(frame, controller) {
// Ensure QR code generation was successful
if (!this.qrCanvasWithBorder_) {
// If QR code failed, just pass the frame through unmodified
controller.enqueue(frame);
return;
}
// Resize internal canvas only if needed (slight optimization)
if (
this.canvas_.width !== frame.displayWidth ||
this.canvas_.height !== frame.displayHeight
) {
this.canvas_.width = frame.displayWidth;
this.canvas_.height = frame.displayHeight;
}
const timestamp = frame.timestamp;
// Draw the incoming video frame
this.ctx_.drawImage(frame, 0, 0);
frame.close(); // Close the original frame
// Draw the pre-generated QR code (with border) onto the video frame
// Use the finalWidth and finalHeight for drawing
this.ctx_.drawImage(
this.qrCanvasWithBorder_,
this.x, // Position defined in constructor
this.y, // Position defined in constructor
this.finalWidth, // Draw with full border width
this.finalHeight // Draw with full border height
);
// Enqueue the modified frame
controller.enqueue(
new VideoFrame(this.canvas_, { timestamp, alpha: 'discard' })
);
}
Desde la interfaz de usuario, puede establecer la URL del código QR, el tamaño y la posición del código QR en la secuencia de vídeo.
QR code transformer
Uso de marcas de agua
Las marcas de agua se utilizan habitualmente para marcar y proteger contenidos digitales. En el contexto del streaming de vídeo, una marca de agua puede servir para múltiples propósitos: puede ser el logotipo de una empresa, un símbolo de copyright para proteger el contenido o cualquier otra imagen.
Aplicación técnica
Para la marca de agua, aceptamos como entrada un archivo de imagen del usuario. La imagen seleccionada se voltea horizontalmente para contrarrestar el efecto espejo del flujo de vídeo. El transformador watermark de nuestro directorio transformers coloca la marca de agua en el flujo de vídeo. Puede personalizar la posición de la marca de agua.
_computePosition(frame) {
if (this._position === "top-left") {
return { x: frame.displayWidth - 150, y: 0 };
} else if (this._position === "top-right") {
return { x: 0, y: 0 };
} else if (this._position === "bottom-left") {
return { x: frame.displayWidth - 150, y: frame.displayHeight - 150 };
} else if (this._position === "bottom-right") {
return { x: 0, y: frame.displayHeight - 150 };
}
return { x: 0, y: 0 };
}
async transform(frame, controller) {
this.canvas_.width = frame.displayWidth;
this.canvas_.height = frame.displayHeight;
const timestamp = frame.timestamp;
this.ctx_.drawImage(frame, 0, 0, frame.displayWidth, frame.displayHeight);
const { x, y } = this._computePosition(frame);
this.ctx_.drawImage(this._image, x, y, 100, 80);
frame.close();
controller.enqueue(
new VideoFrame(this.canvas_, { timestamp, alpha: "discard" })
);
}
Watermark transformer
Guía de códigos
En la página principal, empezamos importando los paquetes necesarios e inicializando el editor de flujo de vídeo. Tenemos dos formularios, uno para cada funcionalidad (Código QR y Marca de agua). El formulario apropiado se muestra en función de la selección del usuario.
En la función applyQrCode recuperamos los datos introducidos por el usuario para el código QR (URL, tamaño y posición), configuramos el transformador del código QR y lo aplicamos a la secuencia de vídeo.
Del mismo modo, en la función applyWatermark tomamos la imagen cargada, la ajustamos según sea necesario (volteamos horizontalmente), configuramos el transformador de marca de agua y lo aplicamos al flujo de vídeo.
El botón "Aplicar" llama a la función adecuada en función de la opción seleccionada, y el botón "Borrar" puede utilizarse para eliminar todas las transformaciones del flujo de vídeo.
QR code generator example
Watermark generator example
Conclusión
Mejorar las transmisiones de video agregando códigos QR o marcas de agua es una manera poderosa de aumentar la interactividad, agregar valor y proteger el contenido. Con la Video API de Vonage y un poco de JavaScript, es bastante sencillo agregar estas funciones a una transmisión de video. Espero que esta publicación del blog te haya resultado útil y te aliento a que experimentes con diferentes maneras de usar las transformaciones del flujo de video para mejorar tus proyectos.
Puede encontrar el repositorio de código GitHub aquí. Si tienes preguntas o comentarios, únete a nosotros en el Slack para desarrolladores de Vonage o envíanos un mensaje a Xy nos comunicaremos contigo.
Compartir:
Enrico es un antiguo miembro del equipo de Vonage. Trabajó como ingeniero de soluciones, ayudando al equipo de ventas con su experiencia técnica. Es un apasionado de la nube, las startups y las nuevas tecnologías. Es cofundador de una startup WebRTC en Italia. Fuera del trabajo, le gusta viajar y probar tantas comidas raras como sea posible.