lame
é perfeitamente adequado para essa tarefa, mas vou usar ffmpeg
e ffprobe
para esta resposta, porque os conheço como as costas da minha mão e porque eles podem ser generalizados para mais do que apenas MP3s. Em primeiro lugar:
sudo apt-get install ffmpeg
Não há nenhuma ferramenta que eu saiba que possa ler arquivos de mídia e depois substituir a entrada imediatamente: você precisa usar um arquivo intermediário. Para um único arquivo, você pode fazer:
ffmpeg -i file.mp3 -c:a libmp3lame -b:a 192k temp.mp3
mv temp.mp3 file.mp3
Você pode combiná-los em uma única linha:
ffmpeg -i file.mp3 -c:a libmp3lame -b:a 192k temp.mp3 && mv temp.mp3 file.mp3
o &&
there significa que o mv
comando não será executado, a menos que ffmpeg
saia com o status 0 (que significa sucesso).
Para verificar qual a taxa de bits de um arquivo, você pode usar ffprobe
:
ffprobe -show_streams -select_streams a:0 -v quiet file.mp3 | grep -F 'bit_rate=320000'
-show_streams
diz ffprobe
para mostrar informações sobre fluxos individuais; -select_streams
diz a ele quais selecionar e a:0
significa 'o primeiro fluxo de áudio (isso é importante para arquivos MP3 no caso da arte da capa, que é armazenada como fluxo de vídeo). O pipe ( |
) pega a saída padrão ffprobe
e a alimenta grep
. grep
imprimirá apenas as linhas que correspondem a um determinado padrão - nesse caso, as linhas que contêm a sequência bit_rate=320000
. Se você executar isso em um MP3 de 320kbps, obterá uma linha como esta:
bit_rate=32000
Se você executá-lo em qualquer coisa com uma taxa de bits diferente, não obterá nenhuma saída; O grep falhará ao fazer uma correspondência e sairá com o status 1. Isso significa que você pode encadear esse comando com o comando ffmpeg:
ffprobe -show_streams -select_streams a:0 -v quiet file.mp3 | grep -F 'bit_rate=320000' && ffmpeg -i file.mp3 -c:a libmp3lame -b:a 192k temp.mp3 && mv temp.mp3 file.mp3
Ou, um pouco mais facilmente:
ffprobe -show_streams -select_streams a:0 -v quiet file.mp3 | grep -F 'bit_rate=320000' &&
ffmpeg -i file.mp3 -c:a libmp3lame -b:a 192k temp.mp3 &&
mv temp.mp3 file.mp3
Isso funcionará apenas em MP3s de 320 kbps. Experimente com alguns arquivos de teste.
O próximo passo é fazer isso funcionar com vários arquivos. Existem duas maneiras padrão de fazer isso: um for
loop e o find
comando. O seguinte atuará em todos os MP3 em um diretório:
for f in *.mp3; do
ffprobe -show_streams -select_streams a:0 "$f" | grep -F 'bit_rate=320000' &&
ffmpeg -y -i "$f" -c:a libmp3lame -b:a 192k /tmp/temp.mp3 && mv /tmp/temp.mp3 "$f"
done
Isso não entrará em subdiretórios; para fazer isso, você deve definir a globstar
opção shell:
shopt -s globstar
for f in **/*.mp3; do
ffprobe -show_streams -select_streams a:0 "$f" | grep -F 'bit_rate=320000' &&
ffmpeg -y -i "$f" -c:a libmp3lame -b:a 192k /tmp/temp.mp3 && mv /tmp/temp.mp3 "$f"
done
Com find
:
find . -name '*.mp3' -exec sh -c 'ffprobe -show_streams -select_streams a:0 "$0" | grep -F "bit_rate=320000" &&
ffmpeg -y -i "$0" -c:a libmp3lame -b:a 192k /tmp/temp.mp3 && mv /tmp/temp.mp3 "$0"' '{}' \;
Tudo isso será executado estritamente em sequência - eles apenas converterão um arquivo por vez. Seu processador é quase certamente capaz de mais do que isso; para acelerar as coisas, você pode usar o GNU parallel
:
sudo apt-get install parallel
shopt -s globstar
parallel 'ffprobe -show_streams -select_streams a:0 {} | grep -F "bit_rate=320000" &&
ffmpeg -y -i {} -c:a libmp3lame -b:a 192k {.}.temp.mp3 && mv {.}.temp.mp3 {}' ::: **/*.mp3
Ou:
find . -name '*.mp3' | parallel 'ffprobe -show_streams -select_streams a:0 {} | grep -F "bit_rate=320000" &&
ffmpeg -y -i {} -c:a libmp3lame -b:a 192k {.}.temp.mp3 && mv {.}.temp.mp3 {}'