We are delighted to announce the release of Liquidsoap 2.2.0! It is now available on our release page and should be available via opam shortly!
This release comes almost 4 months after the last stable release from the 2.1.x release cycle and 14 months (!) after
forking the 2.2.x release branch! It includes some exciting changes in track muxing/demuxing, HLS, sound processing,
and more. See below for a detailed list!
✨ New features
Here are the highlights:
🎛️ Multitrack
This is by far the biggest change in this release! This brings the ability to demux and remux tracks inside sources, making it possible to:
- Encode video with multiple audio tracks
- Create audio-only and audio/video streams from the same content, for instance, a regular audio stream and one with the studio’s video.
- Drop or specify which metadata or track marks track should be used.
- Apply specific audio effect or encoding to different tracks
And much more! The full documentation is here. We plan on expanding this support in the future in particular to allow track selection based on language, encoded content, etc.
🏷️ HLS metadata
At last! We now support metadata in HLS streams using a timed ID3 stream for the mpegts container and plain ID3v2 tags
for adts, mp3, ac3, and eac3 formats. There is currently no support for metadata with mp4 containers.
This feature is enabled by default, so you might want to check if it impacts your listeners before pushing it to
production. It can be turned off by setting id3 to false on your HLS streams.
Full documentation is here.
🎨 Colored logs
Small change but not the least important! Logs are now colored by default when printed on the console. This finally makes it possible to read logs with a high level of details!
We are aware of the need for more developer tooling and quality-of-life improvements! In the next release cycle, we hope to work on code formatting, highlighting, and more!
🕸️ New HTTP API
Interacting with your scripts is essential and, for this, web interfaces and APIs are really useful. In order to make our HTTP server easier to use, we wrote a new web API that is very close to node express’ API and should be fairly easy to use! The documentation is here.
These changes also included a revamping of our SSL support which is now modular and with a new TLS optional support!
🎚️ Native stereotool support
While committed to open-source through and through, we also do want to meet our users where they are. To this end, it seems that a lot of them want to use the proprietary stereotool audio processing. Up until this version, the only option was via the external command line encoder and this was not satisfactory.
With this release, it is now possible to use the shared library distributed by the author, which provides support for a
new stereotool internal operator that is much easier to integrate. See the documentation
here.
📟 Records enhancements
As part of the language changes required for multitrack, we now support the following operations on records:
Record spread:
let {foo, bar, ...rest} = someRecord
let otherRecord = { bla = "blo", ...someRecord }
Additionally, we now support optional record methods, for instance:
def f(x) =
if x?.foo == null() then
print("x does not have method foo")
else
print("x has method foo")
end
end
🪢 Support for YAML parsing/rendering
Following the recent JSON parsing feature, we now support YAML parsing in a very similar way as json.
🔮 Memory optimization
While we are aware that memory consumption with this release may have increased a bit due to ongoing changes, we have done our best to introduce more ways to control it and understand its usage.
In particular, we now support the alternative jemalloc memory allocator, enabled in all our release assets and
configurable via the internal settings.
We also introduced two new audio content formats, pcm_s16 and pcm_f32 that can be used to store audio internally as,
resp., 16-bit signed integers or 32-bit floating point numbers. Our default internal format is OCaml’s native 64-bit
floating point numbers.
We also added a new track.audio.defer operator that can be used to buffer large amount of audio data without impacting
performances.
You can read more about memory utilization in liquidsoap here.
🐪 Switch to dune and javascript runtime
While perhaps more exciting to developers, the project has now fully moved to the OCaml dune builder. This provides an
extra level of flexibility, In particular, we were able to extract the code that is specific to the liquidsoap language,
that is everything that pertains to parsing/evaluating/type checking without the streaming and system-specific operators
and export it as an online playground. We’re not sure yet what we’ll do with it. It
might be possible, for instance, to write a javascript backend to use liquidsoap scripts with the
Web media APIs!
🕵️ Versioning and release assets
For a little over a year now, we have switched to rolling release cycles with maintenance and bugfixes applying only
to the current release cycle. Regular releases are tagged vX.Y.Z (for instance v2.2.0) on GitHub and docker while
ongoing releases are tagged rolling-release-vX.Y.Z.
When an initial release, for instance, 2.2.0, is being worked on, bugfixes and user issues are addressed for users
using the 2.1.x releases. While we would like to extend support, this is the best that we can do with our limited
resources!
rolling-release-vX.Y.Z tags denote the releases being worked on. For stable release branches, this would be for
instance, rolling-release-v2.2.1 after release v2.2.0. For a yet-to-be released initial version, this would be for
instance rolling-release-v2.3.x. We try our best to make those releases as bug-free as possible. Using one of them to
test your production script also guarantees the fastest response to bugs and issues!
For release assets, we try to maintain two packages for debian and ubuntu distributions, one with the latest LTS or
stable and one with a recent release. The new minimal assets are, as the name suggests, minimal builds. They contain
a limited set of features and standard library operators. Minimal builds are intended for most production run and should
limit the risk of issues such as segfault, etc. If your script can run with it, we recommend it over the fully featured
builds.
For each release asset, you can consult the associated .config file to see which features are enabled.
Docker release images are located at: savonet/liquidsoap:v2.2.0. The release tag may be updated if needed. You can use
git sha-based images to pick a fixed build, e.g. savonet/liquidsoap:<sha>.
Lastly, we may update the list of release assets on the GitHub release page. If you are looking for a permanent release asset links make sure to check out savonet/liquidsoap-release-assets.
🧮 Migration guide
We listed most of the migration issues you might run into on this page. The detailed changelog below may also help.
As a reminder, we strongly recommend testing your script in a staging environment, even between minor releases, to make sure that everything is working correctly before pushing a new liquidsoap version to production!
📖 Changelog
The full shebang!
2.2.0 (2023-07-21)
New:
- Added support for less memory hungry audio formats, namely
pcm_s16andpcm_f32(#3008). - Added support for native osc library (#2426, #2480).
- SRT: added support for the
passphrase,pbkeylen, andstreamid; added native type for srt sockets with methods; moved stats to socket methods, addedsocket()method on srt input/outputs (#2556). - HLS: added support for ID3 in-stream metadata (#3154) and custom tags (#2898).
- Added support for FLAC metadata (#2952).
- Added support for YAML parsing and rendering (#2855).
- Added support for the proprietary shared stereotool library (#2953).
- Added TLS support via
ocaml-tls(#3074). - Added
video.align. - Added
string.index. - Added support for ffmpeg decoder parameters to allow decoding of raw PCM stream and file (#3066).
- Added support for unit interactive variables: those call a handler when their value is set.
- Added support for id3v2
v2.2.0frames and pictures. - Added
track.audio.deferto be used to buffer large amount of audio data (#3136). - Added
runtime.locale.forceto force the system’s locale (#3231). - Added support for customizable, optimized
jemallocmemory allocator (#3170). - Added
source.dropto animate a source as fast as possible. - Added in-house replaygain computation:
source.replaygain.computeto compute the replaygain of a source.file.replaygainto compute the replaygain of a file.
- Added support for ImageLib to decode images.
- Added support for completion in emacs based on company (#2652).
- Added syntactic sugar for record spread:
let {foo, gni, ..y} = xandy = { foo = 123, gni = "aabb", ...x}(#2737). - Added
file.{copy, move}(#2771). - Detect functions defining multiple arguments with the same label (#2823).
- Added
null.map. - References of type
'aare now objects of type(()->'a).{set : ('a) -> unit}. This means that you should usex()instead of!xto get the value of a reference. Setting a reference can be done both byx.set(v)andx := v, which is still supported as a notation (#2881). - Added
ref.makeandref.map. - Added
video.board,video.graph,video.info(#2886). - Added the
pico2waveprotocol to perform speech synthesis using Pico TTS (#2934). - Added
settings.protocol.gtts.langto be able to selectgtts’ language, addedsettings.protocol.gtts.optionsto be able to add any other option (#3182). - Added
settings.protocol.pico2wave.langto be able to selectpico2wavlanguage (#3182). - Added
"metadata_url"to the default list of exported metadata (#2946). - Added log colors!
- Added
list.filter_mapandlist.flatten. - Added
medialibto store metadata of files in a folder and query them (#3115). - Added
--unsafeoption (#3113). This makes the startup much faster but disables some guarantees (and might even make the script crash…). - Added
string.split.first(#3146). - Added
string.getter.single(#3125).
Changed:
- Switched to
dunefor building the binary and libraries. - Changed
cryto be a required dependency. - Changed default character encoding in
output.harbor,output.icecastoutput.shoutcasttoUTF-8(#2704). - BREAKING: all
timeoutsettings and parameters are nowfloatvalues and in seconds (#2809). - BREAKING: in
output.{shoutcast,icecast}:- Old
icy_metadatawas renamed tosend_icy_metadataand changed to a nullablebool.nullmeans guess. - New
icy_metadatanow returns a list of metadata to send with ICY updates. - Added
icy_songargument to generate default"song"metadata for ICY updates. Defaults to<artist> - <title>when available, otherwiseartistortitleif available, otherwisenull, meaning don’t add the metadata. - Cleanup, removed parameters that were irrelevant to each operator, i.e.
icy_idinoutput.icecastand etc. - Make
mountmandatory andnamenullable. Usemountasnamewhennameisnull.
- Old
reopen_on_errorandreopen_on_metadatainoutput.fileand related operators are now callbacks to allow dynamic handling.- Added the
reopenmethod tooutput.file. - Added support for a Javascript build and interpreter.
- Removed support for
%definevariables, superseded by support for actual variables in encoders. - Cancel pending append when skipping the current track on the
appendsource. - Errors now report proper stack trace via their
tracemethod, making it possible to programmatically point to file, line, and character offsets of each step in the error call trace (#2712). - Reimplemented
harborhttp handler API to be more flexible. Added a new node/express-like registration and middleware API (#2599). - Switched default persistence for cross and fade-related overrides to follow documented behavior. By default,
"liq_fade_out","liq_fade_skip","liq_fade_in","liq_cross_duration"and"liq_fade_type"now all reset on new tracks. Usepersist_overridesto revert to the previous behavior (persist_overrideforcross/crossfade) (#2488). - Allow running as root by default when the docker container can be detected using the presence of a
/.dockerenvfile. id3v2argument of the%mp3encoder was changed to"none"or version number to allow to choose the metadata version.trueis still accepted and defaults to version3. Switched to our internal implementation so that it does not requiretaglibanymore.- Moved HLS outputs stream info as optional methods on their respective encoder.
- Changed
self_syncininput.ffmpegto be a boolean getter, changedself_syncininput.httpto be a nullable boolean getter. Setself_synctotrueininput.httpwhen an icecast or shoutcast server can be detected. - Add the
sortedoption tofile.ls. - Add the
buffer_lengthmethod toinput.external.rawaudioandinput.external.wav(#2612). - Added full
OCamlbacktrace astraceto runtime errors returned from OCaml code. - Removed confusing
let json.stringifyin favor ofjson.stringify(). - Font, font size, and colors are now getters for text operators (
video.text,video.add_text, etc.) (#2623). - Add the
on_cycleoption tovideo.add_textto register a handler when cycling (#2621). - Renamed
{get,set}envintoenvironment.{get,set}. - Renamed
add_decoder,add_oblivious_decoderandadd_metadata_resolverinto, respectively,decoder.add,decoder.oblivious.add,decoder.metadata.add. - Deprecated
get_mime, addedfile.mime.libmagicandfile.mime.cli, madefile.mimetryfile.mime.libmagicif present andfile.mime.cliotherwise, changed returned value when no mime was found tonull(). - Return a nullable float in
request.duration. - Removed
--list-plugins-jsonand--list-plugins-xmloptions. - Added
--list-functions-jsonoption. - Removed built-in use of
strftimeconversions in output filenames, replaced by an explicit call totime.string(#2593). - Added nullable default to
{int,float,bool}_of_stringconversion functions, raise an exception if conversion fails and no default is given. - Deprecated
string_ofin favor ofstring(#2700). - Deprecated
string_of_floatin favor ofstring.float(#2700). - Added
settings.protocol.youtube_dl.timeoutto specify a timeout when using theyoutube-dlprotocol (#2827). Useyt-dlpas the default binary for the protocol. - The
sleeperoperator is now scripted (#2899). - Reworked remote request file extension resolution (#2947).
- REMOVED
osx-secure-transport. Doubt it was ever used, API was deprecated upstream (#3067). - Renamed
rectangletoadd_rectangle, and similarly forline.
Fixed:
- The randomization function
list.shuffleused inplaylistwas incorrect and could lead to incorrectly randomized playlists (#2507, #2500). - Fixed srt output in listener mode to allow more than one listener at a time and prevent the listening socket from being re-created on listener disconnection (#2556).
- Fixed race condition when switching
input.ffmpeg-based urls (#2956). - Fixed deadlock in the
%externalencoder (#3029). - Fixed crash in encoders due to concurrent access (#3064).
- Fixed long-term connection issues with SSL (#3067).