- Fix situation where supplied JSON data could still overwrite
cue_fileresults even if a file’sliq_cue_filetag was set totrue, meaning thecue_fileresults should be preferred in any case. - For freshly generated/downloaded news or time announcements, this could lead to erroneous cut-offs or loudness jumps in case AzuraCast’s media checker hadn’t yet picked up the new data. It would then overwrite the actual file data with stored values from the database.
- New
liq_cue_filehandling, allows to ignore overrides forcue_filedata if true. This is mainly for fast-changing files like news or time, for which LS/AzuraCast might not yet have updated the metadata.- not set — default behaviour (metadata can override
cue_fileresults) false— don’t autocue (still use metadata if present)true—cue_fileresults override metadata (special use cases)
- not set — default behaviour (metadata can override
For a more thorough explanation, see the FAQ
- Make
durationnon-overridable by existing metadata or annotations.- The real file duration is not a tag, but determined otherwise.
- If such a tag is found, it is typically unusable, incorrect or in a different format.
- AzuraCast might annotate the duration from an earlier version of the file, because the media scan is only done once in a while. With frequently changing files of the same name, like syndicated news or time announcements, this could be problematic.
- Fixed a situation where
cue_filewould read a string duration from ffprobe for audio stream #0, which led to an error in the AzuraCast log like this:2024/07/02 16:03:27 [autocue:2] Error while processing autocue: error(kind="json",message="Parsing error: json value cannot be parsed as type {duration: float, _}",positions="at autocue.liq, line 814 char 6 - line 826 char 10") cue_filenow outputs the same duration for both tag reading and full analysis mode.cue_filewill not anymore write adurationtag to files. That was a newly introduced bug in v4.0.4.
- Allow to override results via JSON even after having done a fresh analysis (automatic or forced), for ultimate flexibility when using
cue_filefor pre-processing. You can now add fades, ramp or hook points, or do other calculations and feed the results intocue_filefor tagging. Use with care, because some values are dependent on others. In any case,cue_filewill ever only write tags beginning withliq_and (if requested)replaygain_. - Prevent some strange errors that could happen when piping something into
cue_fileand JSON input was notstdin. We now useffmpeg -nostdinto prevent it reading input that was meant forcue_file. - Don’t write all
liq_*tags (could have side effects), but only those known (seecue_file --helpfor current list). - Streamlined tag conversion code a little.
- Changed default of
-x/--extraandsettings.autocue.cue_file.overlay_longtailfrom-15.0LU to-12.0LU, requested by @RM-FM and the community. Together with the-d/--dropdefault change from60.0to40.0, this makes for a "tighter" playout and doesn’t lose too much of long or sustained endings. - Updated README and Presentation as well, to reflect the new default.
- Allow recognition of values like
-8.33dB(without blank before "dB") inautocue.cue_file.liqas well (it’s already incue_file). Note: Metadata with units should be used with a blank in between value and unit. - Streamline "sustained endings" code.
- Add some diagnostics output to
cue_fileon the console to easier find and fix problems:Overlay times shown asOverlay: -23.50 LUFS, Longtail: -38.50 LUFS, Measured end avg: -48.40 LUFS, Drop: 29.09% Overlay times: 336.50/348.50/0.00 s (normal/sustained/longtail), using: 348.50 s. Cue out time: 353.00 s0.00mean a calculation has not been done or wasn’t needed, like longtail above. Diagnostics are output tostderr, so don’t interfere with the JSON onstdout. - Changed default for "sustained endings" loudness drop from
60.0% to40.0%. This was a wish from the community and makes for a little tighter/denser song overlap. - Modify to your liking by using
cue_file’s-d/--dropparameter orsettings.autocue.cue_file.sustained_loudness_drop := 40.0in Liquidsoap/AzuraCast. A value of0.0switches the "sustained endings" feature completely off (behaviour like in older versions).
- Bug fix: Catch index error in sustained ending calculation if we’re already at the end of the track. This could happen in very rare cases, if no earlier overlay start than the end of the track could be found.
- Added song that exposes this situation to the test set:
- Camel - The Great Marsh
-
Even better transitions, using both "longtail" logic and the new "sustained endings" feature by @RM-FM, which we could even improve on, in a collaborative work. We are really happy with the results!
-
Combined with the existing blankskip handling (whose default is now 5.0 seconds instead of 2.5 s, to avoid false triggers), we are able to handle the greatest variety of possible song endings with great transitions. Be it a cold end, a long fade, a trick ending, an unexpected noise, chord, riff or vocal at the end — we catch them all. Pure listening enjoyment!
-
If you’re interested, here’s part of our testing set. Try it out for yourself!
Songs with difficult endings:- Beatles, The - Strawberry Fields Forever
- Ben Folds Five - Underground
- Black, Mary - Columbus
- Darkness on Demand - Quicksand
- Def Leppard - Let It Go
- Electric Light Orchestra - Don't Bring Me Down
- ella_henderson_rudimental_-_alibi_feat._rudimental
- Global Deejays - Get Up (feat. Technotronic)
- J.B.O. - Ein Fest
- Nirvana - Something in the Way _ Endless, Nameless
- Pink Floyd - Goodbye Cruel World
- Queen - Bohemian Rhapsody
- radiomonster.fm_-_dropin_01
- R.E.M. - Losing My Religion
- robbie_williams_-_angels
- Stürmer, Christina - Ich lebe
- test-5-15-5-15-5s
- testfiles.txt
- TLC - Waterfalls
- Toto - Africa
- Vega, Suzanne - Tom's Diner (vocals only version)
- Walker, Tom - Leave a Light On
- Who, The - Won't Get Fooled Again
- Wonder, Stevie - Another Star
-
New "sanity check" that (also) checks if your external
cue_fileand the Liquidsoap code have matching versions (a suggestion by John Chewter (@JohnnyC1951)), and shuts down otherwise. After your settings, simply use this code:# Your settings go here... # Check Autocue setup, print result, shutdown if problems # The check results will also be in the log. # Returns a bool: true=ok, false=error. We ignore that here. # Set `print=true` for standalone scripts, `false` for AzuraCast. ignore(check_autocue_setup(shutdown=true, print=true))
- Always use the
check_autocue_setupfunction after your settings, in both standalone scripts and AzuraCast. It will not only check versions, but also set the crossfading duration to a correct value, based on your fade-out setting.
-
New informational boolean value
liq_sustained_endingincue_fileresult, file tags, and Liquidsoap metadata. It shows whether the "sustained endings" feature has been used to determine the "start next song" overlay point. -
Analysed timings shown on console, in case you manually tag a file or just want to check the results. This output don’t affect normal operation, it is done to
stderr:Start next times: 257.50/261.30/0.00 s (normal/sustained/longtail), using: 261.30 s. Cue out time: 263.20 s
- 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_filestill supports the-b/--blankskipoption, which will use a default of2.5seconds minimum silence duration.- Note: If using only
-b/--blankskipwithout 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/--blankskipin 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":Don’t forget to change this setting if you usedsettings.autocue.cue_file.blankskip := 0.0trueorfalsebefore!
- 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 ad revenue!
- You can easily prevent this and turn off blank skipping
- by tagging a file with the
liq_blankskiptag set to0.00, - by not using
cue_file’s-b/--blankskipoption when writing tags, - by prefixing
annotate:liq_blankskip=0.00on playlists. - An annotation has precedence over a file tag.
- by tagging a file with the
- 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
songtypetag 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=trueannotation we honor.
- SAM Broadcaster: Song category is not "Song" (S). For all other categories like News (N), Jingles (J), Ads (A), etc. We look for the
liq_blankskipis 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_fileandautocue.cue_file.liqwill handle the "old" tags gracefully, using0.00for formerfalseand your setting or the default of2.50s for formertrue. 0.00(zero) now means "blankskip disabled".
- Make JSON override switchable (
settings.autocue.cue_file.use_json_metadata). Defaults totrue. - Minor code cleanup (thanks @vitoyucepi).
- JSON override tags for cue_file in temp file: Allows passing annotate/database overrides to cue_file, to reduce re-analysis runs even more.
- Prepare for third-party pre-processing software:
- A JSON file (or stdin) can now be used to set or override any of the known tags (see help). Values from JSON override values read from the audio file’s tags.
- This can be used, for example, to set values from a database (like AzuraCast’s cue and fade data from their Visual Cue Editor).
cue_filemight still decide a re-analysis being necessary, so it’s wise to re-consolidate the data aftercue_filehas returned its results.
- More robust variable reading from tags or JSON:
- Booleans can be bool or string
- Typechecking on tags with unit suffixes, especially
liq_true_peak, which was a "dBFS"-suffixed string in v1.2.3 and now is a linear float.
- Added
liq_fade_in&liq_fade_outto known tags. We don’t use these, but pre-processors might want to set them. - More advance example in
test_autocue.cue_file.liqthat shows how annotations can be used to play 15-second snippets of songs.
- Fix ffmpeg erroneously treating
.oggfiles with cover image as video. The.oggfiletype is now handled by Mutagen.
- Show autocue.cue_file version number in Liquidsoap log on startup, to ease bug hunting. Your
cue_fileshould use the same version.
The log entry looks like this:
2024/06/05 16:16:03 [autocue.cue_file:2] You are using autocue.cue_file version 2.0.2.
2024/06/05 16:16:03 [autocue.cue_file:2] Assure that the external "cue_file" has the same version!
- Fix small bug when reading already stored
liq_true_peakthat contained adBFSvalue from v1.2.3.
Version 2.0.0 is out! It offers the chance to write ReplayGain data to audio files, in addition to the Liquidsoap/Autocue tags.
This is useful for station owners that can’t or don’t want to use audio tracks that have been pre-replaygained. You can now add ReplayGain data to songs and thus ensure the analysis won’t be done over and over again.
This is an additional option to the existing write_tags feature and will only work when write_tags is enabled. Based on our file analysis, it will save (and overwrite) ReplayGain Track data, such as the gain value, the reference loudness, integrated loudness and true peak info.
The logic is inside cue_file, so it can as well be used for pre-processing your files without the need of other tools. Autocue & ReplayGain—all in one!
The cue_file help now shows the file formats it supports, and the tags it knows about. cue_file will automatically detect if Mutagen is installed and offer you a whopping 20 more filetypes to work with!
liq_true_peak(in dBFS) has been renamed toliq_true_peak_db.- A new
liq_true_peakhas been added that stores the peak value as expected and needed by ReplayGain. - Both
cue_fileandautocue.cue_file.liqmust be updated to v2.0.0 for everything to work correctly. - It is advisable to install Mutagen on the system running Liquidsoap, or in the AzuraCast Docker container. Doing this gets you more file and tag types you can work with, and safer/more compatible tagging. Mutagen can usually be installed with
pip3 install mutagen(preferred), orsudo apt install python3-mutagen(often older versions, distros don’t update that often).
First public version with a numbering scheme. We use SemVer:
- MAJOR.MINOR.PATCH
- MAJOR increments when API-breaking changes are released.
- MINOR increments with new functionality compatible with the existing API.
- PATCH increments when API-compatible bugfixes and minor changes are done.
The version numbers of autocue.cue_file and the external cue_file binary should usually be the same.
Introducing:
- Mutagen (Pyhon tagging library) should be installed and allows writing tags to many file and tagging formats.
- ffmpeg is now only used for tagging where we know it’s safe.
- Much better error checking:
- Writing tags only to "known good" file types.
- Gracefully skip writing to write-protected files/folders/drives.
cue_filehas got better CLI params checking and much improved help.
- First released built-in implementation in AzuraCast Rolling Release #caeea9d.
In preparation for later merge with master branch:
- Rename
autocue2.liqtoautocue.cue_file.liq. - Rename
test_local.liqtotest_autocue.cue_file.liq. - Use same
cue_fileas inmasterbranch, updateautocue.cue_file.liq. - Add settings to
test_autocue.cue_file.liqsoautocuedoes the right thing (hopefully).
- Started a CHANGELOG.md, so interested parties can follow.
- Streamlined
autocue2code, removed unnecessary stuff. - Change and solidify metadata handling. It now ensures that:
- Metadata seen in both
autocue2:protocol andenable_autocue2_metadata()mode. - All "processing flags" always seen, like
liq_autocue2liq_blankskipjingle_mode
replaygain_track_gain&liq_amplifyalways unified whensettings.autocue2.unify_loudness_correctionistrue. ReplayGain, if it exists, takes precedence.- All possible combinations of
enable_autocue2_metadata(),autocue2:protocol, andannotate:actually work correctly. It is still considered a user error ifenable_autocue2_metadata()is used in conjunction withautocue2:, since this would invoke processing twice. - Priorities are always respected, so the user can override automatically calculated values using tags in the files, annotations or AzuraCast’s Visual Cue Editor, for example. Priorities are, from lowest to highest:
- Calculated values from
cue_file/autocue2. liq_*andreplaygain_track_gainas tags in the audio file.- Annotated settings like
liq_blankskip=false. These include all settings coming from AzuraCast’s Visual Cue Editor and Advanced Edit Media settings.
- Calculated values from
- Metadata seen in both
You can now do really wild things, like enabling autocue2 processing globally, and still create something like a "sampling" playlist which plays 30s-snippets of a list of songs. And even with the simplest crossfade command possible!
enable_autocue2_metadata()
...
radio = playlist(
prefix='annotate:liq_cue_in=30.,liq_cue_out=60.,liq_cross_duration=2.5:',
'Classic Rock.m3u'
)
radio = crossfade(radio, fade_in=0.1, fade_out=2.5)Or you can exclude your video files from processing, for example:
video_playlist_night = playlist(
id="video_playlist_night",
prefix="annotate:liq_autocue2=false:",
mode="randomize", reload_mode="watch", videos_night_folder)The sky is the limit!