Communitygithub.com

countdown-video

Esta skill deve ser usada quando o usuário pedir para criar um vídeo de contagem regressiva que termina exatamente no momento certo, sem desvios de tempo.

O que é countdown-video?

Esta skill gera vídeos de contagem regressiva com precisão de quadro, garantindo que o cronômetro termine exatamente em zero no quadro final, sem desvios de tempo. É ideal para telas de 'começando em breve' em lives, contagens regressivas de lançamentos e vendas relâmpago, e fundos animados em loop. A regra central é derivar o tempo restante a partir de um relógio autoritário (como `useCurrentFrame()` no Remotion ou `performance.now()` na web) em vez de usar `setInterval`, que acumula erros. Suporta renderização no Remotion para MP4 e exibição ao vivo na web com `requestAnimationFrame`, oferece formatação flexível (mm:ss, hh:mm:ss, dd:hh:mm:ss), animações de dígitos estilo odômetro ou flip-card, e fundos contínuos sem emendas. O fluxo de trabalho inclui verificação de quadros estáticos antes da codificação final para garantir precisão.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/iart-ai/tiktok-video-skills/tree/main/skills/countdown-video

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Vídeo de Contagem Regressiva

Crie uma contagem regressiva que termina exatamente no momento certo. Toda a técnica se baseia em uma ideia: derivar o tempo restante a partir do quadro (ou de um timestamp monotônico), formatar e animar esse número — nunca faça contagem com setInterval. Abrange telas de "começando em breve" para lives, contagens regressivas de lançamentos/vendas e fundos em loop.

Quando usar

  • Telas de "começando em breve" / "volto já" para lives com cronômetro de 5 a 10 minutos.
  • Contagens regressivas de lançamentos e vendas relâmpago (dd:hh:mm:ss até uma data alvo; mm:ss para urgência).
  • Qualquer contador animado onde o número deve chegar a zero no quadro exato.

A única regra: derive o número do relógio, nunca de um tick

Uma contagem com setInterval(fn, 1000) sofre desvio — o callback é disparado no mínimo 1000 ms depois, nunca exato, e acumula atrasos quando a aba é limitada ou um quadro de renderização está lento. Relatos de ~1 segundo perdido por minuto são comuns. A solução é a mesma para vídeo renderizado e web ao vivo: compute o tempo restante como uma função pura de um relógio autoritário, de modo que um quadro atrasado se autocorrija no próximo quadro, em vez de acumular erro.

ContextoRelógio autoritárioTempo restante
Renderização RemotionuseCurrentFrame()total − frame/fps
Web (página ao vivo)performance.now() ou Date.now()targetMs − now
Até uma data fixaDate.now()targetTimestamp − Date.now()

Nunca armazene o tempo restante no estado e o decremente. Recalcule-o a cada quadro.

Contagem regressiva precisa por quadro (Remotion → MP4)

useCurrentFrame() é determinística: o quadro N é sempre renderizado exatamente em N/fps segundos. Subtraia do total e o cronômetro fica livre de desvios por construção.

import { useCurrentFrame, useVideoConfig } from "remotion";

export const Countdown: React.FC<{ durationInSeconds: number }> = ({
  durationInSeconds,
}) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();

  // segundos restantes, limitados a 0 — ceil para que "1" apareça por seu segundo inteiro
  const elapsed = frame / fps;
  const remaining = Math.max(0, Math.ceil(durationInSeconds - elapsed));

  return <div style={{ fontVariantNumeric: "tabular-nums" }}>{formatMMSS(remaining)}</div>;
};

durationInSeconds é uma prop, não uma constante — a mesma composição renderiza um cronômetro de 5 minutos para live ou de 30 segundos para venda apenas alterando uma entrada. Defina durationInFrames da composição como durationInSeconds * fps para que o vídeo tenha exatamente a duração da contagem.

Temporizador web (página ao vivo, requestAnimationFrame)

Para uma página ao vivo, controle um loop rAF com performance.now() e só repinte quando o segundo exibido mudar (sem trabalho 60×/s para um número de 1 Hz):

const start = performance.now();
let lastShown = -1;
function tick(now) {
  const remaining = Math.max(0, Math.ceil(duration - (now - start) / 1000));
  if (remaining !== lastShown) { render(remaining); lastShown = remaining; }
  if (remaining > 0) requestAnimationFrame(tick);
}
requestAnimationFrame(tick);

Contar até uma data fixa segue a mesma ideia com Date.now(): Math.max(0, target - Date.now()). Veja references/countdown-cookbook.md para a versão completa com data alvo e tratamento de fuso horário.

Formatação de tempo

Converta um inteiro de segundos restantes em campos usando divisão + módulo, depois preencha com zeros. Escolha o formato adequado à duração — nunca mostre 00d 00h 05m quando minutos é tudo que importa.

const pad = (n) => String(n).padStart(2, "0");
const formatMMSS = (s) => `${pad(Math.floor(s / 60))}:${pad(s % 60)}`;
const formatDHMS = (s) => {
  const d = Math.floor(s / 86400), h = Math.floor((s % 86400) / 3600);
  const m = Math.floor((s % 3600) / 60), sec = s % 60;
  return `${pad(d)}:${pad(h)}:${pad(m)}:${pad(sec)}`;
};
FormatoUsoOcultar campos quando
mm:ss"começando em breve", temporizadores curtos (<1h)—
hh:mm:ssvenda relâmpago, evento no mesmo diaocultar dd enquanto for 0
dd:hh:mm:sslançamento / contagem de vários diasocultar unidades líderes zero para leitura mais limpa

