- Blog ➔
- Programação ↴
Como criar thumbnails para seus vídeos automaticamente com Node.js
A melhor forma de criar thumbnails para seus vídeos no Instagram
Escrito em 25 de outubro de 2023 - 🕒 5 min. de leituraApenas na semana passada eu postei sobre como fazer upload de Reels para o Instagram usando Node.js, e no código era possível fazer upload de um thumbnail para o vídeo também, mas eu não expliquei como criar esse thumbnail.
I mean, claro que você pode ir para no Photopea e criar um thumbnail para o seu vídeo, mas e se você quiser automatizar esse processo? E se você quiser criar um thumbnail diferente para todos os seus vídeos automaticamente?
Bem, é isso que eu vou te mostrar hoje.
Encontrando o package certo
Como um desenvolvedor frontend, a única coisa que eu sei sobre manipulação de imagens é usando canvas, e felizmente existe um package para Node.js que nos permite fazer isso, ele se chama node-canvas.
Com ele, nós podemos criar um canvas, desenhar imagens, textos, formas, etc. É bem legal, dê uma olhada no exemplo abaixo:
const { createCanvas, loadImage } = require('canvas');
const { writeFileSync } = require('fs');
const canvas = createCanvas(200, 200);
const ctx = canvas.getContext('2d');
ctx.font = '30px Impact';
ctx.fillStyle = '#000';
ctx.fillText('Hello World!', 0, 0);
canvas.toBuffer('image/png', (err, buffer) => {
writeFileSync('./hello-world.png', buffer);
});
Criando um design
Eu não sou um designer, então eu não vou te ensinar como criar um bom design, mas eu posso te mostrar como eu criei o design para as minhas thumbnails.
Eu comecei criando um novo arquivo no Photopea com o mesmo tamanho do vídeo do Instagram Reels, que é 1080x1920px. Então eu adicionei uma imagem de fundo e um texto com o título do vídeo, e também uma cor de fundo para o texto com um pouco de opacidade.
E para finalizar, eu adicionei uma imagem com fundo transparente com uma imagem minha em pixel art.
Criando a thumbnail
Agora que nós temos o design, nós podemos começar a programar. Primeiro, nós precisamos criar uma função que irá criar a thumbnail para nós, e ela irá receber uma imagem de fundo, uma imagem de primeiro plano, um título e o caminho para salvar a thumbnail como parâmetros.
const generateImageForPost = async (
backgroundImagePath,
foregroundImagePath,
title,
outputPath
) => {
const backgroundImage = await loadImage(backgroundImagePath);
const foregroundImage = await loadImage(foregroundImagePath);
const canvas = createCanvas(backgroundImage.width, backgroundImage.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(foregroundImage, 0, 0);
// TODO add text
// addCenteredTextWithBackground(ctx, title, canvas.width, canvas.height);
await new Promise((resolve, reject) => {
const out = createWriteStream(outputPath);
const stream = canvas.createPNGStream();
stream.pipe(out);
out.on('finish', () => {
console.log('The PNG file was created.');
resolve();
});
out.on('error', (err) => {
reject(err);
});
});
};
Esse código irá carregar as imagens de fundo e primeiro plano, criar um canvas com o mesmo tamanho da imagem de fundo, desenhar a imagem de primeiro plano no canvas, e salvar o canvas como um arquivo PNG. Essa foi a parte fácil, agora nós precisamos adicionar o texto.
O desafio aqui é adicionar o texto no centro do canvas, e garantir que ele não irá ultrapassar o canvas. Vamos ver como podemos fazer isso.
Adicionando o texto
Primeiro, nós precisamos criar uma função que irá adicionar o texto no centro do canvas, e ela irá receber o texto e o canvas como parâmetros. Nós iremos fazer isso na função addCenteredTextWithBackground
.
const addCenteredTextWithBackground = (
ctx,
text,
canvasWidth,
canvasHeight
) => {
const fontSize = 150;
ctx.font = `${fontSize}px Impact`;
const lines = text.split(' ');
const textHeight = fontSize * lines.length;
const rectWidth = canvasWidth;
const rectHeight = textHeight + 60;
const rectX = (canvasWidth - rectWidth) / 2;
const rectY = 300;
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(rectX, rectY, rectWidth, rectHeight);
ctx.fillStyle = 'white';
for (const [i, line] of lines.entries()) {
const textX = (canvasWidth - ctx.measureText(line).width) / 2;
const textY = rectY + fontSize * (i + 1);
ctx.fillText(line, textX, textY);
}
};
Essa função irá calcular o tamanho do retângulo que será o fundo do texto, e então irá desenhar o retângulo e o texto no canvas. Infelizmente, apenas fazer text.split(' ');
não irá funcionar, porque dividir o texto por espaços irá simplesmente aumentar a altura do texto, mas não necessariamente irá fazer o texto caber no canvas.
Então vamos criar uma função chamada breakTextToFitCanvas
que irá receber o texto, o contexto do canvas e uma largura máxima como parâmetros, e irá retornar um array de strings com o texto dividido em linhas que irão caber no canvas.
const breakTextToFitCanvas = (ctx, text, maxWidth) => {
const words = text.split(' ');
const lines = [];
let currentLine = words[0];
for (let i = 1; i < words.length; i++) {
const word = words[i];
const { width } = ctx.measureText(`${currentLine} ${word}`);
if (width < maxWidth) {
currentLine += ` ${word}`;
} else {
lines.push(currentLine);
currentLine = word;
}
}
lines.push(currentLine);
return lines;
};
Juntando tudo
Agora que nós temos todas as funções que precisamos, nós podemos juntar tudo e criar a thumbnail. Vamos criar uma função chamada generateThumbnail
que irá receber o título do vídeo e o caminho para salvar a thumbnail como parâmetros.
const generateThumbnail = async (title, outputPath) => {
const backgroundImagePath = './background.png';
const foregroundImagePath = './foreground.png';
await generateImageForPost(
backgroundImagePath,
foregroundImagePath,
title,
outputPath
);
};
E agora nós podemos chamar essa função e criar a thumbnail.
generateThumbnail('How to create thumbnails for your videos with Node.js', './thumbnail.png');
Conclusão
E é isso! Agora você pode criar thumbnails para seus vídeos automaticamente. Eu espero que você tenha gostado desse post, e não se esqueça de ver como fazer upload de Reels para o Instagram usando Node.js.
Até a próxima!
Tags:
Posts relacionados
Publicar um comentário
Comentários
Nenhum comentário.