Artigos aprofundados sobre a tecnologia que molda o que vem a seguir.

FFmpeg Descomplicado: o Modelo Mental que Falta

Pare de copiar comandos do FFmpeg às cegas. Entenda containers, codecs, streams e filtros com receitas práticas que você realmente vai usar.

Máquina separando fluxos de vídeo, áudio e texto por funis em um único contêiner brilhante.

Todos já passamos por isso. Você precisa converter um vídeo, então pesquisa no Google e encontra uma resposta do Stack Overflow com um comando que parece ter sido digitado com a cabeça: ffmpeg -i input.mov -c:v libx264 -preset slow -crf 22 -c:a aac -b:a 128k -movflags +faststart output.mp4. Você executa. Funciona. Você não tem a menor ideia do porquê, e na próxima vez que precisar de algo um pouco diferente, está de volta ao Stack Overflow. Fiz isso por anos até finalmente sentar e entender o que o FFmpeg realmente espera de mim.

O fato é que o FFmpeg não é tão complicado assim. Ele tem um modelo mental consistente que, uma vez compreendido, torna quase qualquer comando legível. O problema é que ninguém explica o modelo — só jogam comandos na sua cara. Então vamos resolver isso.

Containers vs Codecs: O Primeiro Conceito a Entender

A maior fonte de confusão com arquivos de vídeo é a diferença entre containers e codecs. Um container é o formato do arquivo — .mp4, .mkv, .webm, .mov. É uma caixa que carrega coisas. Um codec é a forma como os dados de vídeo e áudio dentro dessa caixa são comprimidos — H.264, H.265, VP9, AV1, AAC, Opus.

Um arquivo MP4 pode conter vídeo H.264 com áudio AAC, ou vídeo H.265 com áudio Opus, ou dezenas de outras combinações. Um MKV pode conter praticamente qualquer coisa. Quando alguém diz “converta para MP4”, geralmente quer dizer “coloque vídeo H.264 e áudio AAC num container MP4” — mas são três decisões separadas.

# See what's actually inside a file
$ ffprobe -hide_banner video.mkv
Input #0, matroska:
Stream #0:0: Video: hevc (Main), 1920x1080, 23.98 fps
Stream #0:1: Audio: opus, 48000 Hz, stereo
Stream #0:2: Subtitle: subrip
# This file is:
# Container: MKV (Matroska)
# Video codec: HEVC (H.265)
# Audio codec: Opus
# Plus a subtitle stream

Use ffprobe antes de fazer qualquer coisa. Ele mostra exatamente com o que você está lidando. Na metade das vezes, a “conversão” de que você precisa é apenas um remux — mover os mesmos streams para outro container sem recodificar. Isso é quase instantâneo.

A Estrutura de Comandos do FFmpeg

Todo comando do FFmpeg segue o mesmo padrão, e depois que você percebe, não consegue mais deixar de ver:

ffmpeg [global options] [input options] -i input [output options] output
# The KEY insight: options apply to the NEXT file.
# Options before -i apply to the input.
# Options after -i (before the output filename) apply to the output.
# This matters! These two commands are different:
ffmpeg -ss 00:01:00 -i video.mp4 output.mp4   # Seeks BEFORE decoding (fast)
ffmpeg -i video.mp4 -ss 00:01:00 output.mp4   # Seeks AFTER decoding (slow, precise)

A posição importa no FFmpeg. É isso que pega todo mundo. O significado de uma opção pode mudar dependendo de ela aparecer antes ou depois de -i. O exemplo do -ss acima é o caso mais comum: colocá-lo antes de -i faz o FFmpeg buscar diretamente no arquivo de entrada (rápido, mas potencialmente impreciso), enquanto colocá-lo depois faz o FFmpeg decodificar tudo até aquele ponto e só então começar a gerar a saída (lento, mas preciso quadro a quadro).

Seleção de Streams: Dizendo ao FFmpeg o Que Você Quer

Arquivos de vídeo costumam conter vários streams — vídeo, áudio, legendas, às vezes várias faixas de áudio em idiomas diferentes. O FFmpeg usa uma sintaxe de especificadores de stream para permitir que você escolha streams específicos:

  • -c:v — codec para streams de vídeo (v = video)
  • -c:a — codec para streams de áudio (a = audio)
  • -c:s — codec para streams de legenda (s = subtitle)
  • -c copy — copia TODOS os streams sem recodificar
  • -c:v copy -c:a aac — copia o vídeo como está e recodifica o áudio para AAC
  • -map 0:a:1 — seleciona o segundo stream de áudio da primeira entrada

