Difference between revisions of "Convert FLAC to MP3"

From ArchWiki
Jump to: navigation, search
(Using the source)
m (Installation)
(37 intermediate revisions by 15 users not shown)
Line 1: Line 1:
[[Category:Development (English)]]
+
[[Category:Audio/Video]]
[[Category: HOWTOs (English)]]
+
[[Category:Scripts]]
[[Category:Package management (English)]]
+
{{Tip|You can use {{AUR|flac2mp3-bash}} script from aur to convert Flac to Mp3 easily.}}
{{i18n_links_start}}
+
{{i18n_entry|English|The_Arch_package_making_HOW-TO_-_with_guidelines}}
+
{{i18n_entry|Русский|The_Arch_package_making_HOW-TO_-_with_guidelines(russian)}}
+
{{i18n_entry|简体中文|The_Arch_package_making_HOW-TO_-_with_guidelines(Chinese)}}
+
{{i18n_links_end}}
+
  
这个文档 [[ABS_-_The_Arch_Build_System | ABS - The Arch Build System]] 提供了一份良好的用于制作和修改 Arch Linux 软件包所需工具和文件的总览。如果你只想要定制或重新编译一个已经存在的软件包,这里应该已经提供了足够的信息。但是,如果你想要制作一个新的软件包,你还需要一些额外的指南。这个文档假定你已经事先阅读并掌握了 ABS 的描述。
+
==Introduction==
 +
Here is a script that will convert FLAC to MP3 via the commandline.
  
==准备文件==
+
Essentially, the .flac files within a directory will be decompressed to .wav and then the resulting .wav files will be encoded to .mp3 using the latest LAME switches for encodings (''-V 0 --vbr-new''). The ID3 tags of the original .flac files will be passed to the resulting .mp3 files.
所有用于制作一个软件包所需的信息放在 <code>PKGBUILD</code>  文件中。当你运行 <code>makepkg</code> 命令,它将在当前工作目录中寻找 <code>PKGBUILD</code> 文件,然后根据 <code>PKGBUILD</code> 文件中的指令编译软件的源代码。当编译成功后,得到的二进制代码,包括诸如包版本和依赖等meta-信息将封装在名叫 <code>name.pkg.tar.gz</code> 的软件包中,你可以使用 <code>pacman -Up <package file></code> 命令将其安装。
+
  
<code>PKGBUILD</code> 文件包含 '''所有''' 用于制作一个软件包所需的指令,这些指令以能够被 bash 识别的的格式存在(don't worry if that little tidbit of clue doesn't help you)。[[ABS_-_The_Arch_Build_System | ABS]] 条目中描述了这里使用的变量,但是最重要的也是最让人迷惑的变量在这里recapped。为了开始制作一个新的包,你应该首先创建一个空的目录,最好取名为 <code>/var/abs/local/<PKGNAME></code>。这样的话,它可以很好的统一到统一的 ABS 树,但如果你没有同步该树的话,cvsup 不会接触(touch)它。进入你新建的目录,创建 <code>PKGBUILD</code> 文件,你可以直接从 <code>/var/abs/PKGBUILD.proto</code> 复制虚构的原型,也可以复制其他软件包的 <code>PKGBUILD</code> 。如果你不需创建一个全新的文件,而只需修改其中的编译选项的话,后者是非常合适的选择。
+
The original .flac files will not be harmed and the resulting .mp3s will be in the same directory. All other files in the directory (.nfo, images, .sfv, etc) will be ignored and unharmed.  
  
