diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8984217 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +FROM debian + + +RUN true \ + && groupadd -g 911 linuxserver \ + && useradd -u 911 -g linuxserver -G cdrom linuxserver \ + && sed -i 's/main$/main contrib non-free/' /etc/apt/sources.list \ + && apt-get -y update \ + && DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -y install \ + ffmpeg \ + handbrake-cli libavcodec-extra \ + abcde eyed3 \ + glyrc setcd eject \ + dvdbackup \ + libdvd-pkg libdvdcss2 \ + python3 \ + cowsay \ + && true +RUN dpkg-reconfigure libdvd-pkg + +RUN true \ + && DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -y install \ + lame \ + procps \ + cowsay + +COPY scripts /scripts +COPY abcde.conf /etc/ +USER linuxserver +ENTRYPOINT ["/scripts/init.sh"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..67e39c8 --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +The Media Sucker +================ + +This program watches your CD/DVD drive. +When you put a CD or DVD in, +it will suck the content off, +eject the drive, +and then re-encode the content to a compressed format. + +## What It Supports + +At the time I'm writing this README, it will: + +* Rip audio CDs, look them up in cddb, encode them to VBR MP3, then tag them. +* Rip video DVDs, transcode them to mkv + +## How To Run This + +First you have to build it. +It will build on a raspberry pi. + + docker build --tag=media-sucker . + +You'll need a place to store all your precious media: + + incoming=/path/to/incoming + mkdir -P $incoming + chown 911:911 $incoming + +Then you can run it: + + docker run -d --restart=unless-stopped \ + --name=sucker \ + --device cdrom --device dvd --device sr0 \ + -v $incoming:/incoming \ + media-sucker + +Or you can put it in a `docker-compose.yaml` file: + +```yaml +services: + sucker: + image: media-sucker + volumes: + - type: bind + source: /path/to/incoming + target: /incoming +``` + +Stick a video DVD or audio CD in, +and the drive should spin up for a while, +then spit your media back out. +Then, eventually, you'll have a new `.mkv` file (for video) +or a new directory of `.mp3` files (for audio). + +You can watch what it's doing: + + docker logs --since=1m -f sucker + +## A note on filenames and tags + +This program does the absolute minimum to try and tag your media properly. + +For DVDs, that means reading the "title" stored on the DVD, +which I've seen vary from very helpful (eg. "Barbie A Fashion Fairytale") +to ridiculously unhelpful (eg. "FBWTF2"). +But at least it's usually unique for each DVD and at least somewhat +related to the DVD contents. + +For CDs, the situation is even worse. +Audio CDs do not store any metadata, +so CDDB takes the length of every track in seconds and tries to match that +against something a user has uploaded in the past. +This is wrong a whole lot of the time. + +If CDDB can't find a match for an audio CD, +this program will append the datestamp of the rip to the album name, +in the hopes that you can remember about what time you put each CD in the drive. +So for stuff like multi-CD audiobooks, that's pretty helpful. + +But the end result in almost every case is that you're going to have to +manually edit the metadata. + +## Why I Wrote This + +The `automatic-ripping-machine` looks really badass. +I spent about two days trying to get a Docker container built for it, +and another day trying to get it to actually read my drive. +I got it reading the drive exactly once, and then never again. + +That's when I gave up and created my own thing, +which is pretty janky, +but works a lot better for me, +in that it actually does something. + +### Why You Should Run This + +The only reason I can think of that anybody would want to use this is if they, +like me, +are too dumb to get the `automatic-ripping-machine` to work. diff --git a/abcde.conf b/abcde.conf new file mode 100644 index 0000000..78bf81b --- /dev/null +++ b/abcde.conf @@ -0,0 +1,2 @@ +OUTPUTFORMAT='${OUTPUT}/${ARTISTFILE}/${ALBUMFILE}/${TRACKNUM} - ${TRACKFILE}' +VAOUTPUTFORMAT='Various/${ALBUMFILE}/${TRACKNUM} - ${ARTISTFILE}-${TRACKFILE}' diff --git a/scripts/audio.encode.sh b/scripts/audio.encode.sh new file mode 100755 index 0000000..865bae8 --- /dev/null +++ b/scripts/audio.encode.sh @@ -0,0 +1,10 @@ +#! /bin/sh + +. /scripts/common.sh + +. ./env + +abcde -C $discid -o mp3:-V2 +cp -r mp3/* $OUTDIR + +# vi: sw=2 ts=2 et ai diff --git a/scripts/cd.audio.read.sh b/scripts/cd.audio.read.sh new file mode 100755 index 0000000..902a4ec --- /dev/null +++ b/scripts/cd.audio.read.sh @@ -0,0 +1,15 @@ +#! /bin/sh + +abcde -N -a cddb,read + +discid=$(cd-discid | awk '{print $1}') + +cat <env +mtype=cd +discid=$discid +EOD + +now=$(date +%Y%m%d.%H%M%S) +sed -i s/'Unknown Album$'/"Unknown Album $now"/ abcde.$discid/cddbread.0 + +# vi: sw=2 ts=2 et ai diff --git a/scripts/common.sh b/scripts/common.sh new file mode 100755 index 0000000..82cc332 --- /dev/null +++ b/scripts/common.sh @@ -0,0 +1,9 @@ +#! /bin/sh + +log () { + printf "\033[36m=== [%s] \033[0m %s\n" "$0" "$*" +} + +# If you haven't set OUTDIR, set it to the default +: ${OUTDIR:=/incoming} +export OUTDIR diff --git a/scripts/dvd.video.read.sh b/scripts/dvd.video.read.sh new file mode 100755 index 0000000..7354af7 --- /dev/null +++ b/scripts/dvd.video.read.sh @@ -0,0 +1,16 @@ +#! /bin/sh -e + +. /scripts/common.sh + +log "Scanning for DVD title" +title=$(dvdbackup -I | awk -F \" '/DVD with title/ {print $2}') + +log "DVD Title: $title" + +cat <env +mtype=dvd +title="$title" +EOD + +dvdbackup -p -M -n DVD + diff --git a/scripts/encoder.sh b/scripts/encoder.sh new file mode 100755 index 0000000..a255766 --- /dev/null +++ b/scripts/encoder.sh @@ -0,0 +1,29 @@ +#! /bin/sh + +. /scripts/common.sh + +run_in () { + ( + cd $1; shift + "$@" + ) +} + +while sleep 2; do + for mtype in audio video; do + ls $mtype | while read d; do + encode=/scripts/$mtype.encode.sh + workdir=$mtype/$d + [ -f $workdir/read.finished ] || continue + + log "Encoding $workdir" + if ! run_in $workdir $encode; then + log "$encode failed" + else + rm -rf $workdir + fi + done + done +done + +# vi: ts=2 sw=2 et ai diff --git a/scripts/init.sh b/scripts/init.sh new file mode 100755 index 0000000..eb2917e --- /dev/null +++ b/scripts/init.sh @@ -0,0 +1,10 @@ +#! /bin/sh -e + +cd /incoming + +mkdir -p audio video + +nice /scripts/reader.sh & +nice /scripts/encoder.sh & + +wait diff --git a/scripts/reader.sh b/scripts/reader.sh new file mode 100755 index 0000000..add4e57 --- /dev/null +++ b/scripts/reader.sh @@ -0,0 +1,34 @@ +#! /bin/sh + +. /scripts/common.sh + +with_time_dir () { + mtype=$1; shift + now=$(date --rfc-3339=s | tr ' ' T) + mkdir -p $mtype/$now + cd $mtype/$now + if ! "$@"; then + log "$1 failed" + else + log "$1 succeeded" + touch read.finished + eject + fi +} + +while sleep 2; do + case $(setcd -i) in + *"Disc found in drive: audio"*) + log "Found audio disc" + ( with_time_dir audio /scripts/cd.audio.read.sh ) + ;; + *"Disc found in drive: data"*) + log "Found DVD" + ( with_time_dir video /scripts/dvd.video.read.sh ) + ;; + *) + ;; + esac +done + +# vi: sw=2 ts=2 et ai diff --git a/scripts/video.encode.sh b/scripts/video.encode.sh new file mode 100755 index 0000000..050e278 --- /dev/null +++ b/scripts/video.encode.sh @@ -0,0 +1,15 @@ +#! /bin/sh -e + +. /scripts/common.sh + +. ./env + +HandBrakeCLI \ + -i DVD/VIDEO_TS \ + --main-feature \ + --native-language eng \ + -Z "Chromecast 1080p30 Surround" \ + -o "${title}.mkv" +mv "${title}.mkv" "$OUTDIR" + +# vi: sw=2 ts=2 et ai