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 у випадку обкладинки, яка зберігається як відеопотік). Труба ( |
) приймає стандартний вихід 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 {}'