domingo, 15 de abril de 2012

Normalizando o áudio do vídeo sem recomprimir a imagem

Nem todo mundo tem muito cuidado técnico ao postar vídeos na internet, nem mesmo as grande emissoras. Faz algum tempo baixei alguns vídeos de um site com dois problemas: Áudio muito baixo e em apenas um lado dos canais estéreo. Mas como corrigir isso sem fazer com que a imagem seja recomprimida quadriculando ainda mais? Esse problema pode ser solucionado através do ffmpeg e um outro programa adicional, o SoX (disponível em http://sox.sourceforge.net/ ou através do Homebrew para usuários do Mac OS X)

O procedimento explicado:

Uso o ffmpeg para extrair do vídeo (um MP4) apenas o áudio em formato WAV, já mixando ele em mono. Depois com o SoX calculo e aplico a normalização no nível de volume e em seguida uso o ffmpeg pra unir a faixa de vídeo original com o arquivo gerado pelo SoX, ao mesmo tempo comprindo para AAC, que o formato MP4 exige.

O código:

Em formato de script do Bash o procedimento fica da seguinte forma:

#!/bin/sh
x=$1
file=${x%.*}
ffmpeg -i "$x" -vn -ac 1 "$file.wav"
sox "$file.wav" "$file-2.wav" vol `sox "$file.wav" -n stat -v 2>&1`
ffmpeg -i "$x" -i "$file-2.wav" -map 0:0 -map 1:0 -vcodec copy -acodec libfaac -ab 128k "$file-2.mp4"
rm "$file-2.wav" "$file.wav"

Feito isso basta apenas chamar pelo Terminal o seu script .sh seguido pelo caminho do arquivo a ser corrigido (não esqueça de atribuir permissões de execução a ele, ou seja, "chmod +x script.sh"). O arquivo corrigido será salvo na mesma pasta do original com o mesmo nome do original acrescentando um "2" no final.

Trocando em miúdos o código:

Agora vamos entender o para que serve cada parte do código:


ffmpeg -i "$x" -vn -ac 1 "$file.wav"
 -i - Indica o arquivo de entrada

-vn - Exclui a faixa de vídeo

-ac 1 - Indica que o arquivo de saída será mono (1 = mono / 2 = estéreo)

sox "$file.wav" "$file-2.wav" vol `sox "$file.wav" -n stat -v 2>&1`
Neste caso usamos um recurso do Bash de executar um comando dentro de outro. Entre os apóstrofes é executado o SoX com o comando -n stat que realiza uma análise do arquivo, inclusive o nível de volume a se ajustado. 2>&1 seleciona e retorna este resultado. Assim, o comando vol ajusta o arquivo de entrada $file.wav e salva como $file-2.wav

ffmpeg -i "$x" -i "$file-2.wav" -map 0:0 -map 1:0 -vcodec copy -acodec libfaac -ab 128k "$file-2.mp4"
Finalmente combinaremos todos os elementos para o arquivo final. Dois comandos -i são realizados, um lendo o vídeo original e outro para o áudio corrigido. Os comandos -map atribuem para estes arquivos de entrada qual será o vídeo e qual será o áudio. -vcodec copy indica que a faixa de vídeo será escrita idêntica a original, sem recompressão e -acodec libfaaac -ab 128k indica que o som WAV será comprimido no formato AAC e em 128kbps. E por último o nome do arquivo de saída. Pronto!

3 comentários:

  1. Olá, muito bom o seu post!
    Como faço para converter um arquivo de vídeo (avi) stereo para mp4 mono com normalização do áudio?

    Abraço.

    ResponderExcluir
    Respostas
    1. Eu sugeriria o mesmo script acima, com algumas modificações para ele codificar para MP4 no ultimo passo

      #!/bin/sh
      x=$1
      file=${x%.*}
      ffmpeg -i "$x" -vn -ac 1 "$file.wav"
      sox "$file.wav" "$file-2.wav" vol `sox "$file.wav" -n stat -v 2>&1`
      ffmpeg -i "$x" -i "$file-2.wav" -map 0:0 -map 1:0 -vcodec libx264 -acodec libfaac -ab 128k -ac 1 "$file-2.mp4"
      rm "$file-2.wav" "$file.wav"

      Excluir
  2. Alguem saberia me dizer o motivo ???
    - uma mesma linha de comando funciona em um arquivo e em outro nao.

    > ok
    ffmpeg -i C:\FFMPEG\input.mp4 -filter:v scale=-1:480 -c:v h264 -b:v 512k -minrate 512k -maxrate 512k -bufsize 512k -r 23 -c:a copy C:\FFMPEG\output.MP4

    > erro
    ffmpeg -i C:\FFMPEG\input.mkv -filter:v scale=-1:480 -c:v h264 -b:v 512k -minrate 512k -maxrate 512k -bufsize 512k -r 23 -c:a copy C:\FFMPEG\output.MP4

    ResponderExcluir