A flag -c copy é a mais importante de conhecer. Ela diz ao FFmpeg para copiar os dados do stream diretamente, sem recodificar. Isso é basicamente instantâneo e sem perda — você está apenas movendo dados de um container para outro. Sempre que não precisar mudar o codec, use -c copy.

# Remux MKV to MP4 without re-encoding (instant)
ffmpeg -i input.mkv -c copy output.mp4
# Copy video but re-encode audio (fast — only audio is processed)
ffmpeg -i input.mkv -c:v copy -c:a aac -b:a 192k output.mp4
# Extract just the audio stream
ffmpeg -i video.mp4 -vn -c:a copy audio.aac
# -vn means "no video" — drop the video stream entirely

Receitas Práticas Que Você Vai Realmente Usar

Aqui estão os comandos que eu uso o tempo todo. Cada um é explicado para que você possa adaptá-lo às suas necessidades.

Comprimir um Vídeo para a Web

ffmpeg -i raw_video.mov \
-c:v libx264 \
-preset slow \
-crf 23 \
-c:a aac -b:a 128k \
-movflags +faststart \
web_video.mp4
# -c:v libx264     → encode video with H.264
# -preset slow     → slower encoding = smaller file (options: ultrafast to veryslow)
# -crf 23          → quality level (18=near lossless, 23=default, 28=low quality)
# -c:a aac         → encode audio as AAC
# -b:a 128k        → audio bitrate 128 kbps
# -movflags +faststart → move metadata to start of file for streaming

O valor de CRF (Constant Rate Factor) é o principal botão de qualidade. Números menores significam mais qualidade e arquivos maiores. Para a maioria dos vídeos para web, CRF entre 20 e 25 é o ponto ideal. Eu normalmente uso 22 para qualquer coisa que precise ficar boa e 26 para vídeos de fundo ou complementares, onde a qualidade importa menos.

Cortar um Vídeo Sem Recodificar

# Extract from 1:30 to 3:45 — no re-encoding, nearly instant
ffmpeg -ss 00:01:30 -to 00:03:45 -i input.mp4 -c copy trimmed.mp4
# If you need frame-accurate cuts (slower):
ffmpeg -i input.mp4 -ss 00:01:30 -to 00:03:45 \
-c:v libx264 -crf 18 -c:a copy trimmed.mp4

Gerar Miniaturas

# Single thumbnail at the 10-second mark
ffmpeg -ss 00:00:10 -i video.mp4 -frames:v 1 thumb.jpg
# One thumbnail every 30 seconds
ffmpeg -i video.mp4 -vf "fps=1/30" thumbs/thumb_%04d.jpg
# Resize to 320px wide, maintain aspect ratio
ffmpeg -ss 00:00:10 -i video.mp4 -frames:v 1 \
-vf "scale=320:-1" thumb_small.jpg

Criar um GIF a Partir de um Trecho de Vídeo

# Good quality GIF with palette generation (two-pass)
ffmpeg -ss 00:00:05 -t 3 -i video.mp4 \
-vf "fps=15,scale=480:-1:flags=lanczos,split[s0][s1]; \
[s0]palettegen[p];[s1][p]paletteuse" \
output.gif
# -t 3              → duration: 3 seconds
# fps=15            → 15 frames per second (keep GIFs small)
# scale=480:-1      → resize to 480px wide
# palettegen/use    → generate optimal color palette (much better quality)

Entendendo os Filtros: O Recurso Poderoso

Os filtros são o que transforma o FFmpeg de “ferramenta útil” em “absurdamente poderoso”. As flags -vf (filtro de vídeo) e -af (filtro de áudio) permitem encadear operações de processamento. Filtros são separados por vírgulas para processamento sequencial, ou por ponto e vírgula para grafos de filtros complexos.

# Chain multiple filters: resize, then add padding for exact dimensions
ffmpeg -i input.mp4 -vf "scale=1280:720:force_original_aspect_ratio=decrease,\
pad=1280:720:(ow-iw)/2:(oh-ih)/2:black" output.mp4
# Normalize audio volume
ffmpeg -i input.mp4 -af "loudnorm" -c:v copy output.mp4
# Speed up a video 2x (with audio pitch correction)
ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" -af "atempo=2.0" fast.mp4
# Add text overlay
ffmpeg -i input.mp4 \
-vf "drawtext=text='DRAFT':fontsize=72:fontcolor=red:x=10:y=10" \
watermarked.mp4

