Tìm thấy chủ đề này trong khi cố gắng thực hiện mã hóa trực tiếp MP3 từ các tệp nguồn FLAC. Câu trả lời của Boehj cung cấp một tùy chọn kịch bản hợp lý, nhưng cá nhân tôi thích sử dụng FFmpeg, vì vậy đây là kịch bản Bash mà tôi nghĩ ra để xử lý tác vụ này. Đã thử nghiệm và hoạt động tuyệt vời trong macOS Sierra (10.12.2).
Yêu cầu: Bạn nên có ffmpeg
và lame
đã cài đặt trên máy Mac của mình. Cách dễ nhất để làm điều này là thông qua Homebrew. Trước tiên hãy đảm bảo bạn đã cài đặt Homebrew như thế này:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Sau đó chạy lệnh này để cài đặt ffmpeg
và lame
:
brew install ffmpeg lame
Khi đã xong, bạn đã sẵn sàng để chạy tập lệnh này. Tập lệnh này sẽ tìm các tệp FLAC trong thư mục path/to/FLAC/files
nhưng có thể thay đổi thành đơn giản .
nếu các tệp FLAC nằm trong cùng thư mục mà bạn đang chạy tập lệnh này. Khi chạy, nó sẽ tạo một mp3/
thư mục con trong đó tất cả các tệp MP3 sẽ ở đặt.
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
Một số lưu ý về những điều tôi đã học được cách thức Hard Hard ™ ™ để những người khác có thể đạt được từ những gì tôi đã làm khác trong kịch bản này so với những người khác trên Internet.
- Các
grep
lệnh để phân tích cú pháp thẻ (sử dụng FFprobe được cài đặt với FFmpeg) không phân biệt chữ hoa chữ thường bằng cách sử dụng -i
tùy chọn để tạo ra nó grep -i
.
- Lệnh sau đây
cut
được giới hạn chỉ chia đầu ra dựa trên tên đầu tiên =
trong tên thẻ với -f 2-
tùy chọn tạo lệnh cut -d '=' -f 2-
. Ví dụ, Pavement có một bài hát có tên là 5-4 = Unity, và nếu chỉ có đoạn thứ hai được chọn thông qua việc cắt thì tiêu đề đó sẽ bị cắt ngắn thành Chú 5-4.
- Đối với số lượng track track và tổng số track track tôi đã thêm một đường ống bổ sung để
sed
loại bỏ các số 0 hàng đầu : sed 's/^0*//'
.
- Trong các tập lệnh tương tự trên Internet, đầu ra FFmpeg giống như thế
-f wav
và điều đó thực sự sẽ nén đầu ra FFmpeg, điều này không có ý nghĩa gì trong thiết lập đường ống nơi LAME sẽ mã hóa lại nó. Thay vào đó, đầu ra ở đây được đặt thành -f s16le -acodec pcm_s16le
về cơ bản là đầu ra RAW; hoàn hảo cho đường ống âm thanh đến một quá trình khác như thế này.
- Để đối phó với đầu ra RAW ở phía LAME của đường ống, tôi đã phải thêm
-r
tùy chọn.
- Cũng lưu ý
--tt
, --ta
, --tl
, --tn
và --tg
tùy chọn thẻ ID3v2 cho LAME. Khi âm thanh được truyền / truyền từ một quá trình vào LAME, siêu dữ liệu từ tệp nguồn bị mất. Một tùy chọn được đề xuất là để FFmpeg lưu siêu dữ liệu vào tệp văn bản bằng cách đặt tùy chọn với -f ffmetadata "[metadata filename here]"
và sau đó chạy lại FFmpeg với nội dung như sau : -i "[metadata filename here]" -map_metadata 1 -c:a copy [destination mp3 file] id3v2_version 3 -write_id3v1 1
. Điều đó hoạt động, nhưng lưu ý các yêu cầu cho một tập tin đích. Có vẻ như FFmpeg chỉ nhập siêu dữ liệu khi nó có thể sao chép tệp có vẻ như là một quá trình rất lãng phí. Sử dụng FFprobe để có được giá trị và sau đó thiết lập chúng trong LAME với --tt
, --ta
, --tl
, --tn
và --tg
tùy chọn hoạt động tốt hơn; tất cả các siêu dữ liệu được viết tại chỗ để tập tin trùng lặp cần được tạo.