Как перейти от .flac к .mp3, используя LAME & FLAC, используя только терминал?

31

В течение долгого времени я использовал относительную неуклюжую технику, которая включает Audacity с плагином LAME. Это хорошо, я думаю, но привлекательность терминального подхода заключается в том, что я могу быть немного лучше с моими [options]и, возможно, использовать более современные двоичные файлы.

Кроме того, мой MacBook немного устарел, и если я смогу избавиться от ненужного графического интерфейса, тем лучше.

Заранее спасибо.

boehj
источник
1
вы действительно получите очки за это;)
Мортимер
Хаха ... Я ответил на вопрос, но там говорится, что я не могу подтвердить свой ответ в течение двух дней. Сожалею. Все еще выясняю, как все здесь работает. Потрясающий сайт. : D
boehj

Ответы:

41

Преобразование одного файла без сохранения тегов

brew install lame
flac --decode --stdout test.flac | lame --preset extreme - test.mp3
  • --decode --stdout знак равно -dc
  • lame - $outfile = вход от STDIN
  • --preset extreme= ~ 245 кбит / с VBR

Сценарий оболочки, который сохраняет некоторые теги ID3

#!/bin/bash

for f in "$@"; do
    [[ "$f" != *.flac ]] && continue
    album="$(metaflac --show-tag=album "$f" | sed 's/[^=]*=//')"
    artist="$(metaflac --show-tag=artist "$f" | sed 's/[^=]*=//')"
    date="$(metaflac --show-tag=date "$f" | sed 's/[^=]*=//')"
    title="$(metaflac --show-tag=title "$f" | sed 's/[^=]*=//')"
    year="$(metaflac --show-tag=date "$f" | sed 's/[^=]*=//')"
    genre="$(metaflac --show-tag=genre "$f" | sed 's/[^=]*=//')"
    tracknumber="$(metaflac --show-tag=tracknumber "$f" | sed 's/[^=]*=//')"

    flac --decode --stdout "$f" | lame --preset extreme --add-id3v2 --tt "$title" --ta "$artist" --tl "$album" --ty "$year" --tn "$tracknumber" --tg "$genre" - "${f%.flac}.mp3"
done

Чтобы использовать скрипт, просто сохраните его где-нибудь как ~/bin/flac2mp3и сделайте его исполняемым chmod +x ~/bin/flac2mp3.

Это преобразовало бы все файлы flac в вашей папке Music:

find ~/Music/ -name '*.flac' -exec ~/bin/flac2mp3 {} \;

Или немного быстрее, так как он вызывает flac2mp3 только один раз:

