Skip to content

Commit

Permalink
adapt to dockerized whipper
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-mc-work committed Mar 11, 2019
1 parent 4ae83b7 commit 80a9a06
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 80 deletions.
27 changes: 12 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
FROM whipper/whipper
FROM joelametta/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 beets, dependency munkres supports python2 up to 1.0.12
RUN pip install --quiet beets munkres==1.0.12 \
&& apt-get install -yqq python-requests \
&& mkdir /home/worker/.config/beets && chown worker: /home/worker/.config/beets \
&& mkdir -p -- "$LOG_DIR" \
&& chown worker: "$LOG_DIR"
COPY --chown=worker:worker beets.yml /home/worker/.config/beets/config.yaml

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

VOLUME "$LOG_DIR"
USER worker

ENTRYPOINT ["/auto-rip-audio-cd.sh"]
114 changes: 71 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,81 +1,109 @@
# Most Possible Unattended Rip Workflow

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__
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 two components:

1. A shell script for the actual process:
1. A wrapper shell script for:

- riping, tagging and naming a CD using [whipper](https://github.com/JoeLametta/whipper)
- grab the cover art using [beets](http://beets.io/)
- ripping and tagging (using [whipper](https://github.com/whipper-team/whipper))
- grab the cover art (using [beets](http://beets.io/))
- eject the CD

2. (optional) __UDEV Integration__: A UDEV rule to automatically run the shell script when a CD is being inserted.
2. (optional) A [udev](https://en.wikipedia.org/wiki/Udev) rule to automatically run the shell script when a CD is
being inserted

## Installation
## Installation (Docker based)

First you need to download and extract the project:
It's the easiest way to run this project using docker. However it's still possible to only use the script
`auto-rip-audio-cd.sh`.

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

# feel free do change these values
config_dir="$HOME/.config/whipper"
log_dir="$PWD/logs"
output_dir="$PWD/output"

[ ! -d "$config_dir" ] && mkdir -p "$config_dir"
[ ! -d "$log_dir" ] && mkdir -p "$log_dir"
[ ! -d "$output_dir" ] && mkdir -p "$output_dir"

### Build The Container

### Docker
# grab the project
curl -L https://github.com/thomas-mc-work/most-possible-unattended-rip/archive/master.tar.gz | tar xz

# build the container
docker build -t tmcw/mpur most-possible-unattended-rip-master

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).
## Usage

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
### Initial drive setup

#### Build The Image
First you're required to create a drive specific config file using whipper:

docker build -t tmcw/mpur .
docker run --rm \
--device=/dev/cdrom \
-v "$config_dir:/home/worker/.config/whipper" \
joelametta/whipper drive analyze

#### Run The Container
This is only required once for each drive.

[ ! -d config ] && mkdir config
[ ! -d logs ] && mkdir logs
[ ! -d output ] && mkdir output
### Run The Container

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

### Native
It's recommended to put this command into a shell script (e.g. `$HOME/bin/mpur.sh`)

# Mark the script executable
chmod +x auto-rip-audio-cd.sh
## Classical Setup

### Installation

# prepare the folders by convention
mkdir -p "${HOME}/bin" "${HOME}/.config/beets"
# Install the script and make it executable
curl -Lo "${HOME}/bin/mpur.sh" "https://raw.githubusercontent.com/thomas-mc-work/most-possible-unattended-rip/master/auto-rip-audio-cd.sh"
chmod +x "${HOME}/bin/mpur.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
curl -Lo "${HOME}/.config/beets/config.yaml" "https://raw.githubusercontent.com/thomas-mc-work/most-possible-unattended-rip/master/beets.yml"

### Usage

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

./auto-rip-audio-cd.sh
$ mpur.sh

### UDEV Integration
#### Parameters

Add a UDEV rule to automatically trigger the script:
- `LOG_DIR`: override the default log files path (`$HOME/logs/audio-rip`)
- `BEETS_CONFIG`: override the default beets config file path (`$HOME/.config/beets/config.yaml`)

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
## udev Integration

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.
Add a udev rule to automatically trigger the script:

**Config File To Control The UDEV Automatism**
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 '/home/<username>/bin/mpur.sh' <username>\"" | sudo tee 80-audio-cd.rules

Just be sure to substitute the placeholder `<username>` (or the entire script path) by the appropriate value. The script
will be run with the according user permissions. This is important to get the correct locale settings in the environment.

### Config File Extension

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:
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 (e.g. `$HOME/bin/mpur-wrapper.sh):

#!/usr/bin/env bash

Expand All @@ -96,7 +124,7 @@ If you want to use a config file then you're required to create an intermediate
exit 0
fi

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

# reread the config file to include a late shutdown decision
if [ -f "$CONFIG_FILE" ]; then
Expand All @@ -110,7 +138,6 @@ If you want to use a config file then you're required to create an intermediate
sudo shutdown -h $SHUTDOWN_TIMEOUT
fi


The config file:

# disable auto ripping?
Expand All @@ -123,7 +150,8 @@ The config file:
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={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=<value>`: Lets you define the shutdown timeout

## Links
Expand All @@ -134,4 +162,4 @@ These options are available:

---

**Any comments, questions or PRs are very welcome!**
**Any comments, questions or pull requests are very welcome!**
40 changes: 21 additions & 19 deletions auto-rip-audio-cd.sh
Original file line number Diff line number Diff line change
@@ -1,53 +1,55 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
# Automated rip process of an audio CD.
set -u
set -o nounset ## set -u : exit the script if you try to use an uninitialised variable

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"}
beets_config=${BEETS_CONFIG:-"$HOME/.config/beets/config.yaml"}

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

fn_log () {
echo "### $*" | tee -a "$log_file"
}

fn_log "auto rip started"
fn_log "starting rip process with whipper"

# PYTHONIOENCODING: workaround for an issue: https://github.com/JoeLametta/whipper/issues/43
export PYTHONIOENCODING="utf-8"
whipper cd rip --output-directory="$output_dir" -U >> "$log_file" 2>&1
whipper cd rip --unknown 2>&1 | tee -a "$log_file"
sc_whipper=$?

# grab the cover art
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")
if [ $sc_whipper = 0 ]; then
# example line:
# INFO:whipper.image.cue:parsing .cue file u'unknown/Unknown Artist - m3JTAxsMcVKGGAiW6CKcaYJ5TG8-/Unknown Artist - m3JTAxsMcVKGGAiW6CKcaYJ5TG8-.cue'
pattern="INFO:whipper\.image\.cue:parsing \.cue file u'.*.cue'"

if [ -z "$folder_line" ]; then
fn_log "result: success (but couldn't find output folder for fetching cover art)"
else
# replace the carriage returns with proper line breaks and search for the output pattern
if cue_file_line=$(tr '\015' "\n" < "$log_file" | grep -E "$pattern"); then
# remove the search pattern
output_path=${folder_line/Creating output directory /}
cue_file=$(echo $cue_file_line | sed "s/.*'\(.*\)'/\1/")
output_path=$(dirname "$cue_file")
fn_log "output path: $output_path"

# 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
fn_log "fetching cover art using beets"
# -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
echo a | beet -c "$beets_config" import "$output_path" >> "$log_file"
sc_beets=$?
fn_log "beet result: ${sc_beets}"
exit $sc_beets
exit $?
else
fn_log "failed to find beets to fetch the cover art"
fi
else
fn_log "result: success (but couldn't find output folder for fetching cover art)"
fi
else
fn_log "failed to rip: ${sc_whipper}"
fn_log "whipper failed with status code ${sc_whipper}"
exit $sc_whipper
fi

4 changes: 1 addition & 3 deletions beets.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
library: /dev/null

import:
copy: no
write: no

plugins: fetchart
plugins: fetchart

0 comments on commit 80a9a06

Please sign in to comment.