Sempre defina font-variant-numeric: tabular-nums (ou uma fonte de dígitos monoespaçada) para que os dígitos mantenham largura igual e o layout não trema quando os números mudarem.

Transições de rolagem / virada de dígitos

Uma simples troca de número parece barata; o visual de "odômetro" rolante valoriza a contagem. Renderize cada dígito como uma faixa vertical de 0 a 9 e desloque-a por -dígito × alturaDoDígito. Anime a posição, não o conteúdo do texto, para que a mudança seja um deslize, não um pulo.

.reel { height: 1em; overflow: hidden; }
.reel .col { transition: transform .45s cubic-bezier(.22,1,.36,1); }
/* col mantém 0..9 empilhados; desloca por -valor em */

No Remotion, controle o deslocamento da faixa pelo quadro em vez de uma transição CSS (para que seja determinístico). O estilo de carta virada (metade superior dobra sobre a inferior) e o rolo por dígito são detalhados, com componentes executáveis, em references/digit-flip.md.

Fundo em loop

Telas de live duram minutos, então o fundo deve fazer loop sem emendas. Construa o movimento em um ciclo que se divida uniformemente na linha do tempo (por exemplo, um gradiente ou deriva de partículas cujo período seja loopFrames) e leia como frame % loopFrames para que não haja emenda visível no final. Mantenha baixo contraste e lento — o número é o assunto; o fundo é ambiente. Receitas em references/countdown-cookbook.md.

Lista de verificação de saída

  • Tempo restante recalculado a partir de useCurrentFrame() / performance.now() a cada quadro — sem decremento com setInterval.
  • O cronômetro chega a 00:00 no quadro pretendido; durationInFrames === durationInSeconds × fps.
  • A duração é uma prop de entrada, não uma constante codificada.
  • Dígitos usam tabular-nums; o layout não se desloca conforme os números mudam.
  • O formato corresponde ao intervalo (mm:ss vs dd:hh:mm:ss); unidades líderes zero são omitidas quando atrapalham.
  • O período do loop do fundo divide a linha do tempo uniformemente; sem emenda no final.

Entregar e verificar (imagens estáticas renderizadas → MP4)

Ajudante empacotado (scripts/): monte suas imagens com scripts/contact-sheet.sh sheet.png f-hook.png f-mid.png f-end.png, depois verifique a codificação com scripts/probe-mp4.sh out.mp4 [LxA] [fps]. Veja scripts/README.md.

A contagem regressiva é fornecida como uma composição Remotion (<Composition> + zod schema + defaultProps, durationInSeconds como prop) — o cronômetro é uma função pura de useCurrentFrame(), nunca setInterval / Date.now() / Math.random(). Defina durationInFrames = durationInSeconds * fps. Entregável = out/*.mp4 + o projeto. O padrão é vertical 9:16 (1080×1920).

Verifique em loop — renderize imagens → inspecione → codifique. Todo o objetivo é a precisão de quadro, então verifique o valor do dígito em quadros exatos antes de codificar.

# Imagens no início / meio / fim — COM AS PROPS FORNECIDAS (a duração real que você renderizará)
npx remotion still Countdown out/f-start.png --frame=0   --props='{"durationInSeconds":300}'
npx remotion still Countdown out/f-mid.png   --frame=N   --props='{"durationInSeconds":300}'
npx remotion still Countdown out/f-end.png   --frame=L   --props='{"durationInSeconds":300}'  # L = durationInFrames-1

# Inspecione cada PNG — os dígitos devem corresponder EXATAMENTE à matemática quadro/fps:
#  - no quadro N, exibido = ceil(durationInSeconds - N/fps)  (ex.: 300s @ 30fps, quadro 4500 → 150s → "02:30")
#  - o último quadro mostra 00:00 (ou o estado final); sem desvio, sem erro de um segundo
#  - tabular-nums: layout não treme entre quadros
#  - área segura 9:16: o cronômetro + bloco de marca ficam livres dos ~12% superiores e dos ~20-35% inferiores da UI e da barra de ação direita

npx remotion render Countdown out/countdown.mp4 --props='{"durationInSeconds":300}'   # codifique assim que os dígitos forem verificados
npx remotion render Countdown out/demo.gif --codec=gif                                 # clipe de prova para README

Use npx remotion compositions para confirmar durationInFrames/fps, depois calcule o quadro de qualquer segundo que queira verificar.

Antes de finalizar:

  1. As imagens estáticas renderizam corretamente no quadro 0, meio e fim — sem erros.
  2. O valor do dígito no quadro N é exatamente ceil(durationInSeconds - N/fps); o último quadro chega a 00:00 no quadro pretendido (sem desvio / erro de um).
  3. Cronômetro + marca permanecem dentro da área segura 9:16 em todos os quadros verificados.
  4. Apenas orientado por quadro — sem setInterval / Date.now() / temporizadores; tabular-nums para manter o layout.
  5. O durationInSeconds fornecido (não apenas defaultProps) renderiza corretamente; MP4 codificado, GIF opcional.

Arquivos de referência

  • references/countdown-cookbook.md — componente <Countdown> Remotion completo e executável (duração configurável, mm:ss / dd:hh:mm:ss, estado final), componente web de contagem até data fixa com tratamento de fuso horário, layout de tela de live "começando em breve" (bloco de marca + redes sociais + fundo gradiente em loop) e padrão de fundo contínuo em loop.
  • references/digit-flip.md — dois componentes determinísticos de animação de dígitos: o rolo de odômetro (faixa vertical de 0 a 9 controlada por quadro) e o efeito de carta virada (dobra da metade superior), além de quando cada um é adequado para lançamento, venda ou live.

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

Habilidades Relacionadas