Skip to content

Commit

Permalink
v3.0.0 – New adjustable blank skip feature
Browse files Browse the repository at this point in the history
  • Loading branch information
Moonbase59 committed Jun 12, 2024
1 parent 534297b commit ec05101
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 43 deletions.
68 changes: 68 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,73 @@
# autocue changelog

### 2024-06-12 – v3.0.0

#### New feature

- **Adjustable minimum silence length** for blank skipping,
i.e., cueing out early when silence is found in the track,
for instance from a long pause and "hidden tracks".
- A much requested feature many have been waiting for (including myself)!
- This new function adds _almost no extra CPU load_.
- Longer silent parts and "hidden tracks" will be _detected accurately_,
without many false triggers, and the track cued out early, with a
perfect transition.
- Long tail handling, overlay point detection (next song start) and
fading stay active as before—they just work from the new cue-out point.
- The new cue-out point will be set _at the beginning_ of the specified
and detected silent part. We don’t want to produce "dead air", after all.
- `cue_file` still supports the `-b`/`--blankskip` option, which will
use a default of `2.5` seconds minimum silence duration.
- **Note:** If using _only_ `-b`/`--blankskip` _without a value_, you
should use it as the _last parameter_ and then add a `--` before the
filename, to signify "end of parameters". This is standard syntax and
you probably know it already from other programs.
**Example:**
```
$ cue_file -kfwrb -- "Nirvana - Something in the Way _ Endless, Nameless.mp3"
```
- You can add the desired duration after `-b`/`--blankskip` in seconds,
it is a new optional parameter.
**Example:**
```
$ cue_file -k -f -w -r -b 5.0 "Nirvana - Something in the Way _ Endless, Nameless.mp3"
```
- In Liquidsoap/AzuraCast, you can use this _setting_ which defaults
to zero (`0.00`) and means "disabled":
```
settings.autocue.cue_file.blankskip := 0.0
```

#### Recommendation

- I recommend _not_ to use this feature on jingles, dry sweepers or liners,
advertisements and podcast episodes. Especially spoken text can contain
some pauses which might trigger an early cue-out.
- Nobody wants a podcast episode to end in the middle, or even risk losing
revenue from ads!
- You can easily prevent this and **turn off blank skipping**
- by tagging a file with the `liq_blankskip` tag set to `0.00`,
- by _not_ using `cue_file`’s `-b`/`--blankskip` option when writing tags,
- by prefixing `annotate:liq_blankskip=0.00` on playlists.
- An annotation has precedence over a file tag.
- In some special cases we **automatically turn off blank skipping:**
- SAM Broadcaster: _Song category_ is _not_ "Song" (S). For all other
categories like News (N), Jingles (J), Ads (A), etc. We look for
the `songtype` tag here. This is useful if you use a common music
library, or have files that have been tagged using SAM categories.
- AzuraCast: _Hide Metadata from Listeners ("Jingle Mode")_ is selected
for a playlist. This sets a `jingle_mode=true` annotation we honor.

#### Breaking Changes

- `liq_blankskip` is now a _float_, not a _boolean_ anymore!
- **Re-tagging recommended!** Sorry for that, but I hope the new functionality
will outweigh the effort.
- Both `cue_file` and `autocue.cue_file.liq` will handle the "old" tags
gracefully, using `0.00` for former `false` and your setting or
the default of `2.50` s for former `true`.
- `0.00` (zero) now means "blankskip disabled".

### 2024-06-11 – v2.2.1

- Make JSON override switchable (`settings.autocue.cue_file.use_json_metadata`).
Expand Down
47 changes: 34 additions & 13 deletions autocue.cue_file.liq
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
# Allows passing annotate/database overrides to
# cue_file, to reduce re-analysis runs even more.
# 2024-06-11 - Moonbase59 - v2.2.1 Make JSON override switchable
# 2024-06-11 - Moonbase59 - v3.0.0 Add variable blankskip (0.0=off)
# - BREAKING: `liq_blankskip` now flot, not bool anymore!
# Pre-v3.0.0 tags will be read graciously.

# Lots of debugging output for AzuraCast in this, will be removed eventually.

Expand All @@ -36,7 +39,7 @@ let settings.autocue.cue_file.version =
settings.make(
description=
"Software version of autocue.cue_file. Should coincide with `cue_file`.",
"2.2.1"
"3.0.0"
)

let settings.autocue.cue_file.path =
Expand Down Expand Up @@ -115,8 +118,12 @@ let settings.autocue.cue_file.noclip =
let settings.autocue.cue_file.blankskip =
settings.make(
description=
'Skip blank (silence) within song (get rid of "hidden tracks").',
false
"Skip blank (silence) within track if longer than `blankskip` seconds \
(get rid of \"hidden tracks\"). \
Sets the cue-out point to where the silence begins. Don't use this \
with spoken or TTS-generated text, as it will often cut the message \
short. Zero (0.0) to switch off.",
0.0
)