无论你用那种方式,总之你需要一个 <code>PKGBUILD</code> 文件。
+
For more information on LAME switches/settings such as V0, visit [http://wiki.hydrogenaudio.org/index.php?title=LAME Hydrogenaudio LAME Wiki]. V0 is roughly equivalent to ''--preset extreme'' which results in a variable bitrate usually between 220-260. The audio of a V0 is transparent, meaning one cannot tell the difference between the lossy file and the original source (compact disc/lossless), but yet the file size is a quite reasonable.
  
==编辑变量==
+
More information on flac: [http://wiki.hydrogenaudio.org/index.php?title=Flac FLAC]
  
现在打开它,根据你构建的包的情况设置各个变量的值:
+
===Installation===
<br /><br />
+
*'''pkgname:''' 将这个变量设置为你的包的名字。按照惯例,你应该使用小写字母。最好包的名字与你所在的工作目录的名字相同,当然也与你将要下载的包含源程序的 tar.gz 文件名相同,但这并不是必须的。
+
  
*'''pkgver:''' 设置包的版本。它可以包含字母、数字和点,但不能有连字符。它由你打包的程序使用的版本系统决定(主版本.次版本.漏洞修复版本、major.日期等)。另外,在大多数情况下,你可以遵循源代码包的文件名的一部分的版本,以便后续步骤变得更为简单和灵活。还要注意:如果包的作者在其版本编号方案中使用了短横,请用下划线替代它。('0.99-10'  =>  '0.99_10')
+
First you need to install the following packages: flac, lame, and id3
  
*'''pkgrel:''' 这个变量从 1 开始,你每重新发布一次,其值将增加 1 ,它的目的是区分一个包的同一版本的连续构建。有时候第一次发布的包有问题或错误。当你第二次发布这个包时,你将 <code>pkgrel</code> 变量加 1 ,这样 pacman 知道它需要重新安装。当这个包又发布了一个新的 '''版本''' 时,你将 <code>pkgrel</code> 变量重设为 1
+
<pre>
 +
pacman -S flac lame id3
 +
</pre>
  
*'''pkgdesc:''' 该变量为该包的简短的描述,通常应该少于 76 个字符。通常并需要重复程序的名字。<code>OpenGL accelerated X server</code> 优于 <code>xgl is a OpenGL...</code> 。
+
Once those are installed, copy the following script into your preferred editor:
  
*'''arch:''' 该变量应该为架构的名称,通常为 'i686' ,它描述的是该 PKGBUILD 文件能够使用的架构。你可以在构建过程中使用 <code>$arch</code> 来获取这个变量。
+
<pre>
 +
#! /bin/sh
  
*'''url:''' 该变量为程序的官方站点的地址,这样有兴趣的人可以由此获得更多的信息。
+
for a in *.flac; do
 +
    OUTF=${a%.flac}.mp3
  
*'''license:''' 许可的类型,如果你不知道,请将其写成 'unknow' 。
+
    ARTIST=$(metaflac "$a" --show-tag=ARTIST | sed s/.*=//g)
 +
    TITLE=$(metaflac "$a" --show-tag=TITLE | sed s/.*=//g)
 +
    ALBUM=$(metaflac "$a" --show-tag=ALBUM | sed s/.*=//g)
 +
    GENRE=$(metaflac "$a" --show-tag=GENRE | sed s/.*=//g)
 +
    TRACKNUMBER=$(metaflac "$a" --show-tag=TRACKNUMBER | sed s/.*=//g)
 +
    DATE=$(metaflac "$a" --show-tag=DATE | sed s/.*=//g)
  
*'''depends:''' 该变量为在该程序能够运行前所必须安装的一系列包的名字的序列,用空格分开每个包名。这些包名可以用单引号引起来,以避免可能的 shell quoting 的问题,并且该序列必须用圆括号括起来。有时,一个程序需要一个最低版本的依赖;在这种情况下,请将数学上的 "大于 或 等于" 运算符,并将这些运算符也放在引号里。这里是一个添加 glibc 包的依赖的实例,slang 库的版本至少应为 1.8.0 :'''<code>depends('glibc' 'slang>=1.8.0')</code>'''
+
    flac -c -d "$a" | lame -m j -q 0 --vbr-new -V 0 -s 44.1 - "$OUTF"
 +
    id3 -t "$TITLE" -T "${TRACKNUMBER:-0}" -a "$ARTIST" -A "$ALBUM" -y "$DATE" -g "${GENRE:-12}" "$OUTF"
 +
done
 +
</pre>
  
*'''makedepends:''' 该变量为只是在打包过程中需要而在安装后的*使用*过程中并不需要的包的名字的序列。举例:<code>unarj</code> 用于在打包过程中解压某些补丁。
+
Below is a modified version of the above script which:
 +
* adds an optional parameter (-d), which, if passed on the command line, causes each source FLAC file to be deleted after successful conversion;
 +
* changes the LAME encoding options as follows:
 +
** drops --vbr-new, as it is the default VBR behaviour as of LAME 3.98, and thus is automatically used when "-V 0" is used;
 +
** drops "-m j", as LAME defaults to the specified value (joint stereo) when using --vbr-new (see above);
 +
** drops "-q 0", as LAME defaults to this behaviour when using VBR;
 +
** drops "-s 44.1", as LAME detects the proper sample rate to use;
 +
** adds "--noreplaygain" (personal preference);
 +
* and uses LAME to write tags instead of the id3 package, which has the dual advantage of removing the need for an additional package in the tool chain and allowing the script to write both id3v1 and id3v2 tags (the id3 package does not support id3v2 tags).
  
*'''provides:''' 该变量为因为即将构建的包提供了相同的作用而变得不再需要的包的名字的序列。
+
Now for the script:
  
*'''conflicts:''' 该变量为安装该包后会产生问题的包的名字的序列。
+
<pre>
 +
#! /bin/sh
  
*'''replaces:''' 该变量为即将构建的包可以替代的陈旧的包的名字的序列。
+
for a in *.flac; do
 +
    OUTF=${a%.flac}.mp3
  
*'''source:''' 该变量为构建该包所需文件的序列,至少应包含程序源的地址,在大多数情况下是一个完整的用双引号引起来的 http 或 ftp 地址。 这里的 <code>PKGBUILD</code> 的样本向你很好的展示了如何使用以前设置的包名和包版本的变量。如果你发现你需要补充一些不能通过下载得到的文件如自制的补丁时,你只需要要将这些文件与 <code>PKGBUILD</code> 放在同一目录即可,然后将补丁的文件名添加在 source 的序列中。任何你在此添加的路径为相对于 <code>PKGBUILD</code> 所在目录的相对路径。在实际的构建过程开始前,所有此处涉及的文件将被下载或检查是否存在,如果存在任何文件遗失, <code>makepkg</code> 将不能进行。
+
    ARTIST=`metaflac "$a" --show-tag=ARTIST | sed s/.*=//g`
 +
    TITLE=`metaflac "$a" --show-tag=TITLE | sed s/.*=//g`
 +
    ALBUM=`metaflac "$a" --show-tag=ALBUM | sed s/.*=//g`
 +
    GENRE=`metaflac "$a" --show-tag=GENRE | sed s/.*=//g`
 +
    TRACKNUMBER=`metaflac "$a" --show-tag=TRACKNUMBER | sed s/.*=//g`
 +
    DATE=`metaflac "$a" --show-tag=DATE | sed s/.*=//g`
  
*'''md5sums:''' 源文件的 md5 检查值,用空格分开,并用引号引起来。当 source 序列中的所有文件都存在时,每个文件的 md5 计算值将自动产生并于这里提供的值对照,'''这些值的顺序应与 source 序列中的顺序相同。''' 同时,源文件本身的顺序并不重要,重要的是与 md5sums 的顺序一致,因为 <code>makepkg</code> 不会猜测 md5sums 属于哪个源文件,所以如果他们不能匹配,则会开始报错,这样可以防止下载错误或程序被篡改。你可以在包含 <code>PKGBUILD</code> 文件的目录下使用 <code>makepkg -g</code> 命令简单的得到 md5sums (在你将源序列正确的设置后) 。<code>makepkg -g >>PKGBUILD</code> 将生成这些 sums 并将其附在 <code>PKGBUILD</code> 的后面,你可以将其挪到合适的位置上。
+
    flac -c -d "$a" | lame --noreplaygain -V0 \
 +
        --add-id3v2 --pad-id3v2 --ignore-tag-errors --tt "$TITLE" --tn "${TRACKNUMBER:-0}" \
 +
        --ta "$ARTIST" --tl "$ALBUM" --ty "$DATE" --tg "${GENRE:-12}" \
 +
        - "$OUTF"
 +
    RESULT=$?
 +
    if [ "$1" ] && [ "$1" = "-d" ] && [ $RESULT -eq 0 ]; then
 +
        rm "$a"
 +
    fi
 +
done
 +
</pre>
  
到目前为止,你只是把与包有关的 meta-信息 设置好了;到哪去下载源代码,包的名字是什么等。下一步是补充如何实际 ''编译和安装'' 你将打包的程序的指令。
+
Alternatively, below is a script that will search for all FLAC audio files beyond where the script resides on your filesystem and convert them to MP3; including those pesky filenames with spaces.
  
==使用源代码==
+
<pre>
现在你需要下载源代码包,将其解压,记录所有需要的用于编译和安装它的命令。<code>PKGBUILD</code> 内的 <code>build()</code> 函数的作用就是将这些步骤重复一遍,并在这些过程完成以后将所有的东西封装起来。
+
#! /bin/bash
  
现在你需要编辑在 <code>PKGBUILD</code> 内的 build() 函数的内容。这个函数使用普通的 bash 语法的  shell 命令。该函数的基本作用就是自动的编译程序并且创建一个用于安装程序的 <code>pkg</code> 目录,然后让 <code>makepkg</code> 将所有的文件封装起来,而不用从你实际的文件系统中将相关文件提取出来。
+
find . -type f -name "*.flac" -print0 | while read -d $'\0' a
  
===build()函数===
+
do
通常 build 函数的第一步是进入因解压源代码包生成的目录中。你可以使用 <code>$startdir</code> 变量(它指的是包含<code>PKGBUILD</code>的目录)。你也可以使用你先前设置的 $pkgname 和 $pkgver 变量。举个例子,取决于由 makepkg 解压产生的目录的名字,你的 build 函数的第一个命令可能是 <code>cd $startdir/src/$pkgname-$pkgver</code> ,这通常是一种非常可能的情况,除非该程序的作者是一个十足的麻烦制造者。
+
    OUTF=${a%.flac}.mp3
  
编译程序是一个较难的部分。我这里假定你可以成功的手动编译该程序,因为所有可能的步骤将不可避免。这也是程序的作者应该写 README 和 INSTALL 文件的原因。
+
    ARTIST=`metaflac "$a" --show-tag=ARTIST | sed s/.*=//g`
 +
    TITLE=`metaflac "$a" --show-tag=TITLE | sed s/.*=//g`
 +
    ALBUM=`metaflac "$a" --show-tag=ALBUM | sed s/.*=//g`
 +
    GENRE=`metaflac "$a" --show-tag=GENRE | sed s/.*=//g`
 +
    TRACKNUMBER=`metaflac "$a" --show-tag=TRACKNUMBER | sed s/.*=//g`
 +
    DATE=`metaflac "$a" --show-tag=DATE | sed s/.*=//g`
  
现在你在那个目录中,你需要将所有用来编译这些文件的命令列出来。在一些简单的情况下,你只需使用现行的 <code>gcc</code> 命令来编译这些包。
+
    flac -c -d "$a" | lame -m j -q 0 --vbr-new -V 0 -s 44.1 - "$OUTF"
 +
    id3 -t "$TITLE" -T "${TRACKNUMBER:-0}" -a "$ARTIST" -A "$ALBUM" -y "$DATE" -g "${GENRE:-12}" "$OUTF"
 +
done
 +
</pre>
  
好的事情是,如果你可以手动编译该包,你基本上只需将你使用的命令列在这里,一切将会很好的进行下去。因为很多包喜欢将其文件安装在相对的 <code>/usr/local</code>  目录中,为了使命令注意到这一点,你可能需要补充一个参数到配置脚本中。<code>PKGBUILD</code> 的样本可以作为一个例子。当然你的情况也有可能与样本不同。再说一次,你的情况有可能不同。
+
Save the script as ''flac2mp3'' and make the script executable:
  
<code>build()</code> 函数的下一步是将已经编译好的文件放在一个 <code>makepkg</code> 可以将其打包的目录。这个目录就是 <code>pkg</code> 目录。该目录是仿照程序安装步骤中你文件系统的根目录。任何在实际安装过程进入你文件系统的的文件将按照相同的目录结构进入 <code>pkg</code> 目录。(打个比方。加入你想要将 <code>myprog</code> 文件安装在 <code>/usr/bin</code> 中,这里你应该将其放在 <code>$startdir/pkg/usr/bin</code> 中)。幸运的是只有少数程序需要用户手动复制很多文件,但他们需要补充某些安装步骤来替代本来应该自动进行的步骤,通常通过运行 "make install" 来调用。它是 '''critical''' ,但是,that you find out how to tell this installation procedure that it's supposed to stuff all it's nifty files '''not''' into your /, but into <code>$startdir/pkg/</code> instead! Otherwise you'll end up with an empty package file, and the binaries of the program you installed "correctly" added to your system already. Most of the time you'll have to supply the prefix parameter to the "make install" call as shown in the prototype, but it's very well possible that the program you're packaging expects an altogether different approach, but here are some hints:
+
<pre>
 +
chmod a+x flac2mp3
 +
</pre>
  
* Sometimes the <code>configure</code> script accepts a prefix property that tells where the files should be installed. You might use <code>./configure --prefix=$startdir/pkg/usr</code> in such configuration, for example.
+
As root, copy the script to /usr/local/bin (or anywhere else that is in your $PATH).
  
* Sometimes there is a <code>PREFIX</code> option to append to a <code>make install</code> command. This is sometimes set as a variable, and sometimes set in the command. In worse cases you have to edit the Makefile(s) (or ant build/properties files if the project uses ant) with sed or a patch you'd have to create yourself.
+
<pre>
 +
cp flac2mp3 /usr/local/bin
 +
</pre>
  
* There might be other sorts of install scripts that allow you to specify where the program should be installed.
+
To make /usr/local/bin in your $PATH, do (as normal user):
  
* In some cases, the program expects to be run from a single directory.  Often it is wise to simply copy these to <code>$startdir/pkg/opt</code>.
+
<pre>
 +
PATH=$PATH:/usr/local/bin/
 +
</pre>
  
As you might have guessed already, that's the part where actual knowledge and experience becomes a necessity. It helps a lot if you browse over the <code>PKGBUILD</code> files in the ABS tree, as those are tested and contain a few tricks that might prove valuable.
+
and then (as normal user):
 +
<pre>
 +
nano .bashrc
 +
</pre>
  
More often that not, the installation routine of the program will take care to create any subdirectories below the <code>pkg/</code> directory. If it does not, however, you'll get a lot of errors during the install stage as files are copied to nonexistent subdirectories. In that case you'll have to create the needed subdirectories by adding the appropriate <code>mkdir</code> commands in the <code>build()</code> function before running the installation procedure. The actual directory structure is package dependent, of course; some programs need to place files in <code>/etc</code> or <code>/usr</code> while others might need to use <code>/bin</code> or <code>/opt</code>.  Most will need to create several directories.  You can do all of this with the <code>mkdir -p $startdir/pkg/OTHER/DIRS/AS/NEEDED</code> command, where OTHER/DIRS/AS/NEEDED represent directories at the root of the filesystem.
+
and add ''export PATH=$PATH:/usr/local/bin/''
  
==Testing the PKGBUILD==
+
====Usage====
  
As you are writing the <code>PKGBUILD</code>'s <code>build()</code> function, you will want to test your changes frequently to ensure there are no bugs. You can do this using the <code>makepkg</code> command in the directory containing the <code>PKGBUILD</code>. With a properly formatted <code>PKGBUILD</code>, this will create a package, but with a broken or unfinished one it will throw an error. Hopefully it will be a descriptive error!
+
Open up a terminal and cd to the directory of .flac files that you wish to convert and enter ''flac2mp3''
  
If running <code>makepkg</code> finished successfully, it will place a shiny new file called $pkgname-$pkgver.pkg.tar.gz in your working directory. This is a pacman package and can be installed with the <code>pacman -U</code> and <code>pacman -A</code> options, or added to a local or web based repository.  Note that just because a package file was built it doesn't mean it works!  It might conceivably contain only the directory structure and no files whatsoever if, for example, you specified a prefix improperly. You can use pacman's query functions to display a list of files contained in the package and the dependencies it requires, and compare those with what you consider as correct. "pacman -Qlp <package file>" and "pacman -Qip <package file>" do the trick.
+
You'll see the verbose decoding/encoding process in the terminal which may take a few moments.  
  
If the package looks sane, that's all you need to do. However, if you plan on releasing the package or PKGBUILD, it is imperative that you check and double check and re-double-check the contents of the depends array. This should contain a list of all packages that need to be installed in order for your package to work. You only need to list first level depends in the depends array. That is, you do not need to list packages that your program depends on if other packages that your program depends on are already listed.
+
Done.
  
For example, <code>gtk2</code> depends on <code>glib2</code>. Like most open source C programs, it also requires <code>glibc</code> to be installed. However, <code>glibc</code> does not need to be listed as a dependency for <code>gtk2</code> because it is a dependency for <code>glib2</code>, and <code>glib2</code> is already listed in <code>gtk2</code>.
+
====Addendum====
  
There are some tools you can use to check dependencies, including Jason Chu's famous <code>namcap</code> program (<code>pacman -Sy namcap</code>), and the more arcane <code>ldd</code> program. Check the man pages for these programs and the links at the end of this document for more information.  You should also scour the program's documentation and website (some nice developers have a page called "dependencies" that helps a lot).
+
With a small modification the command file can be used to transcode the files into a new directory structure:
==Testing the package==
+
<pre>
Also make sure that the package binaries actually ''run'' flawlessly! It's really annoying to release a package that contains all necessary files, but dumps core because of some obscure configuration option that doesn't quite work well with the rest of the system. If you're only going to compile packages for your own system, though, you don't need to worry too much about this quality assurance step, as you're the only person suffering from mistakes after all.
+
#! /bin/bash
 +
find "$1" -name *.flac -print0 | while read -d $'\0' IF
 +
do
 +
  OF=$(echo "$IF" | sed -e 's/\.flac$/.mp3/g' -e "s,$1,$2,g")
 +
  echo "$IF -> $OF"
 +
  mkdir -p "${OF%/*}"
  
==To sum it all up==
+
  ARTIST=`metaflac "$IF" --show-tag=ARTIST | sed s/.*=//g`
* Download the source tarball of the program you want to package up
+
  TITLE=`metaflac "$IF" --show-tag=TITLE | sed s/.*=//g`
* Try compiling the package and installing it into an arbitrary directory
+
  ALBUM=`metaflac "$IF" --show-tag=ALBUM | sed s/.*=//g`
* Copy over the prototype <code>/var/abs/PKGBUILD.proto</code> and rename it to <code>PKGBUILD</code> in a temporary working directory
+
  GENRE=`metaflac "$IF" --show-tag=GENRE | sed s/.*=//g`
* Edit the PKGBUILD according to the needs of your package
+
  TRACKNUMBER=`metaflac "$IF" --show-tag=TRACKNUMBER | sed s/.*=//g`
* Run <code>makepkg</code> and see whether the resulting package is built correctly
+
  DATE=`metaflac "$IF" --show-tag=DATE | sed s/.*=//g`
* If not, repeat the last two steps
+
  
==Useful links==
+
  flac -c -d "$IF" 2> /dev/null | lame -m j -q 0 --vbr-new -V 0 -s 44.1 - "$OF" 2> /dev/null
* [[ABS_-_The_Arch_Build_System | ABS - The Arch Build System]]
+
  id3 -t "$TITLE" -T "${TRACKNUMBER:-0}" -a "$ARTIST" -A "$ALBUM" -y "$DATE" -g "${GENRE:-12}" "$OF"
* [http://www.archlinux.org/pacman/makepkg.8.html makepkg man page]
+
done
* [http://bbs.archlinux.org/viewtopic.php?t=4 about dependencies]
+
</pre>
* [http://bbs.archlinux.org/viewtopic.php?t=1590 makepkg tutorial]
+
if saved in flac2mp3 this can be used as follows
* [[PKGBUILD help|PKGBUILD Help]]
+
<pre>./flac2mp3 /srv/media/music /srv/media/music-lofi</pre>
* [[Arch CVS & SVN PKGBUILD guidelines]]
+
which will take the directory structure under /srv/media/music and transcode its content into /srv/media/music-lofi.
  
==Warnings==
+
With some more tweaks the script will support directories that contain '.' (dots) somewhere in the path and
* Before you can automate the package building process, you should have done it manually at least once unless you know ''exactly'' what you're doing ''in advance'', in which case you would not be reading this in the first place. Unfortunately, although a good bunch of program authors stick to the 3-step build cycle of "./configure; make; make install", this is not always the case, and things can get real ugly if you have to apply patches to make everything work at all. Rule of thumb: If you can't get the program to compile from the source tarball, and make it install itself to a defined, temporary subdirectory, you don't even need to try packaging it. There isn't any magic pixie dust in <code>makepkg</code> that makes source problems go away.
+
executing the script from folders that contain 'flac' files
* In a few cases, the packages are not even available as source and you have to use something like <code>sh installer.run</code> to get it to work. You will have to do quite a bit of research (read READMEs, INSTALL instructions, man pages, perhaps ebuilds from gentoo or other package installers, possibly even the MAKEFILEs or source code) to get it working. In some really bad cases, you have to edit the source files to get it to work at all. However, <code>makepkg</code> needs to be completely autonomous, with no user input. Therefore if you need to edit the Makefiles, you may have to bundle a custom patch with the <code>PKGBUILD</code> and install it from inside the <code>build()</code> function, or you might have to issue some <code>sed</code> commands from inside the <code>build()</code> function.
+
 
* Note that just because a package file was built it doesn't mean it works!  It might conceivably contain only the directory structure and no files whatsoever if, for example, you specified a prefix improperly. You can use pacman's query functions to display a list of files contained in the package and the dependencies it requires, and compare those with what you consider as correct. "pacman -Qlp <package file>" and "pacman -Qip <package file>" do the trick.
+
Also made specifying an alternate folder location optional
 +
<pre>
 +
#! /bin/bash
 +
find "$1" -name "*.flac" -print0 | while read -d $'\0' IF
 +
do
 +
  if [ "$2" != "" ]
 +
  then
 +
    OF="${IF%.flac}.mp3"
 +
    OF="$2/${OF##*/}"
 +
  else
 +
    OF="${IF%.flac}.mp3"
 +
  fi
 +
  echo "$IF -> $OF"
 +
  mkdir -p "${OF%/*}"
 +
 
 +
  ARTIST=`metaflac "$IF" --show-tag=ARTIST | sed s/.*=//g`
 +
  TITLE=`metaflac "$IF" --show-tag=TITLE | sed s/.*=//g`
 +
  ALBUM=`metaflac "$IF" --show-tag=ALBUM | sed s/.*=//g`
 +
  GENRE=`metaflac "$IF" --show-tag=GENRE | sed s/.*=//g`
 +
  TRACKNUMBER=`metaflac "$IF" --show-tag=TRACKNUMBER | sed s/.*=//g`
 +
  DATE=`metaflac "$IF" --show-tag=DATE | sed s/.*=//g`
 +
 
 +
  flac -c -d "$IF" 2> /dev/null | lame -m j -q 0 --vbr-new -V 0 -s 44.1 - "$OF" 2> /dev/null
 +
  id3 -t "$TITLE" -T "${TRACKNUMBER:-0}" -a "$ARTIST" -A "$ALBUM" -y "$DATE" -g "${GENRE:-12}" "$OF"
 +
done
 +
</pre>
 +
if saved in flac2mp3 this can be used as follows
 +
<pre>./flac2mp3 /srv/media.store/music /srv/media/music-lofi</pre>
 +
or
 +
<pre>./flac2mp3 /srv/media.store/music </pre>
 +
 
 +
=====Nautilus-scripts=====
 +
 
 +
Here's a well-written version of "flac2mp3" script which will run either from command line or, if you copy it into <tt>~/.gnome2/nautilus-scripts</tt>, it will appear in the right-click menu in Nautilus:
 +
<pre>
 +
#!/bin/bash
 +
#
 +
# Copyright 2008 Octavio Ruiz
 +
# Distributed under the terms of the GNU General Public License v3
 +
# $Header: $
 +
#
 +
# Yet Another FLAC to MP3 script
 +
#
 +
# Author:
 +
# Octavio Ruiz (Ta^3) <tacvbo@tacvbo.net>
 +
# Thanks:
 +
# Those comments at:
 +
# http://www.linuxtutorialblog.com/post/solution-converting-flac-to-mp3
 +
# WebPage:
 +
# https://github.com/tacvbo/yaflac2mp3/tree
 +
#
 +
# This program is distributed in the hope that it will be useful,
 +
# but WITHOUT ANY WARRANTY. YOU USE AT YOUR OWN RISK. THE AUTHOR
 +
# WILL NOT BE LIABLE FOR DATA LOSS, DAMAGES, LOSS OF PROFITS OR ANY
 +
# OTHER KIND OF LOSS WHILE USING OR MISUSING THIS SOFTWARE.
 +
# See the GNU General Public License for more details.
 +
#
 +
# Modified by woohoo
 +
#
 +
# you need zenity package for notifications.
 +
# please note that you can put this script in ~/.gnome2/nautilus-scripts
 +
# and it will show up in right-click menu in any folder in gnome.
 +
#
 +
# modify the lame options to your preference example change -b 320 to -b 128 or -b 192 or -b 256
 +
# LAME_OPTS="--vbr-new -V 0 -b 256"
 +
# LAME_OPTS="-V 0 --vbr-new"
 +
 
 +
LAME_OPTS="-b 320 -h --cbr"
 +
 
 +
old_IFS=${IFS}
 +
IFS='
 +
'
 +
 
 +
# when running from nautilus-scripts, it useful to find the current folder
 +
base="`echo $NAUTILUS_SCRIPT_CURRENT_URI | cut -d'/' -f3- | sed 's/%20/ /g'`"
 +
if [ -z "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS" ]; then
 +
  dir="$base"
 +
else
 +
  while [ ! -z "$1" -a ! -d "$base/$1" ]; do shift; done
 +
  dir="$base/$1"
 +
fi
 +
 
 +
if [ "$dir" != "" ]; then
 +
  cd "$dir"
 +
fi
 +
 
 +
id3v2=$(which id3v2)
 +
 
 +
files=`find . -type f -regex '^.+\.flac$' | sort`
 +
 
 +
declare -i nn=0
 +
for file in ${files}
 +
do
 +
  fn=$(readlink -f "$file")
 +
  vars=( `metaflac --no-utf8-convert --export-tags-to=- "${fn}"` )
 +
 
 +
  for N_vars in ${!vars[@]}
 +
  do
 +
    export "$(echo "${vars[${N_vars}]%=*}" | tr [:upper:] [:lower:])=${vars[${N_vars}]#*=}"
 +
  done
 +
 
 +
  dest=`echo "$fn"|sed -e 's/\.flac$/\.mp3/'`
 +
 
 +
  flac -dc "$fn" |\
 +
    lame --ignore-tag-errors --add-id3v2 ${LAME_OPTS} \
 +
        ${artist:+--ta} ${artist} \
 +
        ${tracknumber:+--tn} ${tracknumber} \
 +
        ${title:+--tt} ${title} \
 +
        ${album:+--tl} ${album} \
 +
        ${date:+--ty} ${date} \
 +
        ${genre:+--tg} ${genre} \
 +
        ${comment:+--tc} ${comment} \
 +
        - $dest
 +
 +
    [[ -x ${id3v2} ]] && ${id3v2} \
 +
        ${artist:+--artist} ${artist} \
 +
        ${tracknumber:+--track} ${tracknumber} \
 +
        ${title:+--song} ${title} \
 +
        ${album:+--album} ${album} \
 +
        ${date:+--year} ${date} \
 +
        ${genre:+--genre} ${genre} \
 +
        ${comment:+--comment} ${comment} \
 +
        $dest
 +
 
 +
  let nn=nn+1
 +
done
 +
 
 +
zenity --notification --text "Finished converting flac to mp3.${IFS}Processed ${nn} files."
 +
#zenity --info --text "Done!"
 +
IFS=${old_IFS}
 +
 
 +
</pre>
 +
 
 +
More such conversion scripts on pastebin.com [http://pastebin.com/u/woohoo here].
 +
 
 +
==More generic solution==
 +
 
 +
See [[Convert_Any_To_Mp3]] for a more generic solution if you want to transform to mp3 all kind of audio formats supported by both mplayer and mutagen.

Revision as of 07:13, 17 June 2013

Tip: You can use flac2mp3-bashAUR script from aur to convert Flac to Mp3 easily.

Introduction

Here is a script that will convert FLAC to MP3 via the commandline.

Essentially, the .flac files within a directory will be decompressed to .wav and then the resulting .wav files will be encoded to .mp3 using the latest LAME switches for encodings (-V 0 --vbr-new). The ID3 tags of the original .flac files will be passed to the resulting .mp3 files.

The original .flac files will not be harmed and the resulting .mp3s will be in the same directory. All other files in the directory (.nfo, images, .sfv, etc) will be ignored and unharmed.

For more information on LAME switches/settings such as V0, visit Hydrogenaudio LAME Wiki. V0 is roughly equivalent to --preset extreme which results in a variable bitrate usually between 220-260. The audio of a V0 is transparent, meaning one cannot tell the difference between the lossy file and the original source (compact disc/lossless), but yet the file size is a quite reasonable.

More information on flac: FLAC

Installation

First you need to install the following packages: flac, lame, and id3

pacman -S flac lame id3

Once those are installed, copy the following script into your preferred editor:

#! /bin/sh

for a in *.flac; do
    OUTF=${a%.flac}.mp3

    ARTIST=$(metaflac "$a" --show-tag=ARTIST | sed s/.*=//g)
    TITLE=$(metaflac "$a" --show-tag=TITLE | sed s/.*=//g)
    ALBUM=$(metaflac "$a" --show-tag=ALBUM | sed s/.*=//g)
    GENRE=$(metaflac "$a" --show-tag=GENRE | sed s/.*=//g)
    TRACKNUMBER=$(metaflac "$a" --show-tag=TRACKNUMBER | sed s/.*=//g)
    DATE=$(metaflac "$a" --show-tag=DATE | sed s/.*=//g)

    flac -c -d "$a" | lame -m j -q 0 --vbr-new -V 0 -s 44.1 - "$OUTF"
    id3 -t "$TITLE" -T "${TRACKNUMBER:-0}" -a "$ARTIST" -A "$ALBUM" -y "$DATE" -g "${GENRE:-12}" "$OUTF"
done

Below is a modified version of the above script which:

  • adds an optional parameter (-d), which, if passed on the command line, causes each source FLAC file to be deleted after successful conversion;
  • changes the LAME encoding options as follows:
    • drops --vbr-new, as it is the default VBR behaviour as of LAME 3.98, and thus is automatically used when "-V 0" is used;
    • drops "-m j", as LAME defaults to the specified value (joint stereo) when using --vbr-new (see above);
    • drops "-q 0", as LAME defaults to this behaviour when using VBR;
    • drops "-s 44.1", as LAME detects the proper sample rate to use;
    • adds "--noreplaygain" (personal preference);
  • and uses LAME to write tags instead of the id3 package, which has the dual advantage of removing the need for an additional package in the tool chain and allowing the script to write both id3v1 and id3v2 tags (the id3 package does not support id3v2 tags).

Now for the script:

#! /bin/sh

for a in *.flac; do
    OUTF=${a%.flac}.mp3

    ARTIST=`metaflac "$a" --show-tag=ARTIST | sed s/.*=//g`
    TITLE=`metaflac "$a" --show-tag=TITLE | sed s/.*=//g`
    ALBUM=`metaflac "$a" --show-tag=ALBUM | sed s/.*=//g`
    GENRE=`metaflac "$a" --show-tag=GENRE | sed s/.*=//g`
    TRACKNUMBER=`metaflac "$a" --show-tag=TRACKNUMBER | sed s/.*=//g`
    DATE=`metaflac "$a" --show-tag=DATE | sed s/.*=//g`

    flac -c -d "$a" | lame --noreplaygain -V0 \
        --add-id3v2 --pad-id3v2 --ignore-tag-errors --tt "$TITLE" --tn "${TRACKNUMBER:-0}" \
        --ta "$ARTIST" --tl "$ALBUM" --ty "$DATE" --tg "${GENRE:-12}" \
        - "$OUTF"
    RESULT=$?
    if [ "$1" ] && [ "$1" = "-d" ] && [ $RESULT -eq 0 ]; then
        rm "$a"
    fi
done

Alternatively, below is a script that will search for all FLAC audio files beyond where the script resides on your filesystem and convert them to MP3; including those pesky filenames with spaces.

#! /bin/bash

find . -type f -name "*.flac" -print0 | while read -d $'\0' a

do
    OUTF=${a%.flac}.mp3

    ARTIST=`metaflac "$a" --show-tag=ARTIST | sed s/.*=//g`
    TITLE=`metaflac "$a" --show-tag=TITLE | sed s/.*=//g`
    ALBUM=`metaflac "$a" --show-tag=ALBUM | sed s/.*=//g`
    GENRE=`metaflac "$a" --show-tag=GENRE | sed s/.*=//g`
    TRACKNUMBER=`metaflac "$a" --show-tag=TRACKNUMBER | sed s/.*=//g`
    DATE=`metaflac "$a" --show-tag=DATE | sed s/.*=//g`

    flac -c -d "$a" | lame -m j -q 0 --vbr-new -V 0 -s 44.1 - "$OUTF"
    id3 -t "$TITLE" -T "${TRACKNUMBER:-0}" -a "$ARTIST" -A "$ALBUM" -y "$DATE" -g "${GENRE:-12}" "$OUTF"
done

Save the script as flac2mp3 and make the script executable:

chmod a+x flac2mp3

As root, copy the script to /usr/local/bin (or anywhere else that is in your $PATH).

cp flac2mp3 /usr/local/bin

To make /usr/local/bin in your $PATH, do (as normal user):

PATH=$PATH:/usr/local/bin/

and then (as normal user):

nano .bashrc

and add export PATH=$PATH:/usr/local/bin/

Usage

Open up a terminal and cd to the directory of .flac files that you wish to convert and enter flac2mp3

You'll see the verbose decoding/encoding process in the terminal which may take a few moments.

Done.

Addendum

With a small modification the command file can be used to transcode the files into a new directory structure:

#! /bin/bash
find "$1" -name *.flac -print0 | while read -d $'\0' IF
do
  OF=$(echo "$IF" | sed -e 's/\.flac$/.mp3/g' -e "s,$1,$2,g")
  echo "$IF -> $OF"
  mkdir -p "${OF%/*}"

  ARTIST=`metaflac "$IF" --show-tag=ARTIST | sed s/.*=//g`
  TITLE=`metaflac "$IF" --show-tag=TITLE | sed s/.*=//g`
  ALBUM=`metaflac "$IF" --show-tag=ALBUM | sed s/.*=//g`
  GENRE=`metaflac "$IF" --show-tag=GENRE | sed s/.*=//g`
  TRACKNUMBER=`metaflac "$IF" --show-tag=TRACKNUMBER | sed s/.*=//g`
  DATE=`metaflac "$IF" --show-tag=DATE | sed s/.*=//g`

  flac -c -d "$IF" 2> /dev/null | lame -m j -q 0 --vbr-new -V 0 -s 44.1 - "$OF" 2> /dev/null
  id3 -t "$TITLE" -T "${TRACKNUMBER:-0}" -a "$ARTIST" -A "$ALBUM" -y "$DATE" -g "${GENRE:-12}" "$OF"
done

if saved in flac2mp3 this can be used as follows

./flac2mp3 /srv/media/music /srv/media/music-lofi

which will take the directory structure under /srv/media/music and transcode its content into /srv/media/music-lofi.

With some more tweaks the script will support directories that contain '.' (dots) somewhere in the path and executing the script from folders that contain 'flac' files

Also made specifying an alternate folder location optional

#! /bin/bash
find "$1" -name "*.flac" -print0 | while read -d $'\0' IF
do
  if [ "$2" != "" ]
  then
     OF="${IF%.flac}.mp3"
     OF="$2/${OF##*/}"
  else
     OF="${IF%.flac}.mp3"
  fi
  echo "$IF -> $OF"
  mkdir -p "${OF%/*}"

  ARTIST=`metaflac "$IF" --show-tag=ARTIST | sed s/.*=//g`
  TITLE=`metaflac "$IF" --show-tag=TITLE | sed s/.*=//g`
  ALBUM=`metaflac "$IF" --show-tag=ALBUM | sed s/.*=//g`
  GENRE=`metaflac "$IF" --show-tag=GENRE | sed s/.*=//g`
  TRACKNUMBER=`metaflac "$IF" --show-tag=TRACKNUMBER | sed s/.*=//g`
  DATE=`metaflac "$IF" --show-tag=DATE | sed s/.*=//g`

  flac -c -d "$IF" 2> /dev/null | lame -m j -q 0 --vbr-new -V 0 -s 44.1 - "$OF" 2> /dev/null
  id3 -t "$TITLE" -T "${TRACKNUMBER:-0}" -a "$ARTIST" -A "$ALBUM" -y "$DATE" -g "${GENRE:-12}" "$OF"
done

if saved in flac2mp3 this can be used as follows

./flac2mp3 /srv/media.store/music /srv/media/music-lofi

or

./flac2mp3 /srv/media.store/music 
Nautilus-scripts

Here's a well-written version of "flac2mp3" script which will run either from command line or, if you copy it into ~/.gnome2/nautilus-scripts, it will appear in the right-click menu in Nautilus:

#!/bin/bash
#
# Copyright 2008 Octavio Ruiz
# Distributed under the terms of the GNU General Public License v3
# $Header: $
#
# Yet Another FLAC to MP3 script
#
# Author:
# Octavio Ruiz (Ta^3) <tacvbo@tacvbo.net>
# Thanks:
# Those comments at:
# http://www.linuxtutorialblog.com/post/solution-converting-flac-to-mp3
# WebPage:
# https://github.com/tacvbo/yaflac2mp3/tree
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY. YOU USE AT YOUR OWN RISK. THE AUTHOR
# WILL NOT BE LIABLE FOR DATA LOSS, DAMAGES, LOSS OF PROFITS OR ANY
# OTHER KIND OF LOSS WHILE USING OR MISUSING THIS SOFTWARE.
# See the GNU General Public License for more details.
#
# Modified by woohoo
#
# you need zenity package for notifications.
# please note that you can put this script in ~/.gnome2/nautilus-scripts
# and it will show up in right-click menu in any folder in gnome.
#
# modify the lame options to your preference example change -b 320 to -b 128 or -b 192 or -b 256
# LAME_OPTS="--vbr-new -V 0 -b 256"
# LAME_OPTS="-V 0 --vbr-new"

LAME_OPTS="-b 320 -h --cbr"

old_IFS=${IFS}
IFS='
'

# when running from nautilus-scripts, it useful to find the current folder
base="`echo $NAUTILUS_SCRIPT_CURRENT_URI | cut -d'/' -f3- | sed 's/%20/ /g'`"
if [ -z "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS" ]; then
  dir="$base"
else
  while [ ! -z "$1" -a ! -d "$base/$1" ]; do shift; done
  dir="$base/$1"
fi

if [ "$dir" != "" ]; then
  cd "$dir"
fi

id3v2=$(which id3v2)

files=`find . -type f -regex '^.+\.flac$' | sort`

declare -i nn=0
for file in ${files}
do
  fn=$(readlink -f "$file")
  vars=( `metaflac --no-utf8-convert --export-tags-to=- "${fn}"` )

  for N_vars in ${!vars[@]}
  do
    export "$(echo "${vars[${N_vars}]%=*}" | tr [:upper:] [:lower:])=${vars[${N_vars}]#*=}"
  done

  dest=`echo "$fn"|sed -e 's/\.flac$/\.mp3/'`

  flac -dc "$fn" |\
    lame --ignore-tag-errors --add-id3v2 ${LAME_OPTS} \
        ${artist:+--ta} ${artist} \
        ${tracknumber:+--tn} ${tracknumber} \
        ${title:+--tt} ${title} \
        ${album:+--tl} ${album} \
        ${date:+--ty} ${date} \
        ${genre:+--tg} ${genre} \
        ${comment:+--tc} ${comment} \
        - $dest
 
    [[ -x ${id3v2} ]] && ${id3v2} \
        ${artist:+--artist} ${artist} \
        ${tracknumber:+--track} ${tracknumber} \
        ${title:+--song} ${title} \
        ${album:+--album} ${album} \
        ${date:+--year} ${date} \
        ${genre:+--genre} ${genre} \
        ${comment:+--comment} ${comment} \
        $dest

  let nn=nn+1
done

zenity --notification --text "Finished converting flac to mp3.${IFS}Processed ${nn} files."
#zenity --info --text "Done!"
IFS=${old_IFS}

More such conversion scripts on pastebin.com here.

More generic solution

See Convert_Any_To_Mp3 for a more generic solution if you want to transform to mp3 all kind of audio formats supported by both mplayer and mutagen.