Adicionar Legendas a Vídeos
Dependências
/video-understand é um pré-requisito. Execute-o primeiro para que as legendas usem a transcrição validada em nível de palavra e a linha do tempo canônica.
Antes de começar, verifique se está instalado. Se não estiver, avise o usuário que este pré-requisito está faltando e pare antes de processar a mídia.
Requer ffmpeg/ffprobe no PATH, Python com Pillow e Node.js >= 22 (para os scripts .mjs e npx hyperframes, buscado sob demanda). hyperframes render/snapshot utiliza um Chrome headless — ele gerencia seu próprio chrome-headless-shell e, quando o cache está inutilizável, recorre a um Chrome do sistema (defina CHROME para substituir). Verifique estes antes de processar a mídia.
Escopo
Esta skill é responsável pelo agrupamento de legendas, seleção de estilo, revisão e pela faixa de legendas transparente. Ela não transcreve, corta, reajusta o tempo, classifica, reformata ou escolhe a política de áudio de entrega.
Execute as legendas antes dos cartões de conteúdo e movimento gráfico, sempre que algum deles estiver selecionado. O layout de legendas aprovado estabelece uma região de legenda reservada que ambas as operações posteriores devem manter livre. Esta ordem relativa também se aplica quando apenas um par está ativo.
Use video-understand primeiro. Se existir um corte, coloque legendas na linha do tempo do programa ativo; não trate segundos da transcrição fonte como segundos do programa.
Entradas do Protocolo
Obrigatórias:
work/project.jsonwork/understand/transcript.json, com timestamps fonte em nível de palavrawork/understand/media.jsonwork/timeline.json- o vídeo fonte nomeado por
work/project.json
A linha do tempo é o único mapeamento fonte-para-programa. Todos os intervalos são semi-abertos [start_s, end_s). scripts/build_captions.py usa o projectlib.map_transcript_to_timeline compartilhado; palavras em intervalos fonte descartados desaparecem, palavras retidas movem-se para o tempo do programa, e as pistas sempre quebram nos limites dos clipes.
Saídas Duráveis
work/captions/
|-- captions-plan.json
|-- caption-spatial-context.json (apenas para compostos B-roll elegíveis)
`-- caption-interaction.json
work/cache/captions/
|-- preview-project/
|-- preview-snapshots/
|-- overlay-project/
`-- overlay-frames/frame_000001.png ...
review/05-captions/
|-- captions.srt
|-- captions-style-review-<UUID>.html
|-- captions-style-review.html
|-- captions-review.html
|-- preview-early.png
|-- preview-middle.png
|-- preview-late.png
|-- preview-no-caption.png
|-- captions-evidence.json
`-- captions-summary.md
HTML gerado, arquivos de runtime copiados, quadros fonte extraídos e quadros de sobreposição são cache. O plano, contexto espacial opcional, SRT, recibo de decisão e evidência de revisão são duráveis.
Plano de Legendas
work/captions/captions-plan.json é o plano de legendas canônico, tem como alvo overlay e usa tempo do programa. Ele registra:
timeline_id,program_duration_se o caminho da transcrição fonte;- configurações de agrupamento de pistas;
- estilo aprovado, modo de decisão, justificativa, escolha da galeria e estilo resolvido completo;
- evidência de revisão baseada na fonte e ator de aprovação;
- pistas com campos de compatibilidade
start,end,text,linesewords; program_rangeesource_rangesem cada pista;- intervalos de programa/fonte e
clip_idem cada palavra mapeada; - uma receita de renderização local com FPS racional exato e ativos de runtime hash.
O gerador também aceita o antigo array de pistas de nível superior. Isso é apenas um adaptador de compatibilidade independente; não pode expressar proveniência da linha do tempo ou regenerar uma contribuição de protocolo aprovada.
Standard é o modo de apresentação padrão. Planos Standard não precisam de um campo presentation e não devem ser migrados apenas para adicionar um. Expressive é um modo de apresentação explícito, não uma predefinição: solicite-o com --presentation-mode expressive. A etapa de construção então adiciona IDs de pistas estáveis, valores padrão de semantic_role de palavra e um esboço de planejamento presentation; ela não adivinha variantes de layout.
Expressive suporta apenas bottom-standard e center-emphasis. Leia reference/caption-rules.md antes de preencher o esboço. O renderizador existente consome apenas presentation.layout_beats completados; ele não infere posições ou altera o layout dentro de um beat.
Pistas Expressive também podem definir uma hero_line contígua em nível de frase. Use canônico level: hero; ele renderiza a frase em dourado em sua própria linha em 1.5x. O legado level: strong continua aceito como um alias de entrada e renderiza de forma idêntica, mas novos planos criados pelo Agente não devem emiti-lo. Os papéis de palavra mantidos keyword, number e contrast cada um usa 1.22x; normal permanece 1.0x. Estes tratamentos são ortogonais a predefinições e não criam novos IDs de estilo. Leia reference/caption-rules.md para o esquema, política de estouro e regras de Karaokê.
Quando uma operação B-roll ativa e aprovada pela revisão contém compostos de inserção de orador aprovados ou verificados, as legendas podem derivar caption-spatial-context.json do plano upstream congelado, evidência, compostos normalizados e display_mode de subshot explícito. Isso não modifica ou reseleciona o layout B-roll. Alinha os limites das pistas antes do planejamento Expressive e resolve apenas os posicionamentos mantidos preset-bottom, frame-center, panel-center e panel-bottom (apenas limite). panel-bottom é permitido apenas para um unsplittable_word_boundary adjacente a um painel focado no centro inferior; ele centraliza a pista estável dentro da faixa reservada abaixo do retângulo estruturado do orador. Tal pista é verificada contra cada contexto visual que intersecta, não apenas o contexto contendo o ponto médio da palavra. Sem este contexto, todo o comportamento de posicionamento Standard e Expressive existente permanece inalterado.
Estilos
As predefinições mantidas são clean, minimal, social-bold, pill, boxed, stroked e shorts. IDs de combinação da galeria adicionam temas mantidos, por exemplo pill-yellow, stroked-blue e shorts-green. Karaokê é uma opção, não uma predefinição separada.
Escolha padrão delegada: clean, Karaokê desligado. Escolha uma predefinição mais expressiva apenas quando o destino ou a filmagem justificar. Armazene alterações específicas do trabalho em um JSON de substituições; não edite o gerador para feedback de estilo comum.
Expressive suporta tanto semantic-only (Karaokê desligado) quanto semantic-plus-karaoke (Karaokê ligado). A ênfase semântica persiste pela pista inteira em ambas as configurações. No modo de coexistência, a ênfase semântica e a palavra ativa do Karaokê usam style.wordHighlight.activeColor como sua cor de primeiro plano em cada modo de destaque; um destaque de fundo permanece um efeito adicional. A escala efetiva é max(escala semântica, escala ativa do Karaokê), nunca seu produto. Expressive nunca renderiza um sublinhado, incluindo para o papel semântico compatível contrast.
O contrato de revisão existente continua a usar semântico-apenas como a evidência Expressive primária e vincula semântico-mais-karaokê separadamente. O campo de payload de compatibilidade permanece nomeado experimental_comparison; não o renomeie sem uma migração de protocolo de aprovação.
Leia:
reference/caption-rules.mdantes de alterar limites de agrupamento;reference/caption-style-themes.mdpara vocabulário de estilo;reference/caption-feedback-mapping.mdpara mapeamento de substituições.
Modos de Decisão
Dois modos honestos compartilham a mesma máquina de estado vinculada a hash:
human: passe o resumo exato copiado da galeria paraselect, mostre toda a evidência de preview real e passe o resumo de aprovação ou revisão exato copiado paraconfirmouadjust. Comandos vinculados à página de revisão não aceitam frases de aprovação simples.agent: use apenas quando o usuário delegar explicitamente as decisões de legenda. Comece com uma nota de delegação não vazia, então useagent-selecteagent-confirmcom justificativas não vazias.
Comandos humanos falham no modo agente e comandos de agente falham no modo humano. Standard sem contexto espacial requer as quatro imagens mantidas baseadas na fonte; revisões Expressive e com reconhecimento de composto usam seus contratos de evidência dinâmicos. Uma alteração na fonte, plano, linha do tempo, estilo, substituição, metadados do projeto, página de revisão ou evidência invalida a aprovação; contexto espacial, revisão B-roll upstream ou alterações de composto vinculado fazem o mesmo. Reconstrua os artefatos afetados e revise-os novamente.
Fluxo de Trabalho Canônico
Execute da raiz do repositório. Defina os caminhos do projeto:
$RepoRoot = (Resolve-Path ".").Path
$SkillRoot = Join-Path $RepoRoot "skills\video-add-captions"
$ProjectRoot = (Resolve-Path "<project-root>").Path
$Work = Join-Path $ProjectRoot "work"
$SourceVideo = "<caminho absoluto de work/project.json>"
$Plan = Join-Path $Work "captions\captions-plan.json"
$SpatialContext = Join-Path $Work "captions\caption-spatial-context.json"
$SpatialArgs = @()
$SpatialReviewArgs = @()
$Receipt = Join-Path $Work "captions\caption-interaction.json"
$Review = Join-Path $ProjectRoot "review\05-captions"
$Cache = Join-Path $Work "cache\captions"
$PreviewProject = Join-Path $Cache "preview-project"
$ComparisonProject = Join-Path $Cache "preview-project-expressive-karaoke"
$OverlayProject = Join-Path $Cache "overlay-project"
$OverlayFrames = Join-Path $Cache "overlay-frames"
New-Item -ItemType Directory -Force -Path (Split-Path $Plan),$Review,$Cache | Out-Null
Antes de construir o plano de legendas, pergunte ao usuário para escolher o modo de apresentação, a menos que a solicitação atual já selecione um explicitamente. Renderize a pergunta no idioma atual da conversa do usuário, mantendo os identificadores Standard e Expressive sem tradução. Mantenha o prompt em inglês abaixo neste arquivo, apresente a escolha localizada na sessão atual, então Apresente + PARE:
Escolha o modo de apresentação das legendas:
1. Standard: Usa posicionamento convencional estável e é adequado para a maioria dos conteúdos.
2. Expressive: Alterna entre posicionamento inferior e central com base no significado e destaca palavras-chave e números.
Responda com Standard, Expressive ou "Usar o padrão (Standard)."
Não execute build_captions.py até que o usuário responda. Se o usuário delegar explicitamente a escolha em qualquer redação, selecione Standard. Informe que o Standard foi selecionado como o padrão que preserva a compatibilidade antes de construir o plano.
Construa pistas em tempo de programa e o SRT de revisão:
python "$SkillRoot\scripts\build_captions.py" `
"$Work\understand\transcript.json" `
$Plan `
"$Review\captions.srt" `
--timeline "$Work\timeline.json" `
--source-transcript "understand/transcript.json" `
--max-chars 42 --max-lines 2 --max-dur 6 --gap 0.6
Após o usuário selecionar Standard, o comando acima produz o plano Standard inalterado. Após o usuário selecionar Expressive, execute o mesmo comando com:
--presentation-mode expressive
Após a geração do rascunho das pistas, inspecione a operação B-roll ativa e seu plano vinculado (somente leitura). Habilite o posicionamento com reconhecimento de composto apenas quando a operação estiver ativa, seu status for approved ou verified, review.status for approved, as ligações de análise/entrada-do-agente/preview/liberacão de inserção do orador estiverem completas e pelo menos um take verificado ou normalizado tiver um layout composto mantido. O construtor espacial usa display_mode: enabled de subshot explícito para geometria do orador; pure_broll e evidência de orador ausente nunca implicam um retângulo de orador.
Quando elegível, alinhe as pistas de rascunho a cada limite visual B-roll antes de preencher qualquer layout_beats ou hero_line Expressive. O alinhamento divide apenas em lacunas de palavras e escreve atomicamente; um limite dentro de uma palavra mantém a palavra inteira e registra evidência de revisão obrigatória:
python "$SkillRoot\scripts\caption_spatial_context.py" align `
--project-root $ProjectRoot --plan $Plan --out-plan $Plan
Para um projeto elegível, prepare os argumentos opcionais usados por cada porta posterior:
$SpatialArgs = @("--spatial-context", $SpatialContext)
$SpatialReviewArgs = @("--spatial-context", $SpatialContext, "--project-root", $ProjectRoot)
Quando não existir composto elegível, pule todos os quatro comandos espaciais e deixe $SpatialArgs e $SpatialReviewArgs vazios. Não crie ou anexe um contexto vazio.
Antes de iniciar a seleção de estilo ou gerar um preview, o Agente deve planejar todo o programa Expressive em uma passada:
- Leia a transcrição, artefatos de entendimento disponíveis, linha do tempo canônica, pistas de legendas geradas e qualquer evidência de quadro fonte real necessária para justificar alterações de layout.
- Preencha todos os
presentation.layout_beats, anote valores excepcionais desemantic_rolede palavra, adicione no máximo umahero_linecontígua comlevel: herocanônico a uma pista quando justificado, escreva uma justificativa por beat/linha heroica e escreva apresentation.planner.rationalegeral. - Defina
presentation.planning_statuscomocompleteapenas depois que cada pista for coberta exatamente uma vez. - Valide o plano completo antes da geração do preview:
python "$SkillRoot\scripts\build_captions.py" --validate-plan $Plan
Para um composto elegível, construa, valide e anexe o contexto apenas após os IDs finais das pistas e os candidatos Expressive estarem completos. Isso preserva o layout upstream e vincula sua revisão e hashes atuais ao plano de legendas:
python "$SkillRoot\scripts\caption_spatial_context.py" build `
--project-root $ProjectRoot --plan $Plan --out $SpatialContext
python "$SkillRoot\scripts\caption_spatial_context.py" validate `
--project-root $ProjectRoot --plan $Plan --context $SpatialContext
python "$SkillRoot\scripts\caption_spatial_context.py" attach `
--project-root $ProjectRoot --plan $Plan --context $SpatialContext
Não peça ao usuário para escolher uma posição pista por pista. O usuário revisa a evidência HTML existente e corrige apenas um pequeno número de beats anômalos. Iniciar a interação após o planejamento mantém a ligação hash do plano de legendas existente autoritativa.
Inicie um modo de decisão. Para modo humano, publique a galeria mantida offline no diretório de revisão do projeto sem pedir ao usuário para localizar um arquivo:
$StartOutput = node "$SkillRoot\scripts\caption_interaction.mjs" start `
--state $Receipt --source $Sou
...