find ~/Music/ -name '*.flac' -print0 | xargs -0 ~/bin/flac2mp3
boehj
источник
2
Вы должны опубликовать ответ здесь, а не ссылку на текст в вопросе. ИМХО, вы должны отредактировать как вопрос, так и ответ и перенести сюда заключение.
lpacheco
Нормально будет сделать. Сожалею.
Boehj
2
${file%.flac}.mp3является удивительным! Ранее я использовал ${x:: ${#x}-3}m4aдля того, чтобы изменить имя файла песни с .wav на .m4a. Удивительно видеть способ, который выглядит немного проще.
Джейсон Салаз
1
Похоже, в Варианте 3 есть ошибка. Возможно, из-за неудачной версии, но текущий код не говорит ламеру, что он должен использовать входной поток в качестве входного файла, а также выходной файл не указан, так как поток используется, это необходимо. Для меня окончательный код: !/bin/sh file="$1" outfile=${file%.flac}.mp3 eval $(metaflac --export-tags-to - "$file" | sed "s/=\(.*\)/='\1'/") flac -cd "$file" | lame --preset standard \ --add-id3v2 --tt "$TITLE" --ta "$ARTIST" --tl "$ALBUM" \ --ty "$DATE" --tn "$TRACKNUMBER" --tg "$GENRE" \ - "$outfile"
Mehal
Также неплохо создать скрипт, который выполняет эту функцию поиска
Mehal
10

ffmpeg сохранит теги (но не обложку) по умолчанию.

for f in *.flac; do ffmpeg -i "$f" -aq 1 "${f%flac}mp3"; done

-aq 1соответствует -V 1в хромой. -acodec libfaacконвертирует файлы в AAC:

for f in *.flac; do ffmpeg -i "$f" -acodec libfaac -aq 200 "${f%flac}m4a"; done
LRI
источник
Я только что сделал это, и он сказал: `` `Метаданные: комментарий: Cover (front) кодировщик: Lavc57.107.100 png` `` macOS finder показывает обложку. ffmpeg 3.4.2 от варева.
Хабби
Затем я понял, что мой ffmpeg был очень старым. Я обновил его до 4.1.3 с тем же результатом - mp3-файлы того же размера, с рабочей обложкой.
Хабби
4

Я взял то, что у вас было, ребята, но затем заставил его работать еще быстрее, используя xargsраспараллеливание заданий.

find <directory> -name '*.flac' -print0 | xargs -0 -P8 -n1  /usr/local/bin/flac2mp3

Тогда это скрипт сверху / usr / local / bin / flac2mp3

#!/usr/bin/env bash

for f in "$@"; do
  [[ "$f" != *.flac ]] && continue
  album="$(metaflac --show-tag=album "$f" | sed 's/[^=]*=//')"
  artist="$(metaflac --show-tag=artist "$f" | sed 's/[^=]*=//')"
  date="$(metaflac --show-tag=date "$f" | sed 's/[^=]*=//')"
  title="$(metaflac --show-tag=title "$f" | sed 's/[^=]*=//')"
  year="$(metaflac --show-tag=date "$f" | sed 's/[^=]*=//')"
  genre="$(metaflac --show-tag=genre "$f" | sed 's/[^=]*=//')"
  tracknumber="$(metaflac --show-tag=tracknumber "$f" | sed 's/[^=]*=//')"

  flac --decode --stdout "$f" \ 
         | lame --preset extreme \
                --add-id3v2 \
                 --tt "$title" \
                 --ta "$artist" \
                 --tl "$album" \
                 --ty "$year" \
                 --tn "$tracknumber" \
                 --tg "$genre" \
                 - "${f%.flac}.mp3"
done

и вот некоторые статистические данные для повышения производительности с использованием параллелизма.

find <dirOfFlac24s> -name '*.flac -print0 | xargs -0 -P8 -n1 /usr/local/bin/flac2mp320  

0.00s user 0.00s system 60% cpu 0.002 total
115.94s user 1.40s system 359% cpu 32.655 total

time /usr/local/bin/flac2mp320 <dirOfFlac24s>/*.flac
96.63s user 1.46s system 109% cpu 1:29.98 total

Вы можете видеть, что он также использовал мои процессоры более эффективно, у меня есть Intel i7, так что 8, вероятно, правильное количество процессов.

Джейк Плимак
источник
2

Нашел эту ветку при попытке сделать прямое кодирование MP3 из исходных файлов FLAC. Ответ Boehj обеспечивает хороший сценарий, но я лично предпочитаю использовать FFmpeg, так что это сценарий Bash, который я придумал для выполнения этой задачи. Протестировано и прекрасно работает в macOS Sierra (10.12.2).

Преимущества: Вы должны иметь ffmpegи lameуже установлены на вашем Mac. Самый простой способ сделать это через Homebrew. Сначала убедитесь, что Homebrew установлен следующим образом:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Затем запустите эту команду для установки ffmpegи lame:

brew install ffmpeg lame

Как только это будет сделано, вы готовы запустить этот скрипт. Этот сценарий будет искать файлы FLAC в каталоге, path/to/FLAC/filesно это можно изменить, просто .указав, что файлы FLAC находятся в том же каталоге, в котором вы запускаете этот сценарий. При запуске он создаст mp3/подкаталог, в котором будут находиться все файлы MP3. размещены.

find -E "path/to/FLAC/files" -type f -iregex ".*\.(FLAC)$" |\
  while read full_audio_filepath
  do

    # Break up the full audio filepath stuff into different directory and filename components.
    audio_dirname=$(dirname "${full_audio_filepath}");
    audio_basename=$(basename "${full_audio_filepath}");
    audio_filename="${audio_basename%.*}";
    # audio_extension="${audio_basename##*.}";

    # Set the MP3
    mp3_dirpath="${audio_dirname}/mp3";
    mp3_filepath="${mp3_dirpath}/${audio_filename}.mp3";

    # Create the child MP3 directory.
    mkdir -p "${mp3_dirpath}";

    # Get the track metadata.
    mp3_title=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:TITLE= | cut -d '=' -f 2- );
    mp3_artist=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:ARTIST= | cut -d '=' -f 2- );
    mp3_album=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:ALBUM= | cut -d '=' -f 2- );
    mp3_year=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:YEAR= | cut -d '=' -f 2- );
    mp3_track=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:TRACK= | cut -d '=' -f 2- | sed 's/^0*//' );
    mp3_tracktotal=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:TRACKTOTAL= | cut -d '=' -f 2- | sed 's/^0*//' );
    mp3_genre=$(ffprobe 2> /dev/null -show_format "${full_audio_filepath}" | grep -i TAG:GENRE= | cut -d '=' -f 2- );

    # Where the magic happens.
    ffmpeg -y -v quiet -nostdin -i "${full_audio_filepath}" -ar 44100 -sample_fmt s16 -ac 2 -f s16le -acodec pcm_s16le - | \
      lame --quiet --add-id3v2 --pad-id3v2 --tt "${mp3_title}" --ta "${mp3_artist}" --tl "${mp3_album}" --tn "${mp3_track}"/"${mp3_tracktotal}" --tg "${mp3_genre}" -r -m s --lowpass 19.7 -V 3 --vbr-new -q 0 -b 96 --scale 0.99 --athaa-sensitivity 1 - "${mp3_filepath}";

  done

Некоторые заметки о том, что я выучил «The Hard Way ™», чтобы другие могли извлечь выгоду из того, что я сделал по-другому в этом сценарии, по сравнению с другими в Интернете.

  • Эти grepкоманды для тега синтаксического анализа ( с использованием FFprobe , который установлен с FFmpeg) нечувствительны к регистру , используя -iопцию , чтобы сделать это grep -i.
  • Следующая cutкоманда теперь ограничена разделением вывода только на основе первого =в имени тега с -f 2-опцией, которая делает команду cut -d '=' -f 2-. Например, у Pavement есть песня под названием «5-4 = Unity», и если бы только второй фрагмент был выбран посредством вырезания, этот заголовок был бы обрезан до «5-4».
  • Для отслеживания и общее количество дорожек-номеров я добавил дополнительную трубу , sedкоторая избавляется от ведущих нулей: sed 's/^0*//'.
  • В подобных сценариях по всему Интернету вывод FFmpeg является чем-то похожим, -f wavи это фактически сжимает вывод FFmpeg, что не имеет смысла в настройке канала, где LAME собирается перекодировать его. Вместо этого здесь устанавливается выход, -f s16le -acodec pcm_s16leкоторый в основном является выходом RAW; идеально подходит для передачи звука в другой процесс, как этот.
  • Чтобы иметь дело с выводом RAW на стороне трубы LAME, мне пришлось добавить -rопцию.
  • Также обратите внимание на --tt, --ta, --tl, --tnи --tgварианты тегов ID3v2 для LAME. Когда аудио передается / передается из одного процесса в LAME, метаданные из исходного файла теряются. Один из предложенных вариантов, чтобы получить FFmpeg сохранить метаданные в текстовый файл, установив параметр с , -f ffmetadata "[metadata filename here]"а затем снова запустить FFmpeg с чем - то вроде этого: -i "[metadata filename here]" -map_metadata 1 -c:a copy [destination mp3 file] id3v2_version 3 -write_id3v1 1. Это работает, но обратите внимание на требование к файлу назначения. Похоже, FFmpeg импортирует метаданные только тогда, когда он может скопировать файл, что кажется очень расточительным процессом. Использование FFprobe для получения значений , а затем устанавливать их в LAME с --tt, --ta, --tl, --tnи --tgварианты работы лучше; все метаданные записаны на месте, поэтому необходимо создать дубликат файла.
JakeGould
источник