https://d226lax1qjow5r.cloudfront.net/blog/blogposts/video-ai-enhancing-video-streams-with-qr-codes-and-watermarking/videoai_qr-codes-watermarking.png

Video + AI: Mejora de los flujos de vídeo con códigos QR y marcas de agua

Publicado el August 8, 2023

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

  1. Instalar Node y npm

  2. Copiar el repositorio GitHub

  3. Ejecutar npm install

  4. Ejecutar 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 generator transformerQR 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 formWatermark 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 exampleQR code generator example

Watermark generator exampleWatermark 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:

https://a.storyblok.com/f/270183/400x266/5bd495df3c/enrico-portolan.png
Enrico PortolanAutor invitado

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.