/video-subtitle — Ferramenta de Legendas para Vídeo
Transcreva o áudio do vídeo para legendas SRT usando um modelo Whisper local e, em seguida, incorpore-as no vídeo.
Invocável pelo usuário
Quando o usuário digitar /video-subtitle, execute esta skill.
Pré-requisitos
Esta skill requer duas ferramentas. Verifique a disponibilidade antes de prosseguir:
1. mlx-whisper (Apple Silicon) ou openai-whisper
Detecte qual está disponível:
which mlx_whisper whisper 2>/dev/null
Se nenhum for encontrado, oriente o usuário a instalar um:
- Mac com Apple Silicon (recomendado):
pip install mlx-whisper - Qualquer plataforma:
pip install openai-whisper
2. ffmpeg com libass
Verifique o suporte a libass:
ffmpeg -filters 2>&1 | grep subtitles
Se não houver saída (libass ausente), o filtro subtitles não está disponível:
- macOS:
brew install ffmpeg-full(keg-only, use/opt/homebrew/opt/ffmpeg-full/bin/ffmpeg) - Linux:
sudo apt install ffmpeg(geralmente inclui libass) - Fallback: Se o usuário tiver ffmpeg comum sem libass, incorpore o SRT como faixa de legenda (soft-embed) em vez de queimar.
Seleção do modelo Whisper
Descubra modelos em cache:
ls ~/.cache/huggingface/hub/ 2>/dev/null | grep whisper
Prefira o maior modelo disponível. Se nenhum estiver em cache, use:
- mlx-whisper:
mlx-community/whisper-large-v3-mlx - openai-whisper:
large-v3
Modos
/video-subtitle caminho/para/video.mov→ Pipeline completo (transcrever + corrigir + queimar)/video-subtitle srt caminho/para/video.mov→ Apenas SRT (transcrever, sem queimar)/video-subtitle queimar caminho/para/video.mov caminho/para/legenda.srt→ Apenas queimar (usar SRT existente)/video-subtitle(sem argumentos) → Interativo, perguntar pelo caminho do vídeo
Pipeline Completo
Passo 1: Verificar vídeo
Se nenhum caminho for fornecido, pergunte com AskUserQuestion. Confirme que o arquivo existe e leia os metadados:
ffmpeg -i "<video_path>" 2>&1 | grep -E "Duration|Stream.*(Video|Audio)"
Informe duração, resolução e tamanho do arquivo ao usuário.
Passo 2: Extrair áudio
ffmpeg -i "<video_path>" -vn -acodec pcm_s16le -ar 16000 -ac 1 "<output_dir>/<basename>_audio.wav" -y
WAV mono de 16kHz é o formato de entrada ideal para Whisper.
Passo 3: Confirmar idioma
Pergunte ao usuário com AskUserQuestion. Opções comuns:
| Idioma | Flag |
|---|---|
| Chinês | --language zh |
| Inglês | --language en |
| Japonês | --language ja |
| Detecção automática | omitir --language |
Passo 4: Transcrever
mlx-whisper:
mlx_whisper --model "<model>" --language <lang> --output-format srt --output-dir "<output_dir>" "<audio_wav>"
openai-whisper:
whisper "<audio_wav>" --model large-v3 --language <lang> --output_format srt --output_dir "<output_dir>"
Informe ao usuário: "Transcrevendo, aguarde..."
Passo 5: Limpar SRT
Leia o SRT gerado e corrija:
- Remover alucinações: Excluir entradas com timestamps de duração zero (ex.:
00:00:57,640 --> 00:00:57,640) ou texto vazio - Corrigir nomes próprios: O Whisper frequentemente reconhece mal marcas e termos técnicos — use o contexto da conversa para corrigir
- Mesclar fragmentos: Combinar entradas com menos de 0,5s que estejam semanticamente conectadas
- Renumerar: Execute este snippet Python para renumerar todas as entradas:
python3 -c "
import re
with open('<srt_path>', 'r') as f:
content = f.read()
blocks = re.split(r'\n\n+', content.strip())
out = []
for i, block in enumerate(blocks, 1):
lines = block.strip().split('\n')
if len(lines) >= 2:
lines[0] = str(i)
out.append('\n'.join(lines))
with open('<srt_path>', 'w') as f:
f.write('\n\n'.join(out) + '\n')
"
Apresente o SRT corrigido ao usuário e pergunte se são necessárias edições adicionais antes de queimar.
Passo 6: Queimar legendas
Determine o binário ffmpeg correto (prefira ffmpeg-full se o ffmpeg comum não tiver libass):
FFMPEG="ffmpeg"
if ! ffmpeg -filters 2>&1 | grep -q subtitles; then
if [ -x /opt/homebrew/opt/ffmpeg-full/bin/ffmpeg ]; then
FFMPEG="/opt/homebrew/opt/ffmpeg-full/bin/ffmpeg"
fi
fi
Em seguida, queime:
$FFMPEG \
-i "<video_path>" \
-vf "subtitles=<srt_path>:force_style='FontSize=24,PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,Outline=2,MarginV=30'" \
-c:v libx264 -preset medium -crf 23 \
-c:a aac -b:a 128k \
-pix_fmt yuv420p \
"<output_dir>/<basename>_legendado.mp4" -y
Opções de force_style:
| Parâmetro | Padrão | Descrição |
|---|---|---|
| FontSize | 24 | Tamanho da fonte |
| PrimaryColour | &H00FFFFFF | Texto branco |
| OutlineColour | &H00000000 | Contorno preto |
| Outline | 2 | Espessura do contorno |
| MarginV | 30 | Margem inferior |
Importante: O caminho do arquivo SRT não deve conter caracteres especiais que confundam o analisador de filtros do ffmpeg. Use caminhos relativos ou symlink, se necessário.
Passo 7: Concluído
Informe o caminho do arquivo de saída e o tamanho. Sugira open <caminho> para visualizar. Lembre ao usuário que o arquivo intermediário _audio.wav pode ser excluído.
Solução de Problemas
| Problema | Causa | Correção |
|---|---|---|
No such filter: 'subtitles' | ffmpeg sem libass | Use ffmpeg-full ou instale libass |
No such filter: 'drawtext' | ffmpeg sem libfreetype | Use ffmpeg-full |
| Entradas SRT duplicadas/vazias | Alucinação do Whisper | Faça a limpeza no Passo 5 |
| Caracteres chineses aparecem como quadrados | Fonte CJK ausente | macOS: fallback automático para PingFang. Linux: apt install fonts-noto-cjk |
Error parsing filterchain | Caracteres especiais no caminho do SRT | Use caminho relativo, evite espaços |
Regras de Qualidade
- Transcrição fiel: Transcreva apenas o que foi realmente dito — não adicione nem reescreva o significado
- Correção de nomes próprios: Corrija reconhecimentos incorretos comuns do Whisper, mas confirme com o usuário
- Ritmo da legenda: Máximo de duas linhas por entrada, máximo de ~20 caracteres CJK por linha
- Limpeza: Lembre o usuário de excluir os arquivos intermediários (_audio.wav) após a conclusão