lame
идеально подходит для этой задачи, но я собираюсь использовать ffmpeg
и ffprobe
для этого ответа, потому что я знаю их, как тыльную сторону моей руки, и потому что они могут быть обобщены не только в MP3. Прежде всего:
sudo apt-get install ffmpeg
Мне не известен инструмент, который мог бы читать мультимедийные файлы и затем сразу перезаписывать ввод: вам нужно использовать промежуточный файл. Для одного файла вы можете сделать:
ffmpeg -i file.mp3 -c:a libmp3lame -b:a 192k temp.mp3
mv temp.mp3 file.mp3
Вы можете объединить их в одну строку:
ffmpeg -i file.mp3 -c:a libmp3lame -b:a 192k temp.mp3 && mv temp.mp3 file.mp3
&&
там означает , что mv
команда не будет выполнена , если ffmpeg
выходы с состоянием 0 (что означает успех).
Чтобы проверить, какая скорость передачи данных у файла, вы можете использовать ffprobe
:
ffprobe -show_streams -select_streams a:0 -v quiet file.mp3 | grep -F 'bit_rate=320000'
-show_streams
говорит ffprobe
показывать информацию об отдельных потоках; -select_streams
сообщает ему, какие из них выбрать, и a:0
обозначает «первый аудиопоток (это важно для файлов MP3 в случае обложки, которая сохраняется в виде видеопотока). Pipe ( |
) принимает стандартный вывод ffprobe
и передает его grep
. grep
будет печатать только те строки, которые соответствуют заданному шаблону - в этом случае, строки, которые содержат строку bit_rate=320000
. Если вы запустите это на MP3 со скоростью 320 кбит / с, вы получите строку, подобную этой:
bit_rate=32000
Если вы запустите его на чем-то с другой скоростью, вы не получите никакого вывода вообще; grep не сможет найти соответствие и выйдет со статусом 1. Это означает, что вы можете связать эту команду с помощью команды 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
Или, немного более читабельно:
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
Это будет действовать только на MP3 320 кбит / с. Попробуйте это с парой тестовых файлов.
Следующий шаг - заставить это работать с несколькими файлами. Есть два стандартных способа сделать это: for
цикл и find
команда. Следующее будет действовать для каждого MP3 в каталоге:
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
Это не пойдет в подкаталоги; чтобы сделать это, вы должны установить параметр globstar
оболочки:
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
С 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"' '{}' \;
Все они будут выполняться строго последовательно - они будут конвертировать только один файл за раз. Ваш процессор почти наверняка способен на большее; чтобы ускорить процесс, вы можете использовать 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
Или:
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 {}'