let settings.autocue.cue_file.unify_loudness_correction =
Expand Down Expand Up @@ -257,24 +264,34 @@ def cue_file(~request_metadata, ~file_metadata, filename) =
# For standalone Liquidsoap, the ultimate override is `liq_blankskip`.
# This can even be used to switch blank skipping ON if is globally off.
blankskip = ref(blankskip)
blankskip := list.assoc.mem("jingle_mode", meta) ? false : blankskip()
blankskip := list.assoc.mem("jingle_mode", meta) ? 0.0 : blankskip()

# SAM Broadcaster compat: Switch blankskip off for all songtypes != "S"
if list.assoc.mem("songtype", meta) then
if meta["songtype"] != "S" then
blankskip := false
blankskip := 0.0
end
end

# Handle annotated `liq_blankskip`, the ultimate switch
# Pre-v3.0.0 compatibility: Check for true/false (now float)
if list.assoc.mem("liq_blankskip", meta) then
blankskip := bool_of_string(default=false, meta["liq_blankskip"])
b = meta["liq_blankskip"]
if b == "true" then
blankskip := blankskip()
elsif b == "false" then
blankskip := 0.0
else
blankskip := float_of_string(default=0.0, b)
end
m := list.assoc.remove("liq_blankskip", m())
m := list.add(("liq_blankskip", string.float(decimal_places=2, blankskip())), m())
end

log(
level=3,
label=label,
"Blank (silence) skipping active: #{blankskip()}"
"Blank (silence) skipping active: #{blankskip() > 0.0}, set to #{blankskip()} s"
)

log(
Expand Down Expand Up @@ -307,7 +324,10 @@ def cue_file(~request_metadata, ~file_metadata, filename) =
]
)
if noclip then args := list.add('-k', args()) end
if blankskip() then args := list.add('-b', args()) end
if blankskip() > 0.0 then
#args := list.add('-b', args())
args := ['-b', string.float(blankskip(), decimal_places=2), ...args()]
end
if write_tags then args := list.add('-w', args()) end
if write_replaygain then args := list.add('-r', args()) end
if force_analysis then args := list.add('-f', args()) end
Expand All @@ -317,8 +337,8 @@ def cue_file(~request_metadata, ~file_metadata, filename) =
if use_json_metadata then
# write metadata to temp file for cue_file to pick up
tempfile := file.temp("cue_file", ".json")
json_meta = meta_json_stringify(compact=true, meta)
log(level=4, label=label, "Writing metadata to #{tempfile()}: #{json_meta}")
json_meta = meta_json_stringify(compact=true, m())
log(level=3, label=label, "Writing metadata to #{tempfile()}: #{json_meta}")
log(level=3, label=label, "Writing metadata to #{tempfile()}")
file.write(
data=json_meta,
Expand Down Expand Up @@ -394,7 +414,7 @@ def cue_file(~request_metadata, ~file_metadata, filename) =
liq_amplify: string,
liq_amplify_adjustment: string,
liq_reference_loudness: string,
liq_blankskip: bool,
liq_blankskip: float,
liq_blank_skipped: bool,
liq_true_peak: float,
liq_true_peak_db: string
Expand Down Expand Up @@ -432,7 +452,7 @@ def cue_file(~request_metadata, ~file_metadata, filename) =
else
[...res, entry]
end,
meta,
m(),
result()
)

Expand Down Expand Up @@ -694,6 +714,7 @@ def cue_file(~request_metadata, ~file_metadata, filename) =
("liq_loudness", list.assoc("liq_loudness", result())),
("liq_loudness_range", list.assoc("liq_loudness_range", result())),
("liq_reference_loudness", list.assoc("liq_reference_loudness", result())),
("liq_blankskip", list.assoc("liq_blankskip", result())),
("liq_blank_skipped", list.assoc("liq_blank_skipped", result())),
("liq_true_peak", list.assoc("liq_true_peak", result())),
("liq_true_peak_db", list.assoc("liq_true_peak_db", result())),
Expand Down Expand Up @@ -755,7 +776,7 @@ log(level=2, label="autocue.cue_file",
# settings.autocue.cue_file.longtail := 15.0 # seconds
# settings.autocue.cue_file.overlay_longtail := -15.0 # extra LU
# settings.autocue.cue_file.noclip := false # clipping prevention like loudgain's `-k`
# settings.autocue.cue_file.blankskip := false # skip silence in tracks
# settings.autocue.cue_file.blankskip := 0.0 # skip silence in tracks
# settings.autocue.cue_file.unify_loudness_correction := true # unify `replaygain_track_gain` & `liq_amplify`
# settings.autocue.cue_file.write_tags := false # write liq_* tags back to file
# settings.autocue.cue_file.write_replaygain := false # write ReplayGain tags back to file
Expand Down
Loading

0 comments on commit ec05101

Please sign in to comment.