From 1194e2b3296419bee0697f5b1039888b0aceef6a Mon Sep 17 00:00:00 2001 From: Tom Taylor <975744+t0mtaylor@users.noreply.github.com> Date: Mon, 12 Aug 2024 19:30:13 +0100 Subject: [PATCH 1/5] Introduce `skip` arg and `liq_cue_skip` tag for files to avoid reprocessing by force --- cue_file | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/cue_file b/cue_file index b960bbb..7a9071f 100755 --- a/cue_file +++ b/cue_file @@ -69,13 +69,17 @@ # forbid external processes to call us again and # possibly deliver outdated metadata to us. # 2024-08-05 Moonbase59 - v4.1.1 Fix JSON overriding if `liq_cue_file` is true +# 2024-08-12 t0mtaylor - v4.2.0 Introduce `skip` arg and `liq_cue_skip` tag for files + to avoid reprocessing by force, and fix Mutagen m4a python + TypeError: encoding without a string argument on Mac when + writing tags for m4a/mp4 files. # # Originally based on an idea and some code by John Warburton (@Warblefly): # https://github.com/Warblefly/TrackBoundaries # Some collaborative work with RM-FM (@RM-FM): Sustained ending analysis. __author__ = 'Matthias C. Hormann' -__version__ = '4.1.1' +__version__ = '4.2.0' import os import sys @@ -126,6 +130,8 @@ LONGTAIL_EXTRA_LU = -12.0 # reduce 15 dB extra on long tail songs to find overl SUSTAINED_LOUDNESS_DROP = 40.0 # max. percent drop to be considered sustained BLANKSKIP = 5.0 # min. seconds silence to detect blank NICE = False # use Linux/MacOS nice? +SKIP = False # force skip reprocessing of file if tags already exist +NO_SKIP_TAGS = False # allow new tags to be writen to file (when write enabled) unless skip tag exists and skip arg is set # These file types can be handled correctly by ffmpeg safe_ext = [ @@ -219,6 +225,7 @@ tags_to_check = { "liq_cross_start_next": float, "liq_cue_duration": float, "liq_cue_file": is_true, + "liq_cue_skip": is_true, "liq_cue_in": float, "liq_cue_out": float, "liq_fade_in": float, @@ -308,13 +315,15 @@ def override_from_JSON(tags, tags_json={}): # do NOT overwrite from JSON if `liq_cue_file` is true if "liq_cue_file" in tags and tags["liq_cue_file"] == True: pass + # do NOT overwrite from JSON if `liq_cue_skip` is true + elif "liq_cue_skip" in tags and tags["liq_cue_skip"] == True: + pass else: # unify, right overwrites left if key in both tags = {**tags, **tags_in_json} return tags - def read_tags( filename, tags_json={}, @@ -420,6 +429,7 @@ def read_tags( tags_found["liq_amplify"] += (target - tags_found["liq_reference_loudness"]) tags_found["liq_reference_loudness"] = target + else: # liq_amplify or liq_reference_loudness missing, must re-analyse skip_analysis = False @@ -469,6 +479,17 @@ def add_missing(tags_found, target=TARGET_LUFS, blankskip=0.0, noclip=False): if "liq_sustained_ending" not in tags_found: tags_found["liq_sustained_ending"] = False + if not "liq_cue_file" in tags_found: + tags_found["liq_cue_file"] = False + + if not "liq_cue_skip" in tags_found: + tags_found["liq_cue_skip"] = False + + if args.skip: + tags_found["liq_cue_file"] = True + tags_found["liq_cue_skip"] = True + tags_found["liq_blankskip"] = 0.0 + # if not "liq_cross_duration" in tags_found: # tags_found["liq_cross_duration"] = tags_found["liq_cue_out"] - tags_found["liq_cross_start_next"] @@ -850,7 +871,7 @@ def analyse( }) -def write_tags(filename, tags={}, replaygain=False): +def write_tags(filename, tags={}, replaygain=False, skip=False): # Add the liq_* tags (and only these) # Only touch replaygain_track_gain or R128_TRACK_GAIN if so requested. # Only write tags to files if we can safely do so. @@ -897,6 +918,11 @@ def write_tags(filename, tags={}, replaygain=False): tags_new["replaygain_track_gain"] += " dB" tags_new["replaygain_track_range"] += " dB" tags_new["replaygain_reference_loudness"] += " LUFS" + + + if skip: + tags_new["liq_cue_skip"] = True + if replaygain: # delete unwanted tags @@ -1191,12 +1217,24 @@ parser.add_argument( help="Force re-analysis, even if tags exist", default=False, action='store_true') +parser.add_argument( + "-p", + "--skip", + help="Force Skip of re-analysis and skip write if tags exist, overrides --force option", + default=False, + action='store_true') parser.add_argument( "-n", "--nice", help="Linux/MacOS only: Use nice? Will run analysis at nice level 18.", default=False, action='store_true') +parser.add_argument( + "-z", + "--debug", + help="Debug mode with addtional messages", + default=False, + action='store_true') parser.add_argument( "-j", "--json", @@ -1221,7 +1259,18 @@ if args.json: skip_analysis, tags_found = read_tags( args.file, tags_json, args.target, args.blankskip, args.noclip) -if args.force or not skip_analysis: +if args.debug: + print(tags_found) + +if not "liq_cue_skip" in tags_found: + NO_SKIP_TAGS = True + +if args.skip and "liq_cue_skip" in tags_found and tags_found["liq_cue_skip"] == True: + skip_analysis = True +if args.skip and "liq_cue_file" in tags_found and tags_found["liq_cue_file"] == True: + skip_analysis = True + +if args.force and skip_analysis != True: result = analyse( filename=args.file, target=args.target, @@ -1240,13 +1289,18 @@ if args.force or not skip_analysis: # override duration, seems ffprobe can be more exact if "duration" in tags_found: result["duration"] = tags_found["duration"] + else: result = add_missing(tags_found, args.target, args.blankskip, args.noclip) # eprint(result) -if args.write: - write_tags(args.file, result, args.replaygain) +if args.write and NO_SKIP_TAGS: #and not args.skip + if args.debug: + print('START: writing autocue tags for '+args.file) + write_tags(args.file, result, args.replaygain, NO_SKIP_TAGS) + if args.debug: + print('FINISHED: autocue tags written for '+args.file) # prepare JSON result # we use "dB" instead of "LU" units, because LS & others don’t understand "LU" From 89a404e4e5a21d36c52d33305ee527cec6e553dc Mon Sep 17 00:00:00 2001 From: Tom Taylor <975744+t0mtaylor@users.noreply.github.com> Date: Mon, 12 Aug 2024 19:31:18 +0100 Subject: [PATCH 2/5] Fix Mutagen m4a python TypeError: encoding without a string argument on Mac when writing tags for m4a/mp4 files --- cue_file | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cue_file b/cue_file index 7a9071f..fb6628b 100755 --- a/cue_file +++ b/cue_file @@ -951,7 +951,7 @@ def write_tags(filename, tags={}, replaygain=False, skip=False): if f.tags is None: f.add_tags() for k, v in tags_new.items(): - f[f'----:com.apple.iTunes:{k}'] = bytes(v, 'utf-8') + f[f'----:com.apple.iTunes:{k}'] = bytes(str(v), 'utf-8') f.save() elif MUTAGEN_AVAILABLE and filename.suffix.casefold() in id3_ext: From 3affdd0091f056ee8eae8bdcd13e22429202df87 Mon Sep 17 00:00:00 2001 From: Tom Taylor <975744+t0mtaylor@users.noreply.github.com> Date: Mon, 12 Aug 2024 21:27:18 +0100 Subject: [PATCH 3/5] Add more debug, fix: should check liq_cue_file without skip enabled --- cue_file | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/cue_file b/cue_file index fb6628b..0576abd 100755 --- a/cue_file +++ b/cue_file @@ -70,9 +70,9 @@ # possibly deliver outdated metadata to us. # 2024-08-05 Moonbase59 - v4.1.1 Fix JSON overriding if `liq_cue_file` is true # 2024-08-12 t0mtaylor - v4.2.0 Introduce `skip` arg and `liq_cue_skip` tag for files - to avoid reprocessing by force, and fix Mutagen m4a python - TypeError: encoding without a string argument on Mac when - writing tags for m4a/mp4 files. +# to avoid reprocessing by force, and fix Mutagen m4a python +# TypeError: encoding without a string argument on Mac when +# writing tags for m4a/mp4 files. # # Originally based on an idea and some code by John Warburton (@Warblefly): # https://github.com/Warblefly/TrackBoundaries @@ -871,7 +871,7 @@ def analyse( }) -def write_tags(filename, tags={}, replaygain=False, skip=False): +def write_tags(filename, tags={}, replaygain=False, writeSkipTag=False): # Add the liq_* tags (and only these) # Only touch replaygain_track_gain or R128_TRACK_GAIN if so requested. # Only write tags to files if we can safely do so. @@ -920,7 +920,7 @@ def write_tags(filename, tags={}, replaygain=False, skip=False): tags_new["replaygain_reference_loudness"] += " LUFS" - if skip: + if writeSkipTag: tags_new["liq_cue_skip"] = True @@ -1264,12 +1264,22 @@ if args.debug: if not "liq_cue_skip" in tags_found: NO_SKIP_TAGS = True + +if args.debug: + print('Before args.skip: ' + str(args.skip) + ' | skip_analysis: ' + str(skip_analysis) + ' - if true because no tag change') -if args.skip and "liq_cue_skip" in tags_found and tags_found["liq_cue_skip"] == True: - skip_analysis = True -if args.skip and "liq_cue_file" in tags_found and tags_found["liq_cue_file"] == True: +if args.skip: + if "liq_cue_skip" in tags_found and tags_found["liq_cue_skip"] == True: + skip_analysis = True + +if "liq_cue_file" in tags_found and tags_found["liq_cue_file"] == True: skip_analysis = True +if args.debug and args.skip: + print('args.skip is enabled: ' + str(args.skip)) +if args.debug: + print('After args.skip: ' + str(args.skip) + ' | skip_analysis: ' + str(skip_analysis)) + if args.force and skip_analysis != True: result = analyse( filename=args.file, @@ -1298,7 +1308,7 @@ else: if args.write and NO_SKIP_TAGS: #and not args.skip if args.debug: print('START: writing autocue tags for '+args.file) - write_tags(args.file, result, args.replaygain, NO_SKIP_TAGS) + write_tags(args.file, result, args.replaygain, NO_SKIP_TAGS) #args.skip if args.debug: print('FINISHED: autocue tags written for '+args.file) From abfc870e462ee69e8c4d2e5927b54e259deee586 Mon Sep 17 00:00:00 2001 From: Tom Taylor <975744+t0mtaylor@users.noreply.github.com> Date: Tue, 13 Aug 2024 02:03:01 +0100 Subject: [PATCH 4/5] code tidy, liq_cue_file should be false when skip is enabled --- cue_file | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/cue_file b/cue_file index 0576abd..8917a07 100755 --- a/cue_file +++ b/cue_file @@ -131,7 +131,7 @@ SUSTAINED_LOUDNESS_DROP = 40.0 # max. percent drop to be considered sustained BLANKSKIP = 5.0 # min. seconds silence to detect blank NICE = False # use Linux/MacOS nice? SKIP = False # force skip reprocessing of file if tags already exist -NO_SKIP_TAGS = False # allow new tags to be writen to file (when write enabled) unless skip tag exists and skip arg is set +NO_SKIP_TAGS = False # allow new tags to be writen to file (when write enabled) unless skip tag exists and skip arg is set # These file types can be handled correctly by ffmpeg safe_ext = [ @@ -480,16 +480,11 @@ def add_missing(tags_found, target=TARGET_LUFS, blankskip=0.0, noclip=False): tags_found["liq_sustained_ending"] = False if not "liq_cue_file" in tags_found: - tags_found["liq_cue_file"] = False + tags_found["liq_cue_file"] = True if not "liq_cue_skip" in tags_found: tags_found["liq_cue_skip"] = False - if args.skip: - tags_found["liq_cue_file"] = True - tags_found["liq_cue_skip"] = True - tags_found["liq_blankskip"] = 0.0 - # if not "liq_cross_duration" in tags_found: # tags_found["liq_cross_duration"] = tags_found["liq_cue_out"] - tags_found["liq_cross_start_next"] @@ -918,11 +913,11 @@ def write_tags(filename, tags={}, replaygain=False, writeSkipTag=False): tags_new["replaygain_track_gain"] += " dB" tags_new["replaygain_track_range"] += " dB" tags_new["replaygain_reference_loudness"] += " LUFS" - - + if writeSkipTag: tags_new["liq_cue_skip"] = True - + tags_new["liq_cue_file"] = False + tags_new["liq_blankskip"] = 0.0 if replaygain: # delete unwanted tags @@ -1280,7 +1275,7 @@ if args.debug and args.skip: if args.debug: print('After args.skip: ' + str(args.skip) + ' | skip_analysis: ' + str(skip_analysis)) -if args.force and skip_analysis != True: +if args.force or skip_analysis != True: result = analyse( filename=args.file, target=args.target, @@ -1305,7 +1300,10 @@ else: # eprint(result) -if args.write and NO_SKIP_TAGS: #and not args.skip +if not args.skip: + NO_SKIP_TAGS = True + +if args.write and NO_SKIP_TAGS: if args.debug: print('START: writing autocue tags for '+args.file) write_tags(args.file, result, args.replaygain, NO_SKIP_TAGS) #args.skip From ede7f820184dc61dfa5ec7f19561bebfc66058db Mon Sep 17 00:00:00 2001 From: Tom Taylor <975744+t0mtaylor@users.noreply.github.com> Date: Tue, 13 Aug 2024 20:16:30 +0100 Subject: [PATCH 5/5] liq_cue_file must be set to true for Azuracast to read autocue tags --- cue_file | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cue_file b/cue_file index 8917a07..307c510 100755 --- a/cue_file +++ b/cue_file @@ -916,7 +916,7 @@ def write_tags(filename, tags={}, replaygain=False, writeSkipTag=False): if writeSkipTag: tags_new["liq_cue_skip"] = True - tags_new["liq_cue_file"] = False + tags_new["liq_cue_file"] = True tags_new["liq_blankskip"] = 0.0 if replaygain: