Pitch: Weydub — por que detectar texto não basta para remover legendas
Somos a equipe do Weydub, uma ferramenta de localização de vídeo. Este texto apresenta uma decisão técnica do fluxo documentado publicamente: separar a detecção de texto da decisão de remover pixels. A redação e a tradução tiveram assistência de IA. O código abaixo é um exemplo didático executado localmente; não é o código interno do produto nem um teste da qualidade de restauração.
Três operações que não são equivalentes
Uma legenda pode existir como faixa separada no contêiner do vídeo ou estar gravada nos pixels. Excluir a faixa não remove os caracteres que já fazem parte da imagem. Nesse segundo caso, é necessário identificar a área e reconstruir seu conteúdo visual.
OCR responde a “que texto aparece nesta imagem?”. Ele não responde sozinho a “este texto deve desaparecer?”. Em uma aula gravada, por exemplo, a legenda da fala pode ocupar a parte inferior, enquanto uma fórmula no quadro deve permanecer. Uma seleção baseada apenas na existência de texto pode destruir informação útil.
A geração de legendas também é outra tarefa. OCR extrai texto visível; ASR reconhece a fala. Na documentação do Weydub são modos separados, não uma fusão automática. A tradução e a dublagem vêm com decisões adicionais: identidade dos personagens, continuidade da voz e duração das falas.
Da caixa detectada para uma decisão com limites
Uma forma de reduzir ambiguidade na integração é representar explicitamente a região e o intervalo de tempo. Isso não garante que a escolha esteja correta; torna a escolha inspecionável antes de executar uma operação sobre o vídeo.
Neste exemplo usamos um vídeo hipotético de 640 × 360 pixels e 12 segundos. A caixa vai de (64, 270) a (576, 342), mas a intervenção vale apenas entre os segundos 3 e 8. As coordenadas normalizadas são [[0.1, 0.75], [0.9, 0.75], [0.9, 0.95], [0.1, 0.95]].
Salve o exemplo como mask-example.mjs e execute com Node.js:
import assert from 'node:assert/strict';
function makeMask({ width, height, box, start, end, duration }) {
const values = [width, height, ...box, start, end, duration];
if (!values.every(Number.isFinite)) throw new Error('Non-finite value');
const [x0, y0, x1, y1] = box;
if (width <= 0 || height <= 0 || x0 < 0 || y0 < 0 ||
x1 > width || y1 > height || x0 >= x1 || y0 >= y1 ||
start < 0 || end <= start || end > duration) {
throw new Error('Invalid region or time interval');
}
return {
type: 'remove_only_ocr', start, end,
region: [[x0 / width, y0 / height], [x1 / width, y0 / height],
[x1 / width, y1 / height], [x0 / width, y1 / height]],
};
}
const input = { width: 640, height: 360, box: [64, 270, 576, 342], start: 3, end: 8, duration: 12 };
const mask = makeMask(input);
assert.deepEqual(mask.region, [[0.1, 0.75], [0.9, 0.75], [0.9, 0.95], [0.1, 0.95]]);
const payload = { needChineseOcclude: 2, videoInpaintMasks: JSON.stringify([mask]) };
assert.deepEqual(JSON.parse(payload.videoInpaintMasks), [mask]);
assert.throws(() => makeMask({ ...input, width: 0 }));
assert.throws(() => makeMask({ ...input, box: [576, 270, 64, 342] }));
assert.throws(() => makeMask({ ...input, end: 13 }));
assert.throws(() => makeMask({ ...input, start: NaN }));
console.log('PASS: coordinates; JSON round-trip; zero width; reversed box; time overflow; non-finite input');
console.log(JSON.stringify(payload, null, 2));
A execução local passou pelas seis verificações acima. O campo videoInpaintMasks é serializado como string JSON conforme o contrato documentado, não enviado como um array diretamente. Os nomes dos campos foram mantidos como aparecem na API; o nome needChineseOcclude não deve ser interpretado como uma avaliação de qualidade por idioma.
O que esse teste não prova
Ele valida uma transformação de dados, não a detecção OCR nem o preenchimento da imagem. O exemplo assume uma caixa retangular de quatro números. Para entrada externa, ainda é necessário validar o formato do array, o esquema completo da requisição, a origem das coordenadas e a orientação do vídeo. Uma caixa obtida de um preview recortado não pode ser normalizada usando as dimensões do original sem desfazer o recorte.
O tempo também precisa usar a mesma referência do vídeo processado. Se um trecho foi extraído de um arquivo maior, um intervalo absoluto do original pode apontar para a cena errada no trecho. Aqui usamos segundos relativos ao vídeo hipotético de 12 segundos.
A revisão continua sendo parte do fluxo
Uma imagem isolada pode parecer boa e ainda apresentar cintilação durante a reprodução. Por isso, convém revisar movimento, cortes, rostos, mãos e contornos de produtos perto da região escolhida. Texto de cenário, avisos e fórmulas merecem uma decisão explícita de preservação. O resultado de uma ferramenta de preenchimento é uma reconstrução, não uma recuperação garantida dos pixels originais que estavam ocultos.
Para produzir uma nova versão em outro idioma, preserve separadamente o texto extraído e seus tempos. Revise a segmentação das legendas antes de traduzir. Na dublagem, confira a continuidade do personagem e a duração da fala em sequência, não apenas frase por frase.
Fontes e limites da apresentação
- Explicação pública sobre OCR e remoção de legendas
- Contrato da API de remoção
- Modos de geração por OCR e ASR
- Tradução e reconstrução audiovisual
Essas fontes são da própria equipe, não avaliações independentes. Elas explicam controles e problemas do fluxo; não divulgam toda a orquestração interna dos modelos. O exemplo não faz chamada paga nem envia vídeo. O Weydub em português é um serviço comercial com créditos; não estamos anunciando um plano gratuito nem apresentando números de precisão sem um experimento correspondente.
A contribuição que queremos deixar é esta: uma região reconhecida, uma política de edição e uma legenda temporizada são objetos diferentes. Mantê-los separados facilita testar a integração e revisar o que realmente será alterado.