O sistema de filtros é profundo o bastante para render um artigo próprio, mas a ideia-chave é esta: filtros processam quadros decodificados. Isso significa que você não pode usar -c copy com filtros — o vídeo precisa ser decodificado, filtrado e recodificado. Se o seu comando usa -vf, reserve tempo para uma recodificação completa.

Aceleração por Hardware: Use Sua GPU

Se você codifica vídeo com frequência, a aceleração por hardware pode deixar as coisas de 5 a 10 vezes mais rápidas. GPUs modernas têm hardware dedicado de codificação que o FFmpeg consegue usar.

# NVIDIA GPU (NVENC)
ffmpeg -i input.mp4 -c:v h264_nvenc -preset p4 -crf 23 output.mp4
# Apple Silicon (VideoToolbox)
ffmpeg -i input.mp4 -c:v h264_videotoolbox -b:v 5M output.mp4
# Intel Quick Sync (QSV)
ffmpeg -i input.mp4 -c:v h264_qsv -preset medium output.mp4
# Check what's available on your system:
ffmpeg -encoders 2>/dev/null | grep -E '(nvenc|videotoolbox|qsv|vaapi)'

Um aviso: encoders por hardware são mais rápidos, mas normalmente geram arquivos um pouco maiores com a mesma qualidade visual em comparação com a codificação por software (libx264). Para transcodificações pontuais em que a qualidade importa, a codificação por software continua melhor. Para processamento em lote ou streaming em tempo real, a aceleração por hardware é a vencedora clara. Eu uso libx264 para os encodes finais de produção e NVENC para todo o resto.

Erros Comuns e Como Evitá-los

  • Recodificar quando não precisa. Se você está apenas cortando, extraindo áudio ou trocando de container, use -c copy. Não há motivo para gastar 20 minutos recodificando um vídeo do qual você só vai tirar 30 segundos.
  • Usar um valor de CRF baixo demais. CRF 18 produz arquivos enormes com melhorias de qualidade que a maioria das pessoas não consegue ver. Comece em 23 e só desça se notar artefatos. Para a maior parte do conteúdo web, 23 a 25 é mais que suficiente.
  • Esquecer o -movflags +faststart. Sem isso, os metadados do MP4 ficam no final do arquivo, o que significa que os navegadores não conseguem começar a reproduzir até o arquivo inteiro ser baixado. Sempre adicione para vídeo web.
  • Não verificar a entrada primeiro. Execute ffprobe antes de escrever o comando. Conhecer os codecs de entrada, a resolução e a estrutura de streams torna tudo mais fácil.
  • Mandar para lugar nenhum. Se o FFmpeg parecer travado, ele pode estar esperando você responder uma pergunta (como se deve sobrescrever um arquivo existente). Adicione -y para sobrescrever automaticamente, ou -n para nunca sobrescrever.

A Cola de Referência

Isto é o que eu mantenho num arquivo de texto na minha área de trabalho. Estes cobrem cerca de 90% do que preciso no dia a dia:

# Probe a file
ffprobe -hide_banner input.mp4
# Remux (change container, no re-encode)
ffmpeg -i input.mkv -c copy output.mp4
# Compress for web
ffmpeg -i input.mov -c:v libx264 -crf 23 -preset medium \
-c:a aac -b:a 128k -movflags +faststart output.mp4
# Extract audio only
ffmpeg -i video.mp4 -vn -c:a copy audio.m4a
# Trim without re-encoding
ffmpeg -ss 00:01:00 -to 00:02:30 -i input.mp4 -c copy clip.mp4
# Resize to 720p
ffmpeg -i input.mp4 -vf "scale=-1:720" -c:a copy output.mp4
# Convert to GIF
ffmpeg -ss 5 -t 3 -i input.mp4 \
-vf "fps=12,scale=400:-1" output.gif
# Concatenate files (same codec)
echo "file 'part1.mp4'" > list.txt
echo "file 'part2.mp4'" >> list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy combined.mp4

O FFmpeg não é uma ferramenta que você domina em um dia. Mas, quando você entende o modelo mental — containers carregam streams, streams têm codecs, opções se aplicam ao próximo arquivo, filtros exigem recodificação — a documentação começa a fazer sentido. Você para de copiar comandos às cegas e começa a compô-los com intenção. E, sinceramente, essa passagem de “isso é mágica” para “ah, é isso que ele está fazendo” é um dos momentos mais satisfatórios que um desenvolvedor pode ter.