Skip to content

Commit

Permalink
add Docker support
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-mc-work committed Feb 23, 2018
1 parent cc1ef9d commit 4ae83b7
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 107 deletions.
26 changes: 26 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
FROM whipper/whipper

# required env variables for the script
ENV BEETS_CONFIG=/config.albums-cover.yaml
ENV LOG_DIR=/logs
ENV OUTPUT_DIR=/output

USER root

# setup beets
RUN pip install beets \
&& apt-get install -y python-requests \
&& mkdir /home/worker/.config/beets && chown worker: /home/worker/.config/beets
COPY beets.yml /config.albums-cover.yaml
RUN chown worker: /config.albums-cover.yaml \
&& mkdir $LOG_DIR && chown worker: $LOG_DIR
VOLUME "$LOG_DIR"

# setup script
ENV SCRIPT_PATH=/auto-rip-audio-cd.sh
COPY auto-rip-audio-cd.sh $SCRIPT_PATH
RUN chmod +x $SCRIPT_PATH

USER worker

ENTRYPOINT ["/auto-rip-audio-cd.sh"]
145 changes: 111 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,137 @@
# Most possible unattended rip workflow
# Most Possible Unattended Rip Workflow

This is a script that allows you to quickly rip a large collection of audio cd's only with the minimum of manual intervention: __insert cd - remove cd__!
This project allows you to quickly rip a large collection of audio CD's only with the minimum of manual intervention: __insert cd - remove cd__

## Structure

This project comprises three parts:
This project comprises two components:

1. A __shell script__:
- rip a cd with [whipper](https://github.com/JoeLametta/whipper) (fka. morituri) with a very low cpu and storage usage priority
- fall back to abcde if that fails
- automatic atgging and naming
- grab the cover art
- eject the cd
1. A shell script for the actual process:

2. (optional) A __udev rule__ to automatically run the shell script when a cd is being inserted.
- riping, tagging and naming a CD using [whipper](https://github.com/JoeLametta/whipper)
- grab the cover art using [beets](http://beets.io/)
- eject the CD

3. (optional) A __config file__ which lets you do some decision regarding the shell script.

All steps within the script are well documented which makes it easy to customize it to any special needs. Furthermore this makes it easy for beginners to understand each step.
2. (optional) __UDEV Integration__: A UDEV rule to automatically run the shell script when a CD is being inserted.

## Installation

1. Simply download the shell script and give it the executable flag:

`wget https://github.com/thomas-mc-work/most-possible-unattended-rip/auto-rip-audio-cd.sh && chmod +x auto-rip-audio-cd.sh`

1b. If you like to use have the script grabbing the cover for you then you need to install [beets](http://beets.io/) (`pip install beets`) and place a special config only for the cover grabbing process into `$HOME/.config/beets/config.albums-cover.yaml`:

import:
copy: no
write: no

plugins: fetchart
First you need to download and extract the project:

curl -L https://github.com/thomas-mc-work/most-possible-unattended-rip/archive/master.tar.gz | tar xz
cd most-possible-unattended-rip-master

### Docker

At the moment it's required to build the whipper image yourself as the official Docker support is not yet integrated (https://github.com/JoeLametta/whipper/pull/237).

git clone https://github.com/thomas-mc-work/whipper.git
cd whipper
git checkout -b dockerfile
docker build -t whipper/whipper .
# remove the sources again
cd ..
rm -rf whipper

#### Build The Image

docker build -t tmcw/mpur .

#### Run The Container

[ ! -d config ] && mkdir config
[ ! -d logs ] && mkdir logs
[ ! -d output ] && mkdir output

docker run --rm \
--device=/dev/cdrom \
-v "${PWD}/config":/home/worker/.config/whipper \
-v "${PWD}/logs":/logs \
-v "${PWD}/output":/output \
tmcw/mpur

### Native

# Mark the script executable
chmod +x auto-rip-audio-cd.sh
# Install beets via pip
pip install --user beets
# Add the beets configuration
curl -Lo "${HOME}/.config/beets/config.albums-cover.yaml https://raw.githubusercontent.com/thomas-mc-work/most-possible-unattended-rip/master/beets.yml

Now you can simply execute the script after inserting th audio CD:

./auto-rip-audio-cd.sh

2. (optional) Add a udev rule to automatically trigger the script:
### UDEV Integration

`echo "SUBSYSTEM==\"block\", SUBSYSTEMS==\"scsi\", KERNEL==\"sr?\", ENV{ID_TYPE}==\"cd\", ENV{ID_CDROM}==\"?*\", ENV{ID_CDROM_MEDIA_TRACK_COUNT_AUDIO}==\"?*\", ACTION==\"change\", RUN+=\"/bin/su -lc '<path-to-script>/auto-rip-audio-cd.sh' <username>\"" | sudo tee 80-audio-cd.rules`
Add a UDEV rule to automatically trigger the script:

It's important here to replace `<username>` and `<path-to-script>` with the appropriate values. The script will be run with the according user permissions. This is important to get the correct locale settings in the environment.
echo "SUBSYSTEM==\"block\", SUBSYSTEMS==\"scsi\", KERNEL==\"sr?\", ENV{ID_TYPE}==\"cd\", ENV{ID_CDROM}==\"?*\", ENV{ID_CDROM_MEDIA_TRACK_COUNT_AUDIO}==\"?*\", ACTION==\"change\", RUN+=\"/bin/su -lc '<path-to-script>/auto-rip-audio-cd.sh' <username>\"" | sudo tee 80-audio-cd.rules

3. (optional) Download the config file template into your profiles config (`$HOME/.config`) folder:
Just be sure to substitude the placeholders `<username>` and `<path-to-script>` by the appropriate values. The script will be run with the according user permissions. This is important to get the correct locale settings in the environment.

`wget https://github.com/thomas-mc-work/most-possible-unattended-rip/auto-rip.cfg -O $HOME/.config/auto-rip.cfg`
**Config File To Control The UDEV Automatism**

These options are available:
Create a config file in your profiles config (`$HOME/.config`) folder:

If you want to use a config file then you're required to create an intermediate shell script that is invoked by the UDEV rule:

#!/usr/bin/env bash

# end previous shutdown if one is active
sudo shutdown -c

# marker file for skipping the automated ripping
CONFIG_FILE="${HOME}/.config/auto-rip.cfg"

# include config file
if [ -f "$CONFIG_FILE" ]; then
. "$CONFIG_FILE"
fi

# optionally omit the process by config setting
if [ "$DISABLED" = 1 ]; then
echo "# omitting auto rip due to config setting"
exit 0
fi

nice -n 19 ionice -c 3 /path/to/auto-rip-audio-cd.sh

# reread the config file to include a late shutdown decision
if [ -f "$CONFIG_FILE" ]; then
. "$CONFIG_FILE"
fi

# optionally shutdown after a short delay
if [ "$SHUTDOWN" = 1 ]; then
echo "# shutting down the system"
if ! [[ $SHUTDOWN_TIMEOUT =~ ^[0-9]+$ ]]; then SHUTDOWN_TIMEOUT=3; fi
sudo shutdown -h $SHUTDOWN_TIMEOUT
fi


The config file:

# disable auto ripping?
DISABLED=0
# shutdown after finish?
SHUTDOWN=0
# shutdown timeout in minutes
SHUTDOWN_TIMEOUT=3

These options are available:

- `DISABLED={0,1}`: Disable the script. Good if you like listen to some music CDs without instantly ripping them
- `SHUTDOWN={0,1}`: You can choose whether to automatically shutdown the system ofter the rip process has finished. This is good e.g. when going to bed and letting the system finish the last CD by itself. For using this you need to have the permission to shutdown the system via the command line. You can achieve this by inserting `%sudo ALL = NOPASSWD: /sbin/shutdown` into `/etc/sudoers`.
- `SHUTDOWN_TIMEOUT=3`: Lets you define the shutdown timeout
- `SHUTDOWN_TIMEOUT=<value>`: Lets you define the shutdown timeout

## Links

- [whipper](https://github.com/JoeLametta/whipper)
- [good explanations and debug help with udev on arch wiki](https://wiki.archlinux.org/index.php/udev)
- [beets](http://beets.io/)
- [abcde best of breed configuration](http://www.andrews-corner.org/linux/abcde/index.html)
- [let abcde grab album art](http://www.andrews-corner.org/linux/abcde/getalbumart.html)

Any comments, questions or PRs are very welcome!
---

**Any comments, questions or PRs are very welcome!**
96 changes: 29 additions & 67 deletions auto-rip-audio-cd.sh
Original file line number Diff line number Diff line change
@@ -1,91 +1,53 @@
#!/usr/bin/env bash
# automatisches rippen einer audio-cd
# https://github.com/JoeLametta/whipper
# Vorbereitung morituri:
# # rip offset find
# # rip drive analyze
# Automated rip process of an audio CD.
set -u

LOG_DIR="$HOME/logs/audio-rip"
OUTPUT_DIR="$HOME/rip"
log_dir=${LOG_DIR:-"$HOME/logs/audio-rip"}
output_dir=${OUTPUT_DIR:-"$HOME/rip"}
beets_config=${BEETS_CONFIG:-"$HOME/.config/beets/config.albums-cover.yaml"}

# ============
log_file="${log_dir}/rip-$(date +%Y-%m-%dT%H-%M-%S).log"

LOG_FILE="$LOG_DIR/rip-$(date +%Y-%m-%dT%H-%M-%S).log"
fn_log () {
echo "### $*" | tee -a "$log_file"
}

# end previous shutdown if one is active
sudo shutdown -c

# marker file for skipping the automated ripping
CONFIG_FILE="${HOME}/.config/auto-rip.cfg"

# include config file
if [ -f "$CONFIG_FILE" ]; then
. "$CONFIG_FILE"
fi

# optionally omit the process by config setting
if [ "$DISABLED" = 1 ]; then
echo "# omitting auto rip due to config setting" | tee -a "$LOG_FILE"
exit 0
fi

echo "# auto rip started" | tee -a "$LOG_FILE"
fn_log "auto rip started"

# PYTHONIOENCODING: workaround for an issue: https://github.com/JoeLametta/whipper/issues/43
nice -n 19 ionice -c 3 whipper cd rip --output-directory="$OUTPUT_DIR" -U true >>"$LOG_FILE" 2>&1
SC=$?
echo "# auto rip finished" | tee -a "$LOG_FILE"
export PYTHONIOENCODING="utf-8"
whipper cd rip --output-directory="$output_dir" -U >> "$log_file" 2>&1
sc_whipper=$?

# grab the cover art
if [ $SC == 0 ]; then
if [ $sc_whipper == 0 ]; then
fn_log "whipper rip finished"

# replace the carriage returns with proper line breaks and search for the output pattern
FOLDER_LINE=$(tr '\015' "\n" < "${LOG_FILE}" | grep "utput directory")
echo "# folder line: $FOLDER_LINE" >> "${LOG_FILE}"
folder_line=$(tr '\015' "\n" < "$log_file" | grep "utput directory")

if [ "$FOLDER_LINE" == "" ]; then
echo "# result: success (but couldn't find output folder for fetching cover art)" | tee -a "$LOG_FILE"
if [ -z "$folder_line" ]; then
fn_log "result: success (but couldn't find output folder for fetching cover art)"
else
# remove the search pattern
FOLDER=${FOLDER_LINE/Creating output directory /}
echo "# output path: $FOLDER" >> "${LOG_FILE}"
output_path=${folder_line/Creating output directory /}
fn_log "output path: $output_path"

# if you have beets then grab image with beets
# can be removed once this is closed: https://github.com/JoeLametta/whipper/issues/50
# Use beets for image grabbing if it is available.
# Can be removed once this is implemented: https://github.com/JoeLametta/whipper/issues/50
if type beet >/dev/null 2>&1; then
# -l: discard all additions to the library
# -c: path to the config file
# import: normally you import the file here and grab the cover alongside
# -q: quiet - don't ask for user input. Either it works or forget about it
beet -l /dev/null -c "$HOME/.config/beets/config.albums-cover.yaml" import -q "$FOLDER" >> "${LOG_FILE}"
echo "# result: success" | tee -a "$LOG_FILE"
echo a | beet -c "$beets_config" import "$output_path" >> "$log_file"
sc_beets=$?
fn_log "beet result: ${sc_beets}"
exit $sc_beets
fi
fi
else
echo "# result: no success with whipper/morituri: status code = ${SC}" | tee -a "$LOG_FILE"

# if you have abcde then use it as fallback
if type abcde >/dev/null 2>&1; then
echo "# trying abcde" | tee -a "$LOG_FILE"
abcde | tee -a "$LOG_FILE"
SC=$?

if [ $SC == 0 ]; then
echo "# result: success with abcde" | tee -a "$LOG_FILE"
eject
else
echo "# result: no success with abcde: status code = ${SC}" | tee -a "$LOG_FILE"
fi
fi
fn_log "failed to rip: ${sc_whipper}"
exit $sc_whipper
fi

# reread the config file to include a late shutdown decision
if [ -f "$CONFIG_FILE" ]; then
. "$CONFIG_FILE"
fi

# optionally shutdown after a short delay
if [ "$SHUTDOWN" = 1 ]; then
echo "# shutting down the system" | tee -a "$LOG_FILE"
if ! [[ $SHUTDOWN_TIMEOUT =~ ^[0-9]+$ ]]; then SHUTDOWN_TIMEOUT=3; fi
sudo shutdown -h $SHUTDOWN_TIMEOUT | tee -a "$LOG_FILE"
fi
6 changes: 0 additions & 6 deletions auto-rip.cfg

This file was deleted.

7 changes: 7 additions & 0 deletions beets.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
library: /dev/null

import:
copy: no
write: no

plugins: fetchart
5 changes: 5 additions & 0 deletions docker-build-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env sh
set -o nounset ## set -u : exit the script if you try to use an uninitialised variable
set -o errexit ## set -e : exit the script if any statement returns a non-true return value

docker build -t tmcw/mpur:0.6-1 -t tmcw/mpur:latest .

0 comments on commit 4ae83b7

Please sign in to comment.