commit b63bf587e11b90355a747bac1d66fbaa9d79db0f
parent 0623b4cace16127ab6f4fd075444e9c196a5bec0
Author: hhvn <dev@hhvn.uk>
Date: Sun, 17 Apr 2022 22:28:00 +0100
Reimplement a/v tagging scripts
Diffstat:
6 files changed, 278 insertions(+), 47 deletions(-)
diff --git a/.scripts/musictag b/.scripts/musictag
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-[ -z $1 ] || [ -z $4 ] && echo "usage: musictag <file>.<fileext> <artist> <title> <album> [track]" && exit 1
-
-[ ! -z $5 ] && outname="$5."
-outname="${outname}$(echo "$2" | tr ' /' '.+').-.$(echo "$3" | tr ' /' '.+').${1##*.}"
-
-ffmpeg -y -nostdin -i "$1" -map_metadata -1 -vn -c copy -metadata "artist=$2" -metadata "title=$3" -metadata "album=$4" -metadata "track=$5" "$outname"
diff --git a/.scripts/musictaginteractive b/.scripts/musictaginteractive
@@ -1,23 +0,0 @@
-#!/bin/sh
-#
-# usage: musictaginteractive [artist] [album]
-
-[ "$1" != "" ] && sartist=1 && artist="$1"
-[ "$2" != "" ] && salbum=1 && album="$2"
-
-get(){
- printf "$1? "
- read $1 </dev/tty
-}
-
-[ ${sartist:-0} -ne 1 ] && get artist
-[ ${salbum:-0} -ne 1 ] && get album
-
-num=0
-for f in *
-do
- num=$(($num+1))
- echo "$(tput setaf 10)$f:$(tput sgr0)"
- get title
- musictag "$f" "$artist" "$title" "$album" "$(printf "%02d" "$num")"
-done
diff --git a/.scripts/musictagorder b/.scripts/musictagorder
@@ -1,16 +0,0 @@
-#!/bin/sh
-#
-# usage: musictagorder -m [f1] [f2]
-#
-# -m do not prefix filename with track num
-
-[ "$1" != "-m" ] && move=y || shift
-
-count=0
-while [ $# -ne 0 ]
-do
- count=$(($count+1))
- prettycount=$(printf '%02d' $count)
-
- ffmpeg -y -notdin -i "$1" -map_metadata 0 -vn -c -copy -metadata "track=$prettycount" "$prettycount.$1"
-done
diff --git a/.scripts/tag/get b/.scripts/tag/get
@@ -0,0 +1,37 @@
+#!/bin/rc
+
+fn usage {
+ printf 'usage: tag/get files...\n' >[1=2]
+ exit 2
+}
+
+if (~ $#* 0 || ~ $1 -h) {
+ usage
+}
+
+label = ''
+
+for (f in $*) {
+ if (!~ $#* 1) {
+ label = '[' ^ $f ^ '] '
+ }
+ if (!test -f $f) {
+ printf '%sCould not locate file.\n' $label >[1=2]
+ continue
+ }
+ ffmpeg -i $f -f ffmetadata - >[2]/dev/null |
+ awk -vlabel=^$label '/=/ {
+ key = $0; sub(/=.*/, "", key)
+ pad = key; gsub(/./, " ", pad)
+ val = $0; sub(/^[^=]*=/, "", val)
+ printf("%s%s: %s\n", label, key, val);
+ next
+ }
+
+ # Print multiline metadata values indented
+ /^[^;\[]/ { printf("%s%s %s\n", label, pad, $0) }
+
+ # Chapters/streams
+ /^\[/ { printf("\n%s%s\n", label, $0) }' |
+ sed -E 's/\\$//g;s/\\([=;#\\])/\1/g'
+}
diff --git a/.scripts/tag/interactive b/.scripts/tag/interactive
@@ -0,0 +1,111 @@
+#!/bin/rc
+
+usage = (
+'usage: tag/interactive [-n] [-k] [-p metadata] [--artist artist]'
+' [--title title] [--album album]'
+' [--track track] [--comment comment]'
+' files...'
+''
+'tag/interactive is an interactive interface to tag/set.'
+''
+'-p Metadata to prompt the user for. Usuable multiple times.'
+' Can contain: artist, title, album, track, comment'
+'-n Dry run. Prints commands to be executed.'
+'-k Preserve all metadata this is not specified.'
+''
+'--artist, --title, --album, --track, and --comment'
+' Specify default metadata to apply to all files.'
+)
+
+targs = ()
+
+fn usage {
+ for (line in $usage) {
+ printf '%s\n' $line >[1=2]
+ }
+ exit 2
+}
+
+fn addmd {
+ if (~ $2 ()) {
+ usage
+ }
+ targs = ($targs $1 $2)
+ have = ($have `$nl{echo $1 | sed 's/^--//'})
+}
+
+fn get {
+ if (~ $want $1) {
+ tput bold
+ printf '%s: ' $1
+ tput sgr0
+ curtargs = ($curtargs --$1 `$nl{head -n 1})
+ }
+}
+
+fn printcmd {
+ whatis $1 >[2=1] | sed 's/^[^=]*=(//;s/)$//'
+}
+
+while (!~ $#* 0) {
+ switch ($1) {
+ case --artist
+ addmd $*
+ shift
+ case --title
+ addmd $*
+ shift
+ case --album
+ addmd $*
+ shift
+ case --track
+ addmd $*
+ shift
+ case --comment
+ addmd $*
+ shift
+ case -p
+ if (~ $2 ()) {
+ usage
+ }
+ if (!~ $2 artist title album track comment) {
+ printf 'Unsupported prompt: %s\n' $2 >[1=2]
+ }
+ want = ($want $2)
+ shift
+ case -k
+ targs = (-k $targs)
+ case -n
+ dry = 1
+ case -*
+ printf 'No such option: %s\n' $1 >[1=2]
+ usage
+ case *
+ files = ($files $1)
+ }
+ shift
+}
+
+for (w in $want) {
+ if (~ $have $w) {
+ printf 'Cannot have both --%s and -p %s\n' $w $w >[1=2]
+ }
+}
+
+for (f in $files) {
+ curtargs = $targs
+ printf '==> %s <==\n' $f
+ get artist
+ get title
+ get album
+ get track
+ get comment
+ cmd = (tag/set $curtargs $f)
+ if (~ $dry 1) {
+ printcmd cmd
+ tag/set -n $curtargs $f >[2=1]
+ } else {
+ echo Running `$nl{printcmd cmd}
+ $cmd
+ }
+}
diff --git a/.scripts/tag/set b/.scripts/tag/set
@@ -0,0 +1,130 @@
+#!/bin/rc
+
+usage = (
+'usage: tag/set [-n] [-k] [--artist artist]'
+' [--title title] [--album album]'
+' [--track track] [--comment comment]'
+' files...'
+' tag/set [-n] [-d] files...'
+''
+'tag/set removes and replaces metadata from audio/video files.'
+''
+'-n Dry run. Only print commands to be executed.'
+'-d Remove all data without replacing. Cannot be used with other options'
+' except -n. This option was added to prevent accidental destruction.'
+'-k Preserve all metadata that is not specified'
+''
+'--artist, --title, --album, --track, and --comment'
+' Specify replacement metadata.'
+)
+
+clear = (-map_metadata -1)
+files = ()
+tmp = ()
+margs = ()
+
+fn sigexit {
+ for (f in $tmp) {
+ rm -f $f >[2]/dev/null >[1=2]
+ }
+}
+
+fn usage {
+ for (line in $usage) {
+ printf '%s\n' $line >[1=2]
+ }
+ exit 2
+}
+
+fn tmp {
+ if (~ $dry 1) {
+ echo tmpfile
+ } else {
+ location = /tmp/$pid.`$nl{echo $1 | tr / _} {
+ echo $location
+ tmp = ($tmp $location)
+ }
+ }
+}
+
+fn addmd {
+ if (~ $2 ()) {
+ usage
+ }
+ margs = ($margs -metadata `$nl{echo $1 | sed 's/^--//'} ^ '=' ^ $2)
+}
+
+fn printcmd {
+ whatis $1 >[2=1] | sed 's/^[^=]*=(//;s/)$//'
+}
+
+while (!~ $#* 0) {
+ switch ($1) {
+ case --artist
+ addmd $*
+ shift
+ case --title
+ addmd $*
+ shift
+ case --album
+ addmd $*
+ shift
+ case --track
+ addmd $*
+ shift
+ case --comment
+ addmd $*
+ shift
+ case -k
+ clear = ()
+ case -d
+ delete = 1
+ case -n
+ dry = 1
+ case -*
+ printf 'No such option: %s\n' $1 >[1=2]
+ usage
+ case *
+ files = ($files $1)
+ }
+ shift
+}
+
+if (~ $files ()) {
+ printf 'No files specified\n' >[1=2]
+ exit 1
+}
+
+# --delete cannot be specified along with other args
+if (~ $delete 1 && {!~ $margs () || ~ $clear ()}) {
+ printf '--delete cannot be specified along with other args\n'
+ exit 1
+}
+
+if (~ $margs () && !~ $delete 1) {
+ printf 'Nothing to do\n' >[1=2]
+ exit 1
+}
+
+for (f in $files) {
+ out = `$nl{tmp $f}
+ fcmd = (ffmpeg -y -nostdin -i $f $clear -c copy $margs $out(1))
+ mcmd = (mv $out(1) $f)
+ if (~ $dry 1) {
+ printcmd fcmd
+ printcmd mcmd
+ } else if (!test -f $f) {
+ printf 'No such file: %s\n' $f >[1=2]
+ } else {
+ if (~ $delete 1) {
+ echo Removing metadata...
+ } else if (~ $clear ()) {
+ echo Adding metadata...
+ } else {
+ echo Replacing metadata...
+ }
+ $fcmd
+ echo Replacing file...
+ $mcmd
+ }
+}