Znalazłem ten wątek podczas próby bezpośredniego kodowania plików MP3 z plików źródłowych FLAC. Odpowiedź Boehja zapewnia przyzwoitą opcję skryptową, ale ja osobiście wolę używać FFmpeg, więc jest to skrypt Bash, który wymyśliłem, aby poradzić sobie z tym zadaniem. Testowane i działa świetnie w macOS Sierra (10.12.2).
Wymagania: Powinieneś mieć ffmpeg
i lame
już zainstalować na komputerze Mac. Najłatwiej to zrobić za pomocą Homebrew. Najpierw upewnij się, że masz zainstalowany Homebrew w ten sposób:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Następnie uruchom to polecenie, aby zainstalować ffmpeg
i lame
:
brew install ffmpeg lame
Po zakończeniu możesz uruchomić ten skrypt. Ten skrypt będzie szukał plików FLAC w katalogu, path/to/FLAC/files
ale można to zmienić tak, aby .
pliki FLAC znajdowały się w tym samym katalogu, w którym uruchamiany jest ten skrypt. Po uruchomieniu utworzy mp3/
podkatalog, w którym wszystkie pliki MP3 będą umieszczony.
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
Kilka notatek o rzeczach, których nauczyłem się „The Hard Way ™”, aby inni mogli czerpać korzyści z tego, co zrobiłem inaczej w tym skrypcie w porównaniu do innych w Internecie.
- Te
grep
komendy dla tagu parsowania (używając FFprobe którym jest zainstalowany z FFmpeg) są wrażliwe na wielkość liter przy użyciu -i
opcji, aby go grep -i
.
- Następujące
cut
polecenie jest teraz ograniczone do dzielenia danych wyjściowych tylko na podstawie pierwszego =
w nazwie znacznika z -f 2-
opcją, która tworzy polecenie cut -d '=' -f 2-
. Na przykład, Pavement ma utwór zatytułowany „5-4 = Unity”, a gdyby tylko drugi fragment został wybrany przez cięcie, tytuł zostałby skrócony do „5-4”.
- Na torze-torowych i całkowitych numerami dodałem dodatkową rurę
sed
, która pozbywa zer wiodących: sed 's/^0*//'
.
- W podobnych skryptach w Internecie wyjście FFmpeg jest czymś podobnym
-f wav
i faktycznie kompresuje wyjście FFmpeg, co nie ma sensu w konfiguracji potoku, w której LAME zamierza go ponownie zakodować. Zamiast tego ustawia się tutaj wyjście, -f s16le -acodec pcm_s16le
które jest zasadniczo wyjściem RAW; idealny do przesyłania dźwięku do innego procesu takiego jak ten.
- Aby poradzić sobie z danymi wyjściowymi RAW po stronie LAME rury, musiałem dodać
-r
opcję.
- Należy również pamiętać
--tt
, --ta
, --tl
, --tn
i --tg
ID3v2 opcji znacznik do LAME. Gdy dźwięk jest przesyłany strumieniowo / przesyłany strumieniowo z jednego procesu do LAME, metadane z pliku źródłowego są tracone. Jednym z sugerowanych opcji jest uzyskanie FFmpeg zapisać metadane w pliku tekstowym poprzez ustawienie opcji z -f ffmetadata "[metadata filename here]"
czym działa FFmpeg znowu z czymś takim: -i "[metadata filename here]" -map_metadata 1 -c:a copy [destination mp3 file] id3v2_version 3 -write_id3v1 1
. To działa, ale zwróć uwagę na wymaganie dotyczące pliku docelowego. Wydaje się, że FFmpeg importuje metadane tylko wtedy, gdy może skopiować plik, co wydaje się bardzo marnotrawstwem. Korzystanie FFprobe uzyskać wartości, a następnie ustawiając je w LAME z --tt
, --ta
, --tl
, --tn
i --tg
opcje działa lepiej; wszystkie metadane są zapisane w miejscu, dlatego należy wygenerować duplikat pliku.