From e70dc21af548d2c312c698c4a2f6033d3134fc0e Mon Sep 17 00:00:00 2001 From: LuKe Tidd Date: Sun, 4 Aug 2024 10:52:06 -0400 Subject: [PATCH] fix utf-8 tags --- encode_all | 12 +++- encode_dir | 90 ++++++++++++++++++++++++++++ split_dir | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++ split_tracks | 16 ++--- 4 files changed, 275 insertions(+), 9 deletions(-) create mode 100755 encode_dir create mode 100755 split_dir diff --git a/encode_all b/encode_all index 13ae904..f5efffe 100755 --- a/encode_all +++ b/encode_all @@ -144,10 +144,18 @@ function encode() { '--tracknumber' "${tags['TRACKNUMBER']}" '--date' "${album_date}") [[ -n "${tags[DISK]}" ]] && tag_flags+=('--comment' "DISK=${tags['DISK']}") + tags='' + for tag in "${tag_flags[@]}"; do + tags+="$(printf '"%s" ' "$tag")" + done if [[ "$debug_only" == 'false' ]]; then - err="$(opusenc --quiet --discard-comments --discard-pictures "${tag_flags[@]}" "$file" "$final_opus" 2>&1)" + # err="$(opusenc --quiet --discard-comments --discard-pictures "${tag_flags[@]}" "$file" "$final_opus" 2>&1)" + cmd=$(printf 'opusenc --quiet --discard-comments --discard-pictures %s "%s" "%s"\n' "$tags" "$file" "$final_opus") + printf '%s\n' "$cmd" + eval $cmd else - echo opusenc --quiet --discard-comments --discard-pictures "${tag_flags[@]}" "$file" "$final_opus" + cmd=$(printf 'opusenc --quiet --discard-comments --discard-pictures %s "%s" "%s"\n' "$tags" "$file" "$final_opus") + printf '%s\n' "$cmd" fi if [[ -n "$err" ]]; then printf '%s\n' "$err" >> "$log" diff --git a/encode_dir b/encode_dir new file mode 100755 index 0000000..141db9f --- /dev/null +++ b/encode_dir @@ -0,0 +1,90 @@ +#!/bin/bash +# encode_all encodes the whole library into specified format +# +ulimit -n "$(ulimit -Hn)" +. env_parallel.bash + +function ts() { + date '+%Y-%m-%d_%H:%M' +} + +debug_only=false +# debug_only=true +src_dir="$1" +export output_dir="$2" +if [[ -z "$src_dir" || -z "$output_dir" ]]; then + printf 'Usage:\nencode_dir \n' >&2 + exit 1 +fi + +logdir="${HOME}/encoding_logs" +[[ -d "$logdir" ]] || mkdir "$logdir" +start_ts="$(ts)" +log="${logdir}/${start_ts}_encoding_log" +fixes="${logdir}/${start_ts}_fixes.sh" +temp_dir="$(mktemp -d)" + +printf '#!/bin/bash\n# FIXES generated by library_works/encode_all\n\n' > "$fixes" + +function encode() { + src_file_and_path="$1" + src_file="$(basename "$in_file_path")" + # file is full original path + filename + src_dir="$(dirname "$src_file_and_path")" + file_name="$(basename "$src_file_and_path")" + final_opus="${output_dir}/$(sed -e 's/\.flac$/.opus/' <<< "$file_name")" + + unset tags + unset dest_dir + + declare -A tags + while read -r line; do + tag_type="$(cut -d= -f1 <<< "$line")" + tag_type="${tag_type^^}" + tag_val="$(cut -d= -f2- <<< "$line")" + # TODO: suggest fixes for lower case tags + tags["$tag_type"]="$tag_val" + done < <(metaflac --list --block-type='VORBIS_COMMENT' "$src_file_and_path" | \ + grep 'comment\[' | \ + cut -d: -f2- | \ + sed 's/^ //') + + tag_ensure=( 'TRACKNUMBER' 'TITLE' 'ALBUM' 'ARTIST' 'YEAR') + for tag_type in "${tag_ensure[@]}"; do + if [[ -z "${tags["$tag_type"]}" ]]; then + printf '%s is missing tag: %s\n' "$src_file_and_path" "$tag_type" >> "$log" + tags["$tag_type"]="missing $tag_type" + fi + done + + [[ -d "$output_dir" ]] || mkdir -p "$output_dir" + tag_flags=( + '--title' "${tags['TITLE']}" + '--artist' "${tags['ARTIST']}" + '--album' "${tags['ALBUM']}" + '--tracknumber' "${tags['TRACKNUMBER']}" + '--date' "${tags['DATE']}") + [[ -n "${tags[DISK]}" ]] && tag_flags+=('--comment' "DISK=${tags['DISK']}") + tags='' + for tag in "${tag_flags[@]}"; do + tags+="$(printf '"%s" ' "$tag")" + done + cmd=$(printf 'opusenc --downmix-mono --bitrate 48 --speech --quiet --discard-comments --discard-pictures %s "%s" "%s"\n' "$tags" "$src_file_and_path" "$final_opus") + printf '%s\n' "$cmd" + eval $cmd + + if [[ -n "$err" ]]; then + printf '%s\n' "$err" >> "$log" + fi +} + +echo starting processing +# find "$src_dir" -type f -name '*.flac' | while read line; do encode "${line}"; done +# exit 1 +# find "$src_dir" -type f -name '*.flac' | while read line; do encode "$line"; done +# wait +find "$src_dir" -type f -name '*.flac' -print0 | env_parallel -P 0 -0 --bar encode {} +echo done processing + +echo deleting any empty directories +# find "$output_dir" -empty -type d -delete diff --git a/split_dir b/split_dir new file mode 100755 index 0000000..ebdedc8 --- /dev/null +++ b/split_dir @@ -0,0 +1,166 @@ +#!/bin/bash + +# split_dir splits each track from a specified directory. +# +# The library is mirrored for each type of split. +# +# karaoke: reduces the volume of the vocals by 80% and remixes it +# drum only: just the drums +# no drum: reduces the volume of the drums by 80% and remixes it + + +target="$1" +if [[ -z "$target" ]]; then + printf 'Give a target dir\n' >&2 + exit 1 +fi + + +function make_drum() { + mkdir -p "${dest_dir['no drums']}" + # quiet_drums="${actual_work_dir}/quiet drums.wav" + wav_name="$(sed 's/\.flac$/.wav/' <<< "$file_name")" + mixed_wav="${dest_dir['no drums']}/${wav_name}" + final_opus="$(sed 's/\.wav$/.opus/' <<< "$mixed_wav")" + + # echo sox -v "$volume_reduction_factor" "$drum_track" "$quiet_drums" + # sox -v "$volume_reduction_factor" "$drum_track" "$quiet_drums" + # echo sox -m "${nodrums[@]}" "$quiet_drums" "$mixed_wav" + # sox -m "${nodrums[@]}" "$quiet_drums" "$mixed_wav" + echo sox -m "${nodrums[@]}" "$mixed_wav" + sox -m "${nodrums[@]}" "$mixed_wav" + # rm "$quiet_drums" + echo opusenc --comp 10 --downmix-stereo \ + --title "'${tags[TITLE]}'" --artist "'${tags[ARTIST]}'" \ + --album "'${tags[ALBUM]}'" --tracknumber "'${tags[TRACKNUMBER]}'" \ + --date "'${tags[DATE]}'" "'$mixed_wav'" "'$final_opus'" + opusenc --comp 10 --downmix-stereo \ + --title "${tags[TITLE]}" --artist "${tags[ARTIST]}" \ + --album "${tags[ALBUM]}" --tracknumber "${tags[TRACKNUMBER]}" \ + --date "${tags[DATE]}" "$mixed_wav" "$final_opus" + rm "$mixed_wav" +} + +function make_drumonly() { + mkdir -p "${dest_dir['drums only']}" + echo echo dest dir: ${dest_dir['drums only']} + echo drum track: "$drum_track" + final_opus="${dest_dir['drums only']}/$(sed 's/\.flac$/.opus/' <<< "$file_name")" + echo opusenc --comp 10 --downmix-stereo \ + --title "'${tags[TITLE]}'" --artist "'${tags[ARTIST]}'" \ + --album "'${tags[ALBUM]}'" --tracknumber "'${tags[TRACKNUMBER]}'" \ + --date "'${tags[DATE]}'" "'$drum_track'" "'$final_opus'" + opusenc --comp 10 --downmix-stereo \ + --title "${tags[TITLE]}" --artist "${tags[ARTIST]}" \ + --album "${tags[ALBUM]}" --tracknumber "${tags[TRACKNUMBER]}" \ + --date "${tags[DATE]}" "$drum_track" "$final_opus" +} + +function make_karaoke() { + mkdir -p "${dest_dir[karaoke]}" + quiet_vocals="${actual_work_dir}/quiet vocals.wav" + wav_name="$(sed 's/\.flac$/.wav/' <<< "$file_name")" + mixed_wav="${dest_dir['karaoke']}/${wav_name}" + final_opus="$(sed 's/\.wav$/.opus/' <<< "$mixed_wav")" + echo sox -v "$volume_reduction_factor" "$vocal_track" "$quiet_vocals" + sox -v "$volume_reduction_factor" "$vocal_track" "$quiet_vocals" + echo sox -m "${karaoke[@]}" "$quiet_vocals" "$mixed_wav" + sox -m "${karaoke[@]}" "$quiet_vocals" "$mixed_wav" + rm "$quiet_vocals" + echo opusenc --comp 10 --downmix-stereo \ + --title "'${tags[TITLE]}'" --artist "'${tags[ARTIST]}'" \ + --album "'${tags[ALBUM]}'" --tracknumber "'${tags[TRACKNUMBER]}'" \ + --date "'${tags[DATE]}'" "'$mixed_wav'" "'$final_opus'" + opusenc --comp 10 --downmix-stereo \ + --title "${tags[TITLE]}" --artist "${tags[ARTIST]}" \ + --album "${tags[ALBUM]}" --tracknumber "${tags[TRACKNUMBER]}" \ + --date "${tags[DATE]}" "$mixed_wav" "$final_opus" + rm "$mixed_wav" +} + +volume_reduction_factor='0.1' +src_library="$target" +work_dir="${HOME}/split" +actual_work_dir="${work_dir}/htdemucs_ft" + +type -P 'demucs' &>/dev/null || ( + printf 'No demucs in path.\nInstall with `pip install demucs` or something.\n\n' >&2 + exit 1 +) + +find "$src_library" -type f -name '*.flac' | while read file; do + if find "$work_dir" -type f &>/dev/null; then rm -rf "${work_dir}"/*; fi + echo "file: $file" + # file is full original path + filename + src_dir="$(dirname "$file")" + file_name="$(basename "$file")" + unset tags + unset dest_dir + + declare -A tags + echo tag time + while read -r line; do + tag_type="$(cut -d= -f1 <<< "$line")" + tag_type="${tag_type^^}" + tag_val="$(cut -d= -f2- <<< "$line")" + tags["$tag_type"]="$tag_val" + done < <(metaflac --list --block-type=VORBIS_COMMENT "$file" | grep 'comment\[' | cut -d: -f2- | sed 's/^ //') + album="$(basename "$final_dir")" + if [[ "$file_name" =~ ^D[0-9]+ ]]; then + disk="$(cut -d\ -f1 <<< "$file_name")" + tags[DISK]="${disk#D}" + fi + declare -a tag_ensure + tag_ensure=( TRACKNUMBER TITLE DATE ALBUM ARTIST ) + for tag_type in "${tag_ensure[@]}"; do + if [[ -z "${tags[$tag_type]}" ]]; then + tags[$tag_type]="missing $tag_type" + fi + done + + declare -A dest_dir + dest_dir['karaoke']="${src_dir//flac/karaoke}" + dest_dir['drums only']="${src_dir//flac/drums only}" + dest_dir['no drums']="${src_dir//flac/no drums}" + + demucs -n htdemucs_ft -o "$work_dir" --filename '{track} {stem}.{ext}' -j50 -d cpu --clip-mode rescale -- "$file" < /dev/null + unset files karaoke nodrums + declare -a files karaoke nodrums + readarray -t files < <(find "$work_dir" -type f -name '*.wav') + unset vocal_track + unset drum_track + + for cur_file in "${files[@]}"; do + echo current file: "$cur_file" + if ! grep -Eq 'drums\.wav$' <<< "$cur_file"; then + nodrums+=("$cur_file") + else + drum_track="$cur_file" + fi + + if ! grep -Eq 'vocals\.wav$' <<< "$cur_file"; then + karaoke+=("$cur_file") + else + vocal_track="$cur_file" + fi + done + + for i in "${nodrums[@]}"; do + printf 'Drum practice: %s\n' "$i" + done + if [[ -z "$drum_track" ]]; then + printf 'No drum track. Will not create a drum practice file.\n' + else + make_drum + make_drumonly + fi + for i in "${karaoke[@]}"; do + printf 'Karaoke practice: %s\n' "$i" + done + if [[ ! "$vocal_track" ]]; then + printf 'No vocal track. Will not create a karaoke file.\n' + else + make_karaoke + fi +done + diff --git a/split_tracks b/split_tracks index 85913ec..374ad0e 100755 --- a/split_tracks +++ b/split_tracks @@ -10,16 +10,18 @@ function make_drum() { mkdir -p "${dest_dir['no drums']}" - quiet_drums="${actual_work_dir}/quiet drums.wav" + # quiet_drums="${actual_work_dir}/quiet drums.wav" wav_name="$(sed 's/\.flac$/.wav/' <<< "$file_name")" mixed_wav="${dest_dir['no drums']}/${wav_name}" final_opus="$(sed 's/\.wav$/.opus/' <<< "$mixed_wav")" - echo sox -v "$volume_reduction_factor" "$drum_track" "$quiet_drums" - sox -v "$volume_reduction_factor" "$drum_track" "$quiet_drums" - echo sox -m "${nodrums[@]}" "$quiet_drums" "$mixed_wav" - sox -m "${nodrums[@]}" "$quiet_drums" "$mixed_wav" - rm "$quiet_drums" + # echo sox -v "$volume_reduction_factor" "$drum_track" "$quiet_drums" + # sox -v "$volume_reduction_factor" "$drum_track" "$quiet_drums" + # echo sox -m "${nodrums[@]}" "$quiet_drums" "$mixed_wav" + # sox -m "${nodrums[@]}" "$quiet_drums" "$mixed_wav" + echo sox -m "${nodrums[@]}" "$mixed_wav" + sox -m "${nodrums[@]}" "$mixed_wav" + # rm "$quiet_drums" echo opusenc --comp 10 --downmix-stereo \ --title "'${tags[TITLE]}'" --artist "'${tags[ARTIST]}'" \ --album "'${tags[ALBUM]}'" --tracknumber "'${tags[TRACKNUMBER]}'" \ @@ -68,7 +70,7 @@ function make_karaoke() { rm "$mixed_wav" } -volume_reduction_factor='0.2' +volume_reduction_factor='0.1' src_library="${HOME}/flac" work_dir="${HOME}/split" actual_work_dir="${work_dir}/htdemucs_ft"