
Compartilhar:
Enrico é um ex-funcionário da Vonage. Ele trabalhou como engenheiro de soluções, auxiliando a equipe de vendas com seus conhecimentos técnicos. Ele é apaixonado pela nuvem, por startups e por novas tecnologias. É cofundador de uma startup de WebRTC na Itália. No tempo livre, gosta de viajar e experimentar o máximo possível de comidas exóticas.
Vídeo + IA: Aprimorando transmissões de vídeo com códigos QR e marcas d’água
Tempo de leitura: 4 minutos
Este artigo foi atualizado em maio de 2025
Introdução
Na era digital atual, aprimorar transmissões de vídeo tornou-se uma prática cada vez mais comum, seja para fins de identidade visual, publicidade ou para fornecer informações adicionais de maneira não intrusiva. Esta postagem do blog tem como objetivo orientá-lo sobre como adicionar códigos QR e marcas d’água a uma transmissão de vídeo usando a Video API da Vonage.
Para isso, vamos aproveitar os recursos da API do Media Processor. Essa API inovadora oferece a funcionalidade de personalizar fluxos de áudio e vídeo por meio da integração de transformadores ao fluxo. Uma análise detalhada da API e de seus possíveis usos será apresentada mais adiante nesta postagem do blog.
Resumo: Se você quiser pular essa parte e ir direto para a implantação, pode encontrar todo o código do aplicativo no GitHub
Configuração do projeto
Instale o Node e o npm
Copie o repositório do GitHub
Correr
npm installCorrer
npm run serve
API de Processadores de Mídia
A biblioteca Vonage Media Processor, disponível via npm, é uma ferramenta poderosa que simplifica o uso da API Insertable Streams para transformar faixas de vídeo e áudio. Para os fins desta postagem no blog, utilizaremos apenas os métodos relacionados a vídeo.
A biblioteca apresenta duas classes principais:
MediaProcessor: Essa classe gerencia transformadores e inclui um
setTransformers()método para configurar os transformadores.MediaProcessorConnector: Essa classe requer um objeto MediaProcessor para seu construtor e é responsável por lidar com as faixas de entrada e saída. Embora a implementação das faixas seja feita pelo Vonage Video JS Client, basta fornecer a instância do MediaProcessorConnector. Você pode encontrar a documentação relevante em https://developer.vonage.com/en/video/guides/media-processor/web
Vamos agora nos aprofundar na criação dos processadores de vídeo para o recurso de código QR e marca d’água.
Como usar códigos QR
Os códigos QR têm inúmeras aplicações em situações da vida real. Eles podem conter dados como URLs, texto etc., que podem ser lidos por meio da câmera de um smartphone. Em uma transmissão de Video, os códigos QR podem ser usados para diversos fins, como redirecionar o usuário para um URL específico, exibir um texto personalizado para o usuário e muito mais.
Imagine estar realizando um webinar em que você queira compartilhar links úteis com seus espectadores. Ao integrar um código QR à sua transmissão ao vivo, você pode direcionar seu público a esses links sem esforço, oferecendo a eles uma maneira fácil e em tempo real de acessar conteúdos relevantes.
Implementação técnica
Estamos gerando códigos QR usando um transformador personalizado. Para gerar o código QR, estamos usando uma biblioteca de terceiros chamada QrCode. A URL do código QR é fornecida pelo usuário. Usamos o qrCode transformador do nosso transformers diretório para criar e posicionar o código QR no fluxo de Video. É possível personalizar a posição e o tamanho do 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' })
);
}
Na interface do usuário, é possível definir a URL do código QR, o tamanho e a posição do código QR no fluxo de Video.
QR code transformer
Como usar marcas d’água
As marcas d’água são comumente utilizadas para identificar a marca e proteger conteúdos digitais. No contexto do streaming de Video, uma marca d’água pode ter diversas finalidades: pode ser o logotipo de uma empresa para identificação da marca, o símbolo de direitos autorais para proteção do conteúdo ou qualquer outra imagem, aliás.
Implementação técnica
Para a inserção de marca d’água, aceitamos um arquivo de imagem do usuário como entrada. A imagem selecionada é então invertida horizontalmente para neutralizar o efeito de espelhamento do fluxo de Video. O watermark transformador do nosso transformers diretório posiciona então a marca d’água no fluxo de Video. Você pode personalizar a posição da marca d’água.
_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
Explicação passo a passo do código
Na página principal, começamos importando os pacotes necessários e inicializando o publicador de fluxo de Video. Temos dois formulários, um para cada funcionalidade (código QR e marca d’água). O formulário apropriado é exibido de acordo com a seleção do usuário.
Na applyQrCode função, recuperamos as entradas do usuário para o código QR (URL, tamanho e posição), configuramos o transformador de código QR e o aplicamos ao fluxo de Video.
Da mesma forma, na applyWatermark função, pegamos a imagem enviada, ajustamos conforme necessário (invertemos horizontalmente), configuramos o transformador de marca d’água e o aplicamos ao fluxo de Video.
O botão “Aplicar” chama a função apropriada com base na opção selecionada, e o botão “Limpar” pode ser usado para remover todas as transformações do fluxo de Video.
QR code generator example
Watermark generator example
Conclusão
Aprimorar transmissões de vídeo com a adição de códigos QR ou marcas d’água é uma maneira eficaz de aumentar a interatividade, agregar valor e proteger o conteúdo. Com a Video API da Vonage e um pouco de JavaScript, é bastante simples adicionar esses recursos a uma transmissão de vídeo. Espero que você tenha achado esta postagem útil e te encorajo a experimentar diferentes maneiras de usar transformações em transmissões de Video para aprimorar seus projetos.
Você pode encontrar o repositório de código no GitHub aqui. Se tiver dúvidas ou sugestões, junte-se a nós no Slack dos desenvolvedores da Vonage ou envie-nos uma mensagem no X, e entraremos em contato com você!
Compartilhar:
Enrico é um ex-funcionário da Vonage. Ele trabalhou como engenheiro de soluções, auxiliando a equipe de vendas com seus conhecimentos técnicos. Ele é apaixonado pela nuvem, por startups e por novas tecnologias. É cofundador de uma startup de WebRTC na Itália. No tempo livre, gosta de viajar e experimentar o máximo possível de comidas exóticas.