From fb39957c3450964733e636e3d91f91e41586965a Mon Sep 17 00:00:00 2001 From: Luke Tidd Date: Fri, 19 May 2023 10:26:43 -0400 Subject: [PATCH] added tool to fix deprecated id3 tags in flacs --- compare_flac_opus | 9 ++++ encode_all | 16 ++++--- flac_update_id3 | 107 ++++++++++++++++++++++++++++++++++++++++++++++ update_all_id3 | 18 ++++++++ 4 files changed, 145 insertions(+), 5 deletions(-) create mode 100755 compare_flac_opus create mode 100755 flac_update_id3 create mode 100755 update_all_id3 diff --git a/compare_flac_opus b/compare_flac_opus new file mode 100755 index 0000000..af0f549 --- /dev/null +++ b/compare_flac_opus @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +flac_dir="${HOME}/flac" +opus_dir="${HOME}/opus" +# +printf 'flacs: %s\n' "$(find "$flac_dir" -name '*.flac' -type f | wc -l)" +printf 'opuses: %s\n' "$(find "$opus_dir" -name '*.opus' -type f | wc -l)" +# find "$opus_dir" -name '*.opus' -type f | sed -e "s,$opus_dir,$flac_dir," -e 's_\.opus$_\.flac_' | sort -V +printf 'diff:\n' +diff --suppress-common-lines -y <(find "$flac_dir" -name '*.flac' -type f | sort -V) <(find "$opus_dir" -name '*.opus' -type f | sed -e "s,$opus_dir,$flac_dir," -e 's_\.opus$_\.flac_' | sort -V) diff --git a/encode_all b/encode_all index 0a141aa..3057825 100755 --- a/encode_all +++ b/encode_all @@ -5,6 +5,7 @@ src_library="${HOME}/flac" output_dir="${HOME}/opus" +log="${HOME}/encode_log_$(date '+%Y-%m-%d_%H:%M')" function encode() { file="$1" @@ -14,6 +15,9 @@ function encode() { file_name="$(basename "$file")" final_dir="$(sed "s_${HOME}/flac_${HOME}/opus_" <<< "$src_dir")" final_opus="$(sed -e 's/\.flac$/.opus/' -e "s_${HOME}/flac_${HOME}/opus_" <<< "$file")" + if [[ -f "$final_opus" ]]; then + return + fi unset tags unset dest_dir @@ -39,17 +43,19 @@ function encode() { [[ -d "$final_dir" ]] || mkdir -p "$final_dir" if [[ -n "${tags[DISK]}" ]]; then - opusenc \ + err="$(opusenc --quiet \ --title "${tags[TITLE]}" --artist "${tags[ARTIST]}" \ --album "${tags[ALBUM]}" --tracknumber "${tags[TRACKNUMBER]}" \ - --date "${tags[DATE]}" --comment "DISK=${tags[DISK]}" "$file" "$final_opus" + --date "${tags[DATE]}" --comment "DISK=${tags[DISK]}" "$file" "$final_opus" 2>&1)" else - opusenc \ + err="$(opusenc --quiet \ --title "${tags[TITLE]}" --artist "${tags[ARTIST]}" \ --album "${tags[ALBUM]}" --tracknumber "${tags[TRACKNUMBER]}" \ - --date "${tags[DATE]}" "$file" "$final_opus" + --date "${tags[DATE]}" "$file" "$final_opus" 2>&1)" + fi + if [[ -n "$err" ]]; then + printf '%s\n' "$err" >> "$log" fi - } time find "$src_library" -type f -name '*.flac' -print0 | env_parallel -P 0 -0 --bar encode {} diff --git a/flac_update_id3 b/flac_update_id3 new file mode 100755 index 0000000..c1ab61d --- /dev/null +++ b/flac_update_id3 @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 + +import logging +import os +import pathlib +import pprint +import re +import shutil +import subprocess +import sys +import tempfile + + +comment_re = re.compile(' comment\[[0-9]+\]: (?P[^=]+)=(?P.*)') + + +def run(cmd): + p = subprocess.run(cmd, capture_output=True) + return (p.stdout.decode('UTF-8'), p.stderr.decode('UTF-8'), p.returncode) + + +def get_tags(filename): + tags = {} + cmd = ('/usr/bin/metaflac', '--list', '--block-type=VORBIS_COMMENT', filename) + stdout, stderr, exit_code = run(cmd) + stdout = stdout.split('\n') + logging.debug(f'stdout: {stdout}') + logging.debug(f'stderr: {stderr}') + logging.debug(f'exit: {exit_code}') + if exit_code != 0: + sys.exit(stderr) + for line in stdout: + match = comment_re.search(line) + if match: + tags[match.group('tag_name')] = match.group('tag') + return tags + + +def writable(filename): + return os.access(filename, os.R_OK) + + +def ffmpeg_encode(input_file, output_file): + cmd = ('/usr/bin/ffmpeg', '-loglevel', 'error', '-i', input_file, output_file) + stdout, stderr, exit_code = run(cmd) + if exit_code != 0: + logging.fatal(stderr) + + +def write_flac(input_wav, tags, output_flac): + cmd = ['/usr/bin/flac', '-f', '-s', '--best'] + tags = [f'{tag_type}={tag}' for tag_type, tag in tags.items()] + logging.debug(tags) + for tag in tags: + cmd.append('-T') + cmd.append(tag) + cmd.append(input_wav) + cmd.append('-o') + cmd.append(output_flac) + _, stderr, exit_code = run(cmd) + if exit_code != 0: + sys.exit(stderr) + + +def replace_original(new, old): + try: + os.rename(new, old) + except: + logging.error(f'Failed to replace {old} with {new}.') + pprint.pprint(get_tags(old)) + sys.exit(1) + +def main(): + logging.basicConfig(encoding='utf-8', level=logging.DEBUG) + if len(sys.argv) != 2: + sys.exit('Give a flac with id3 tags.') + + full_flac = pathlib.Path(sys.argv[1]).resolve() + + if not writable(full_flac): + sys.exit(f'{full_flac} is not writable.') + + stem = full_flac.stem + file = full_flac.name + path = full_flac.parent + + logging.debug(f'stem: {stem}') + logging.debug(f'file: {file}') + logging.debug(f'path: {path}') + tags = get_tags(full_flac) + + with tempfile.TemporaryDirectory(dir='/dev/shm') as working_dir: + with tempfile.NamedTemporaryFile(dir=path, delete=False) as temp_flac: + full_wav = working_dir / pathlib.Path(stem + '.wav') + + ffmpeg_encode(full_flac, full_wav) + write_flac(full_wav.as_posix(), tags, temp_flac.name) + cmd = ('/usr/bin/flac', '-t', temp_flac.name) + stdout, stderr, exit_code = run(cmd) + print(f'stdout: {stdout}') + print(f'stderr: {stderr}') + print(f'exit code: {exit_code}') + pprint.pprint(get_tags(temp_flac.name)) + replace_original(temp_flac.name, full_flac) + +if __name__ == '__main__': + main() diff --git a/update_all_id3 b/update_all_id3 new file mode 100755 index 0000000..c1f0f3a --- /dev/null +++ b/update_all_id3 @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +log_file="$1" + +if [[ -z "$log_file" ]]; then + printf 'give a log file from encode_all\n' >&2 + exit 1 +fi +if [[ ! -r "$log_file" ]]; then + printf '%s isnt a readable log file.\n' "$log_file" >&2 + exit 1 +fi + +time while read line; do + file="/$(cut -d/ -f2- <<< "$line")" + printf '%s\n' "$file" + +done < "$log_file" | parallel -P 0 --bar ./flac_update_id3 {}