metadata scripts
This commit is contained in:
1 parent
74a3cfe8ed
commit
cff21a4dab
4 files changed
+256
No files matched your search
@@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
escape_kid3() {
|
||||||
|
printf '%s' "$1" | sed "s/'/'\\\\''/g"
|
||||||
|
}
|
||||||
|
DRY_RUN=false
|
||||||
|
|
||||||
|
if [[ "$1" == "--dry-run" ]]; then
|
||||||
|
DRY_RUN=true
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $# -ne 1 ]]; then
|
||||||
|
echo "Usage: $0 [--dry-run] file.txt"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
list="$1"
|
||||||
|
|
||||||
|
if [[ ! -f "$list" ]]; then
|
||||||
|
echo "ERROR: File list not found: $list"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
while IFS= read -r file; do
|
||||||
|
|
||||||
|
[[ -z "$file" ]] && continue
|
||||||
|
|
||||||
|
if [[ ! -e "$file" ]]; then
|
||||||
|
echo "ERROR: Missing file: $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -d "$file" ]]; then
|
||||||
|
echo "WARNING: Is a directory, skipping: $file"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
bookdir="$(dirname "$file")"
|
||||||
|
booktitle="$(basename "$bookdir")"
|
||||||
|
author="$(basename "$(dirname "$bookdir")")"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "File: $file"
|
||||||
|
echo "Artist: $author"
|
||||||
|
echo "Album: $booktitle"
|
||||||
|
|
||||||
|
if $DRY_RUN; then
|
||||||
|
echo "DRY RUN: no changes made"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
artist=$(escape_kid3 "$author")
|
||||||
|
album=$(escape_kid3 "$booktitle")
|
||||||
|
|
||||||
|
kid3-cli "$file" \
|
||||||
|
-c "tag 1" \
|
||||||
|
-c "set artist '$artist'" \
|
||||||
|
-c "set album '$album'" \
|
||||||
|
-c "tag 2" \
|
||||||
|
-c "set artist '$artist'" \
|
||||||
|
-c "set album '$album'" \
|
||||||
|
-c save
|
||||||
|
done < "$list"
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
DRY_RUN=false
|
||||||
|
DELETE=false
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--dry-run)
|
||||||
|
DRY_RUN=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--delete)
|
||||||
|
DELETE=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ $# -ne 1 ]]; then
|
||||||
|
echo "Usage: $0 [--dry-run] [--delete] file.txt"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
list="$1"
|
||||||
|
|
||||||
|
while IFS= read -r file; do
|
||||||
|
|
||||||
|
[[ -z "$file" ]] && continue
|
||||||
|
|
||||||
|
if [[ ! -e "$file" ]]; then
|
||||||
|
echo "ERROR: Missing file: $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ -d "$file" ]]; then
|
||||||
|
echo "WARNING: Is a directory, skipping: $file"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# Get comment from ID3v2
|
||||||
|
comment=$(kid3-cli "$file" \
|
||||||
|
-c "tag 2" \
|
||||||
|
-c "get comment" 2>/dev/null)
|
||||||
|
|
||||||
|
[[ -z "$comment" ]] && continue
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "File: $file"
|
||||||
|
echo "Comment: $comment"
|
||||||
|
|
||||||
|
composer=""
|
||||||
|
|
||||||
|
# Match: read by Name; text
|
||||||
|
if [[ "$comment" =~ ^[Rr]ead[[:space:]]+[Bb]y[[:space:]]+([^;]+)\; ]]; then
|
||||||
|
composer="${BASH_REMATCH[1]}"
|
||||||
|
composer="$(echo "$composer" | sed 's/[[:space:]]*$//')"
|
||||||
|
|
||||||
|
echo "Found narrator: $composer"
|
||||||
|
|
||||||
|
if $DRY_RUN; then
|
||||||
|
echo "DRY RUN: set composer '$composer', delete comment"
|
||||||
|
else
|
||||||
|
kid3-cli "$file" \
|
||||||
|
-c "tag 2" \
|
||||||
|
-c "set composer '$composer'" \
|
||||||
|
-c "set comment ''" \
|
||||||
|
-c save
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [[ ${#comment} -lt 40 ]]; then
|
||||||
|
|
||||||
|
echo "Short comment (${#comment} chars): $comment"
|
||||||
|
|
||||||
|
if $DELETE; then
|
||||||
|
if $DRY_RUN; then
|
||||||
|
echo "DRY RUN: delete comment"
|
||||||
|
else
|
||||||
|
kid3-cli "$file" \
|
||||||
|
-c "tag 2" \
|
||||||
|
-c "set comment ''" \
|
||||||
|
-c save
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
done < "$list"
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
root="${1:-.}"
|
||||||
|
mode="${2:-}"
|
||||||
|
THRESHOLD=40
|
||||||
|
find "$root" \( -iname '*.mp3' -o -iname '*.m4a' -o -iname '*.m4b' \) -print0 |
|
||||||
|
while IFS= read -r -d '' f; do
|
||||||
|
|
||||||
|
comment=$(ffprobe -v error \
|
||||||
|
-show_entries format_tags=comment \
|
||||||
|
-of default=nw=1:nk=1 \
|
||||||
|
-- "$f")
|
||||||
|
|
||||||
|
description=$(ffprobe -v error \
|
||||||
|
-show_entries format_tags=description \
|
||||||
|
-of default=nw=1:nk=1 \
|
||||||
|
-- "$f")
|
||||||
|
|
||||||
|
# trim comment
|
||||||
|
comment="${comment#"${comment%%[![:space:]]*}"}"
|
||||||
|
comment="${comment%"${comment##*[![:space:]]}"}"
|
||||||
|
|
||||||
|
# ---- DELETE MODE ----
|
||||||
|
if [[ "$mode" == "del" && -n "$comment" && ${#comment} -lt $THRESHOLD ]]; then
|
||||||
|
tmp=$(mktemp -p "$(dirname -- "$f")" ".fftmp.XXXXXX.${f##*.}") || continue
|
||||||
|
|
||||||
|
echo "Removing short comment: $f"
|
||||||
|
echo " comment: $comment"
|
||||||
|
|
||||||
|
ffmpeg -nostdin -v error -y \
|
||||||
|
-i "$f" \
|
||||||
|
-map 0 \
|
||||||
|
-map_metadata 0 \
|
||||||
|
-c copy \
|
||||||
|
-metadata comment= \
|
||||||
|
"$tmp" &&
|
||||||
|
mv -f -- "$tmp" "$f" || {
|
||||||
|
echo "FAILED: $f" >&2
|
||||||
|
rm -f -- "$tmp"
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---- SCAN MODE ----
|
||||||
|
# only show short non-empty tags (<20 chars)
|
||||||
|
for tag in comment description; do
|
||||||
|
value="${!tag}"
|
||||||
|
|
||||||
|
value="${value#"${value%%[![:space:]]*}"}"
|
||||||
|
value="${value%"${value##*[![:space:]]}"}"
|
||||||
|
|
||||||
|
if [[ -n "$value" && ${#value} -lt $THRESHOLD ]]; then
|
||||||
|
printf "%s\n %s: %s\n\n" "$f" "$tag" "$value"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
done
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
find . \( -iname '*.mp3' -o -iname '*.m4a' -o -iname '*.m4b' \) -print0 |
|
||||||
|
while IFS= read -r -d '' f; do
|
||||||
|
|
||||||
|
comment=$(ffprobe -v error \
|
||||||
|
-show_entries format_tags=comment \
|
||||||
|
-of default=nw=1:nk=1 \
|
||||||
|
-- "$f")
|
||||||
|
|
||||||
|
[[ $comment =~ ^[Rr]ead[[:space:]]+[Bb]y[[:space:]]+(.+) ]] || continue
|
||||||
|
|
||||||
|
composer="${BASH_REMATCH[1]}"
|
||||||
|
echo "Updating: $f"
|
||||||
|
echo " Composer: $composer"
|
||||||
|
|
||||||
|
dir=$(dirname -- "$f")
|
||||||
|
base=$(basename -- "$f")
|
||||||
|
ext="${base##*.}"
|
||||||
|
|
||||||
|
case "${ext,,}" in
|
||||||
|
mp3) format=mp3 ;;
|
||||||
|
m4a|m4b) format=ipod ;;
|
||||||
|
*) continue ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
tmp=$(mktemp -p "$dir" ".${base}.XXXXXX") || {
|
||||||
|
echo "Couldn't create temporary file in $dir" >&2
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ffmpeg -nostdin -v error -y \
|
||||||
|
-i "$f" \
|
||||||
|
-map 0 \
|
||||||
|
-map_metadata 0 \
|
||||||
|
-c copy \
|
||||||
|
-metadata composer="$composer" \
|
||||||
|
-metadata comment= \
|
||||||
|
-f "$format" \
|
||||||
|
"$tmp"
|
||||||
|
then
|
||||||
|
mv -f -- "$tmp" "$f"
|
||||||
|
else
|
||||||
|
echo "FAILED: $f" >&2
|
||||||
|
rm -f -- "$tmp"
|
||||||
|
fi
|
||||||
|
done
|
||||||
Reference in new issue
Block a user