如何仅使用终端机使用LAME和FLAC从.flac转换为.mp3?


31

很长时间以来,我一直在使用一种相对笨拙的技术,该技术涉及带有LAME插件的Audacity。我想这很好,但是使用Terminal方法的吸引力在于,我可以更精细地了解自己,[options]并且可以使用更多最新的二进制文件。

此外,我的MacBook现在已经老化了一些,如果我可以摆脱不必要的GUI,那就更好了。

提前致谢。


1
您实际上会为此获得积分;)
Mortimer

哈哈...我已经回答了这个问题,但这是说我无法在两天内确认我的回答。抱歉。仍在弄清楚这里的工作方式。很棒的网站。:D
boehj 2011年

Answers:


41

转换单个文件而不保留标签

brew install lame
flac --decode --stdout test.flac | lame --preset extreme - test.mp3
  • --decode --stdout = -dc
  • lame - $outfile =来自STDIN的输入
  • --preset extreme= 〜245 kbit / s VBR

一个保留一些ID3标签的shell脚本

#!/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

这将转换Music文件夹中的所有flac文件:

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

或稍快一些,因为它只调用flac2mp3一次:

find ~/Music/ -name '*.flac' -print0 | xargs -0 ~/bin/flac2mp3

2
您应该在此处发布答案,而不要参考问题中的文字。恕我直言,您应该同时编辑问题和答案,然后将结论移到此处。
lpacheco'2

好的。抱歉。
boehj 2011年

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 2012年

同样很高兴创建一个脚本来执行此“查找”任务……
Mehal 2012年

10

ffmpeg默认会保留标签(但不包括封面)。

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

-aq 1对应于-V 1in脚。-acodec libfaac会将文件转换为AAC:

for f in *.flac; do ffmpeg -i "$f" -acodec libfaac -aq 200 "${f%flac}m4a"; done

我只是这样做了,它说:```元数据:注释:Cover(前)编码器:Lavc57.107.100 png```macOS finder显示了封面。来自brew的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

您可以看到它也更有效地利用了我的CPU,我有一个Intel i7,所以8可能是正确数量的进程。


2

尝试从FLAC源文件直接对MP3进行编码时找到了此线程。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)"

然后运行这个命令来安装ffmpeglame

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-。例如,“ 铺装”有一首名为“ 5-4 = Unity”的歌曲,如果仅通过剪切选择了第二块,则该标题将被截断为“ 5-4”。
  • 对于轨道和总轨道数,我添加了一个多余的管道,以sed消除前导零:sed 's/^0*//'
  • 在Internet上类似的脚本中,FFmpeg输出类似于这样-f wav,并且实际上会压缩FFmpeg输出,这在LAME将对其进行重新编码的管道设置中毫无意义。而是将此处的输出设置-f s16le -acodec pcm_s16le为基本上是RAW输出;非常适合将音频传递到这样的另一个过程。
  • 为了处理管道的LAME端上的RAW输出,我必须添加该-r选项。
  • 还要注意--tt--ta--tl--tn--tgID3v2标签的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选择工作得更好; 所有元数据都写入到位,因此需要生成重复文件。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.