abcdeで音楽CDからCue, FLAC, M4A, Opusを一括生成する
linuxで音楽CDのリッピングをしたい場合、abcde 1 が大変便利である。このツールはCDDB 2 からのアルバム情報 (タイトル、発表年、曲名等) の取得、WAVファイルの読取、各種音声フォーマットへのエンコード、ID3タグの付与、等々を一度に自動的に行ってくれる大変便利なものである。また、コンソール上で全て操作できるのがうれしい。
abcde は十分に便利なため、基本的にはそのまま使えば大抵のことはできてしまうはずだが、今回、私は以下の要件が満たしかったため、少しハックして利用することにした。本記事ではそのスクリプトを掲載する。
- CDDB情報は自分で1度だけ入力
- CDDB情報はCueとして残す
- 音楽CDの音声データ全体を1つのファイルとしてFLACファイルにする
- トラック毎に分割した音声ファイルも生成する
- トラック毎の音声ファイルはFLAC, M4A, Opusエンコードを生成する
- 最後は作業ファイルを削除する
そのままの abcde では 3 と 4 を同時に処理できないため、abcde を2回実行するようにした。abcde 音声CDデバイスから音声ファイルを抽出する機能 (abcde -d /dev/cdrom
のようにする) の他、その代わりに指定した FLAC ファイルから音声ファイルを読み出す機能 (abcde -d single.flac
のようにする) があるため、前者を実行してから後者を実行すればよい。ただし、1回目の実行時のデータを残したまま2回目を実行しても、1回目の実行ログが邪魔して2回目の処理はスキップされてしまう。かと言って1回目の実行後、実行データを消去するようにすると、2回目でまたCDDB情報の入力を求められてしまい、これも面倒。そこで1回目の後、実行ログの一部を強引に書き換えて2回目を行うこととした。
abcde 設定ファイル
abcde の動作はコマンドラインオプションで制御可能だが、設定ファイルによっても変更することができる。設定ファイル名はデフォルトで ~/.abcde.conf
が使われるが、今回は2個の設定ファイルを用意したため、1回目用を abcde.single.conf
、2回目用を abcde.tracks.conf
とした。これらの設定ファイルは abcde 実行時に -c
オプションで指定することができる。
各種ファイルの内容は以下の通り:
abcde.single.conf:
INTERACTIVE=y
ACTIONS=cddb,getalbumart,cue,read,encode,tag,move
CDROM=/dev/cdrom
OUTPUTDIR=/mnt
OUTPUTTYPE=flac
ONETRACKOUTPUTFORMAT='output'
EJECT=y
abcde.tracks.conf:
ACTIONS=cddb,cue,read,encode,tag,move,clean
OUTPUTDIR=/mnt
OUTPUTTYPE=flac,m4a,opus
OUTPUTFORMAT='${ARTISTFILE}/${ALBUMFILE}/${TRACKNUM} - ${TRACKFILE}'
各種設定項目についての説明は面倒臭いから割愛する。
デフォルトの設定は /etc/abcde.conf
に書いてある。
abcde を2回実行するスクリプト
ripcd.sh を実行することで2回の abcde 実行を自動化した。また、先に述べた、1回目の実行ログを書き換える処理もこの中で行う:
#!/bin/sh
ABCDE=abcde
SINGLECONF=abcde.single.conf
TRACKSCONF=abcde.tracks.conf
WAV=/mnt/output.flac
help() {
script=$(basename $0)
cat <<EOF
Usage: $script [-f flac]
EOF
}
while [ $# != 0 ]; do
case $1 in
-f|--flac)
WAV="$2"
shift 2
;;
*)
help
exit 1
esac
done
CUE="$WAV".cue
ensure_requirements() {
if [ ! $(which $ABCDE) ]; then
echo "Error, $ABCDE needs to be installed."
exit 1
fi
}
artist_in_cue() {
cue=$1
artist=$(grep PERFORMER $cue | sed -e 's/PERFORMER "\(.*\)"$/\1/')
echo $artist
}
title_in_cue() {
cue=$1
title=$(grep TITLE $cue | sed -e 's/TITLE "\(.*\)"$/\1/' | head -1)
echo $title
}
ensure_requirements
if [ ! -f "$WAV" ]; then
$ABCDE -1 -c abcde.single.conf
if [ $? != 0 ]; then
echo "Failed to ripping tracks."
exit
fi
fi
for f in $(ls abcde.*/status); do
echo "Reset last status: $f"
sed -i -e 's/onetrack//g' $f
sed -i -e 's/.*track-01.*//g' $f
done
$ABCDE -c abcde.tracks.conf -d "$WAV"
if [ $? != 0 ]; then
echo "Failed to create tracks."
exit
fi
ARTIST=$(artist_in_cue "$CUE")
TITLE=$(title_in_cue "$CUE")
echo "Ripping done."
echo " Artist: $ARTIST"
echo " Title: $TITLE"
if [ -f "$CUE" ]; then
NEWCUE=$(dirname $CUE)/"$ARTIST - $TITLE.cue"
mv "$CUE" "$NEWCUE"
fi
NEWWAV=$(dirname "$WAV")/"$ARTIST - $TITLE.flac"
mv "$WAV" "$NEWWAV"
Docker 上で動作させる
さらに、PCの環境を清潔に保つため、Docker コンテナ上で動作するように作成した。 この手のメディア系のプログラムは多くのエンコーダライブラリ等が必要なため、素のOS環境上で実行しようとすると色々とインストールすることになり、作業環境が複雑になるため個人的に好まない。コンテナ様々である。
Dockerfile は以下:
FROM ubuntu:latest
VOLUME ["/mnt"]
ENV DEBIAN_FRONTEND=noninteractive
ENV EDITOR=vim
ENV LANG=C.UTF-8
RUN apt-get -y update
RUN apt-get install -y abcde mkcue flac fdkaac opus-tools eject vim
RUN groupadd -g 11 cdrom2
RUN groupadd -g 1000 user
RUN useradd -u 1000 -g user -G root,cdrom2 -d /home/user -m -s /bin/bash user
WORKDIR /home/user
COPY ripcd.sh .vimrc abcde.single.conf abcde.tracks.conf /home/user/
RUN chown user:user -R /home/user
RUN chmod u+x ripcd.sh
USER user
GID:11, 1000 や UID:1000 は必要に応じ各自ホスト側の環境に合わせる必要がある。
上記の Dockerfile では、ホストの普段使いのユーザーが UID:1000, GID:1000 であるとしている。また、/dev/cdrom
のアクセス権限が GID:11 としている。
出力されるファイルが root パーミッションになっても気にしないのならば、RUN groupadd
、RUN useradd
、RUN chown user:user
、USER user
の行を削除すると簡単に動く。
Dockerコンテナ起動スクリプト
Dockerイメージのビルドとコンテナの起動もコマンド一発でできるよう、以下のスクリプトを用意した。
起動スクリプト:
fujii@fg-ryz ~/D/p/ripcd> cat start.sh
#!/bin/sh
IMAGE=ripcd
REBUILD_IMAGE=0
help() {
script=$0
cat <<EOF
$script [-r]
Options:
-r Force rebuild docker image
EOF
}
while [ $# != 0 ]; do
case $1 in
-r)
REBUILD_IMAGE=1
shift
;;
*)
help
exit 1
;;
esac
done
if [ $(docker images | grep $IMAGE | wc -l) == 0 ]; then
REBUILD_IMAGE=1
fi
if [ $REBUILD_IMAGE != 0 ]; then
docker build -t ripcd .
if [ $? != 0 ]; then
echo "Failed build docker image."
exit 1
fi
fi
docker run -ti --rm \
--device /dev/cdrom \
-v $HOME/Music/rip:/mnt \
ripcd ./ripcd.sh
実行例:
$ sh start.sh