Skip to content

Releases: savonet/liquidsoap

Liquidsoap Rolling Release 2.5.x

Pre-release

Choose a tag to compare

@github-actions github-actions released this 18 Aug 19:49
86d008f

This release provides liquidsoap assets before they are published as a new versioned release.

You can use it to install the latest stable code before it is published and test/prepare your production environment for it.

Rolling releases can also be useful for us to quickly detect and report bugs before the final published release!

⚠️ Warning ⚠️
Assets in this release will be deleted. If you are looking for permanent links to release assets, please head over to https://github.com/savonet/liquidsoap-release-assets/releases

For more details about our release process, please checkout https://github.com/savonet/liquidsoap#release-details

2.5.0 (unreleased)

New:

  • Added getter(t) type annotation syntax for getter types (#5078).
  • Added atomic(f), which runs f without letting any other atomic section run at the same time. Script code now runs on several cores at once, so a group of changes that must not be observed half-done — writing several references together, or checking a flag and setting it — needs to say so.
  • Added r.exchange(v), which sets a reference and returns the value it replaced in one
    indivisible step. Now that script code runs on several cores at once, a flag guarding
    work that must happen only once cannot be read and set separately: two threads both see
    it unset and both do the work.
  • Added source.content operator returning an associative list of frame field names to their content format, track.format returning the content format of a single track, and format.description returning a typed record description of a content format.
  • Renamed the internal video content type from canvas to yuv420p, which better reflects the
    actual content; the content itself is still organized as a canvas of yuv420p layers. Type
    annotations such as source(video=canvas) must be updated to source(video=yuv420p).
  • Added subtitles support as a dedicated content type. Includes native SRT decoding,
    FFmpeg subtitle encoding/decoding (%subtitle), passthrough for bitmap subtitles
    (%subtitle.copy), callbacks (on_subtitle), transformations (subtitles.map),
    and dynamic insertion (subtitles.insert) (#4860, #4861, #4862).
  • Video dimensions (video.frame.width/height) are now automatically detected
    from the first decoded video file. This can be disabled by setting settings.video.detect_dimensions
    to false or by explicitly setting the video dimensions.
  • Added support for XML .nfo sidecar files as a metadata source (enable_nfo_metadata,
    file.nfo.metadata) (#4910).
  • Added Icecast-compatible streaming server (icecast.server) with support for source
    authentication, mount points, relay, and per-listener encoding (#4915).
  • Added dedicated encoder mode to output.harbor: mount points can now be served with
    a single shared encoder instead of per-listener encoding (#5003).
  • Rewrote JACK I/O using native OCaml bindings, removing the dependency on the bjack
    C library (#5028).
  • Added settings.clock.child.max_buffer, the amount of data an operator such as
    crossfade or stretch may buffer from its child source. Operators sharing a child
    source must consume it at converging rates; past this value, an error names the operator
    that fell behind instead of letting the buffer grow without bound (#5267).
  • Source callbacks (on_track, on_metadata, on_frame, on_connect, ...) now return a
    release method taking the callback back, so a function registering on a source it is given
    can release what it registered instead of keeping it alive for as long as that source lives.
    Existing scripts are unaffected, the returned value being still ignorable; see the new
    source callbacks page.
  • Added source.collect_callback_releases, which runs a function and gathers the callbacks
    it registered on a given list of sources into a single release. This is what switch and
    cross use, available to scripts calling their own functions more than once.
  • Clocks created by script code running after startup are now started by the code that
    created them, through an effect handler scoped to that code, instead of a global registry
    polled after every script application.
  • Added the source(_) type: a source whose content is unknown. Any source can be used where
    one is expected, so sources of different content can be held together, for instance in a list,
    without unifying their content types, while nothing can be assumed about what a source(_)
    streams.
  • Added domain to thread.run, pinning the function and every rerun to the
    scheduler worker on that domain. An object is only collected by a GC on the
    domain that allocated it, which makes this the way to ask for one.

Changed:

  • Liquidsoap now requires OCaml 5.5 to build.

  • Scheduled work — requests, harbor clients, script callbacks, thread.run handlers — is now fully concurrent,
    taking advantage of OCaml 5's core-based concurrency, so a busy instance keeps up with much more of it at once.
    Heavy work in a callback or a request resolution no longer stalls playback either.

  • Added settings.scheduler.legacy, a fail-safe for a script that concurrent execution breaks: tasks run on
    threads, one at a time, as they did before. It will be removed in a later version once the concurrent
    scheduler has settled.

  • Deprecated settings.scheduler.generic_queues, settings.scheduler.fast_queues and
    settings.scheduler.non_blocking_queues: the scheduler sizes itself from the number of cores and there is
    nothing left to tune. They now only configure the legacy scheduler, and setting them without it logs a
    warning. settings.scheduler.blocking_tasks replaces them, limiting how many slow tasks — request
    resolutions, thread.run handlers, last.fm submissions — may run at once. It defaults to one per
    domain and never fewer than 8, so a machine with few cores keeps room to run several at once. Raising it pays off
    when those tasks truly wait. A task that uses a core instead of waiting on one, such as probing a
    file for its decoder, only takes cores the streaming threads need.

  • Clocks run as scheduler tasks rather than each on a thread of its own. A clock that is ahead
    of real time parks and is resumed by the scheduler's timer, so a machine running many outputs
    has as many busy threads as cores instead of one per clock competing for them. A clock
    catching up yields its domain to the others after each burst of frames. Ticks run directly on
    a scheduler domain, one at a time, ahead of request resolution.
    A clock driving JACK input or output keeps a thread of its own, since it rests by waiting on the
    JACK server. settings.clock.task := false restores a thread per clock everywhere.

  • When the scheduler is busy, quick work is served before slow work: the server, then request resolutions, then
    long tasks such as last.fm submissions. The order used to be arbitrary and often favoured the slow ones.

  • Bindings written without let accept the same targets as let — destructuring patterns, field paths and type
    annotations — so (x, y) = (1, 2), r.field = 1 and (n : int) = 2 are all valid, and an invalid left-hand side
    reports what is allowed instead of a bare syntax error. A leading binding inside the { … } function shorthand
    still requires let, since { x = 1 } is a record literal.

  • String interpolation accepts any expression: "#{m["key"]}", "#{ {a = 1}.a }" and nested interpolated strings
    now work. Error positions inside #{ … } point at the offending code rather than at the start of the string.

  • http.transport.ssl and http.transport.tls: key parameter is now optional in server mode when the certificate file also contains the private key.

  • switch, fallback, rotate, random: replaced the parallel list parameters
    (transitions, transition_length, override, track_sensitive,
    replay_metadata, single, weights) with per-source composition methods
    (composition_type, track_sensitive, replay_metadata, single, weight,
    on_select, on_leave) registered on every source, switching behavior now
    defaulting automatically based on whether a source is file-based or live. See the
    new source composition page, and
    doc/content/migrating.md for the parameter-by-parameter mapping (#5074).

  • Switching now fades by default: a switch cutting into a playing track fades the
    leaving source out over up to settings.source.composition.max_fade seconds (default
    1.) when it carries only PCM audio, handoffs happening at a track boundary being
    unchanged since nothing was interrupted. Use source.composition.legacy_on_select to
    restore the previous behavior.

  • Deprecated fallback.skip. A source with track_sensitive set to false can be cut
    into mid-track and the file composition profile skips a source it was left in the
    middle of, so fallback([main, fallback_source.{track_sensitive = getter(false)}])
    now does natively what the operator polled for on every frame.

  • Simplified the cross/crossfade implementation: start_duration and end_duration are
    replaced by a single duration parameter, the metadata overrides liq_cross_start_duration
    and liq_cross_end_duration by liq_cross_duration, and the start_duration() and
    end_duration() methods by cross_duration(). Autocue-specific code and the
    assume_autocue setting are removed (#4893).

  • Add metadata from all sources/tracks in add operators (#4892).

  • Make sure script fails on on_close errors in output.file to prevent
    fatal errors from being ignored. Use reopen_on_error to ignore errors
    from the callback.

  • Allow implicit casting of an integer as a float (#2887).

  • Removed settings.decoder.ffmpeg.max_interleave_delta. The setting was never read by
    the decoder; stream interleaving is bounded by
    settings.decoder.ffmpeg.max_interleave_duration ...

Read more

Liquidsoap Rolling Release 2.4.x

Pre-release

Choose a tag to compare

This release provides liquidsoap assets before they are published as a new versioned release.

You can use it to install the latest stable code before it is published and test/prepare your production environment for it.

Rolling releases can also be useful for us to quickly detect and report bugs before the final published release!

⚠️ Warning ⚠️
Assets in this release will be deleted. If you are looking for permanent links to release assets, please head over to https://github.com/savonet/liquidsoap-release-assets/releases

For more details about our release process, please checkout https://github.com/savonet/liquidsoap#release-details

2.4.6 (unreleased)

Fixed:

  • Fixed fade.in/fade.out amplifying by infinity while a liq_fade_*_delay was
    pending on a track whose fade duration is 0..
  • cross and crossfade with their default deduplicate=true no longer drop
    the metadata of a track that repeats the one before it, e.g. a single file on
    a loop, which silenced the handlers a script registers after the operator.
    cross now marks the outgoing track's metadata where it replays it into the
    transition, so the repeat it is meant to remove is told apart from a fresh
    announcement rather than guessed at by comparing values (#5360)
  • metadata.deduplicate no longer compares across a track mark, for the same
    reason (#5360)
  • cross and crossfade now fire on_track on every crossing. The default
    transition mixes the two tracks and carries no track mark of its own, so
    handlers registered after a crossfade only ever saw the first track (#5379)
  • Fixed a synchronous callback hanging or looping forever when it reads the
    frame of the source it is registered on, e.g. calling s.time() inside
    s.on_metadata(synchronous=true, ...) (#5361)
  • Fixed file.watch losing track of a file that gets replaced rather than
    written in place: an inotify watch follows the inode, so a writer doing the
    usual write-to-temporary-then-rename silenced the watcher for good. The
    containing directory is watched instead. playlist with reload_mode="watch"
    also waits for a burst of events to settle before reloading, so a writer that
    truncates before writing no longer triggers two racing reloads and plays
    tracks out of order (#3343)
  • Anything logged while evaluating the script, deprecation warnings in
    particular, was silently dropped when liquidsoap exited before reaching the
    streaming loop, e.g. on No output defined, nothing to do. (#3375)
  • Liquidsoap no longer exits when started as root: it now logs a warning
    instead. Container detection through /proc/1/cgroup does not work under
    cgroup v2, which made the check fire on plain docker run (#3406)
  • Fixed output.file and the other piped outputs ignoring the delay returned by
    reopen_on_error when the failure happened while opening the file: the output
    stays Idle in that case and retried on every streaming cycle (#2437)
  • output.file reports Unix errors, e.g. Permission denied when creating the
    destination directory, as system errors, like it already did for Sys_error
    (#2437)
  • rotate and random name the switch they build internally after themselves,
    e.g. schedule_rotate, instead of leaving it with an anonymous id (#3851)
  • Fixed clock.create documenting and reporting sync modes, "CPU" and
    "unsynced", that it does not accept. The accepted values are "auto",
    "cpu", "none" and "passive"
  • Added Unifier path compression to avoid unbounded deref cost growth (#5257)
  • Fixed unbounded buffer growth (#5287)
  • Fixed sequence dropping the first chunk of a source, along with its
    metadata, when the source it follows leaves no room in the current frame.
    This showed up as the track after a cross/crossfade transition built with
    sequence keeping the previous track's metadata until the next track
    boundary (#5296).
  • Fixed ICY metadata negotiation in output.harbor: the Icy-MetaData request
    header was looked up before normalization, so clients never received
    in-stream metadata (thanks to @uhthomas, #5279)
  • Fixed srt restart logic (#5309)
  • Fixed HLS segment boundaries drifting away from segment_duration: a segment
    closing on a stale split position re-anchored the next boundary on it instead
    of the segment grid. The drift rate depends on the encoder's frame size, so
    variants using different codecs, e.g. HE-AAC and AAC-LC, diverged from each
    other without bound (#5319).
  • Fixed a clock's on_error handler being defeated by the shutdown of the
    source it just contained: putting the failed source to sleep runs its cleanup,
    e.g. output.file.hls closing its current segment when persist_at is set,
    and an error raised there escaped uncaught and killed the process. Shutdown
    errors are logged instead (#5260)
  • Fixed switch and sequence not notifying their new sync source when
    switching child, leaving the clock synced on the source they just left
  • Fixed the type unifier retaining collapsed variables forever, by merging
    unified variables using union by rank (#5342)
  • Fixed Audioscrobbler base url (#5404, @iibaranov-IG)

Liquidsoap 2.4.5

Choose a tag to compare

@github-actions github-actions released this 15 Jun 19:46

2.4.5 (2026-06-15)

New:

  • Added remove and remove_request_id methods to request.queue to remove
    a specific request from the queue, also available as a telnet remove command (#5237)
  • Improved error messages in playlist parsers to include more context about the
    source of the error
  • Added audio/aiff, audio/x-aiff and audio/x-wavpack entries to
    the default settings.http.mime.extnames table so protocol.http resolves
    AIFF and WavPack URLs to their real extensions instead of the .osb
    fallback.

Fixed:

  • Fixed crash when external input (input.process, input.ffmpeg, etc.) encounters an EOF (thanks to @MikaSappi, #5139)
  • Fixed harbor.remove_http_handler discarding all registered handlers except the one being removed
  • Fixed crash in crossfade/cross when source.skip is called from outside the clock thread, e.g. from a harbor.http handler or thread.run (#5194)
  • Fixed memory leak in Strings.Mutable (#5231)

Optimized:

  • Clock sync-source propagation is now push-based and O(1) per tick instead of scanning all sources (#5133)
  • Stream format/kind dispatch now uses O(1) int-indexed array lookup instead of iterating a queue (#5136)
  • Optimized content_length and timed blit hot paths (#5137)
  • Chunk total length is now cached in the chunks record to avoid recomputation (#5140)
  • Chunk length is now pre-computed on lift (#5135)
  • Watcher before/after cycle callbacks are only registered when watchers are actually present
  • WeakQueue now uses geometric doubling and a RW-lock for faster concurrent access (#5118)
  • Use direct Int comparison functions in stream hot paths

Liquidsoap 2.4.4

Choose a tag to compare

@github-actions github-actions released this 20 Apr 14:30

This is a quick follow-up to Liquidsoap 2.4.3.

A big thank you to everyone who tested 2.4.3 and reported issues so swiftly — your feedback made this patch possible! We recommend skipping 2.4.3 entirely and migrating directly to 2.4.4.

Notable fixes

  • Shared encoder crash: A crash that could occur when multiple streams shared the same encoder, caused by incorrect child clock controller initialization, is now fixed.
  • input.harbor 403 response: Clients connecting to an already-taken mountpoint now receive a proper 403 error instead of a confusing "Unknown error".
  • Sub-clock leak: A leak that could cause gradual resource growth when on_sleep deregistered a source during has_stopped is resolved.
  • is_binary charset detection: A subtle bug that caused is_binary to skip charset conversion for non-UTF-8 text content is now corrected.

Liquidsoap 2.4.3

Choose a tag to compare

@github-actions github-actions released this 11 Apr 21:09

This is the third bugfix release of Liquidsoap 2.4.x.

This release has been extensively tested and should be rock solid. We still recommend trying it on your staging environment before rolling out to production.

This release is intended to be the last of the 2.4.x branch. We've already started working on 2.5.x and there are some exciting things in store!

⚠️ Note for Ubuntu Noble users: this is the last release that includes binary packages for Ubuntu Noble. To keep up with the latest FFmpeg releases, we need to move forward to more recent Ubuntu versions.

New features

  • Raw string syntax {|...|} and {id|...|id}: a new string literal form where no escape sequences or string interpolation (#{}) are processed. This is especially useful in automated or user-facing setups where external input (filenames, URLs, user-provided values) is embedded directly in a script — with regular strings, a value containing #{...} would be silently evaluated as code. Raw strings prevent this entirely, making scripts that handle untrusted input safer and more predictable.

Notable fixes

  • Audio glitches with crossfade: Two separate issues caused clicks or audio gaps when using cue points and crossfades together — both are now resolved.
  • HLS fMP4 audio+video: Multiplexed HLS streams using fragmented MP4 containers were broken; this is now fixed.
  • Playlist initialization slowdown: A performance regression that made large playlists slow to start is gone.
  • Process I/O reliability: Several edge cases around reading stdout/stderr and handling EINTR signal interruptions have been addressed, making external process integration more robust.
  • Sequence resource cleanup: The sequence operator now releases sources it no longer needs early, reducing resource usage in scripts with many fallback sources.
  • Better error messages: Invalid_value errors now include a call stack, making it much easier to track down where an invalid value originated at runtime.

📢 6th Liquidshop Workshop — Friday, 29 May 2026!

We're gearing up for the 6th Liquidshop workshop and we'd love to see you there! If you'd like to share what you've built or how you use Liquidsoap, please consider contributing a talk — and everyone is welcome to attend. We love connecting with the community!


2.4.3 (2026-04-11)

New:

  • Added raw string syntax {|...|} and {id|...|id} for strings
    with no escape sequences (#4959)
  • Added optional replay_metadata and add_new_track to
    the buffer operator to replay latest metadata and insert
    track marks when the buffer becomes available again.
  • Added support for array options in ffmpeg filters (#4799)

Changed:

  • DEPRECATED telnet/server request.on_air command is enabled when
    settings.request.deprecated_on_air_metadata is true.
  • Add back missing "status" telnet/server command for outputs.
  • Reduced default buffer size throughout the app to improve memory efficiency
    (#4919)
  • Refactored XML parsing to be type-driven, support optional fields with
    custom element name aliases (#4926, #4927)
  • Removed self_sync parameter from input.jack and output.jack (#5017)
  • Make posix build target paths configurable via env vars (#5046)

Fixed:

  • sequence now releases unused sources early, reducing resource usage when
    earlier sources in the sequence are no longer needed (#5082)
  • Improved error messages: Invalid_value errors now include the call stack
    to help pinpoint the origin of the invalid value (#5090)
  • Fixed clicks/glitches when combining liq_cue_in with liq_fade_in due to fade.in firing too late on new tracks (#5019)
  • Prevent crashing when getting out-of-bound mark in split_frame (#5054)
  • Fixed clock source detach when clock is running (#5051)
  • Fixed ?? operator type inference in conditional branches (#4922)
  • Prevent double nullable types (#4925)
  • Make active stereotool really be active.. (#4882)
  • Fixed fMP4 HLS support for audio+video streams (#4841)
  • Fixed crossfade clocks inconsistencies leading to weird caching audio glitches (#4851)
  • Fixed first frame of new track getting lost when crossfading with fade.in duration is set to 0. (#4887)
  • Fixed crash with concurrent stop/start operations (#4849)
  • Fixed metadata leak from underlying ffmpeg ogg demuxer in ffmpeg stream
    decoder (#4848)
  • Fixed performance regression when initializing playlist (#4913)
  • Make sure that we read all stdout/stderr before considering a process closed. (#4918, #4934, #4941)
  • Fixed EINTR signal interruption in process I/O, read, and flush operations (#4947, #4949, #4951)
  • Improved string binary detection heuristics by checking for valid UTF-8 and max length; added settings.string.max_printable_length configuration key
  • Make sure output.file does not create files without data (#4899)
  • Fixed content type propagation through free type variables (#4988)
  • Improved runtime error reporting by wrapping low-level exceptions into proper
    runtime errors (#5004)
  • Fixed syslog support and added it to build configuration detection (#5009)
  • Fixed sub-clock accumulation causing gradual CPU growth over time (#5032)

Liquidsoap 2.4.2

Choose a tag to compare

@github-actions github-actions released this 17 Jan 16:46

This is the second bugfix release of liquidsoap 2.4.x.

The first bugfix had some issues with sources not being properly cleaned up so this one is coming out right off the bat to fix this!

But, fear not, we have also added some exciting new changes to counterbalance!

As usual, please try this version on a staging/testing environment. Otherwise, we do believe it is safe to upgrade from any 2.4.0 or 2.4.1 version.

2.4.2 (2025-01-17)

New:

  • Added pretty-print of clocks and source graphs! Use via --describe-<clocks/sources> in the command line or clocks.dump and clocks.dump_sources on telnet/server! (#4837, #4836)

Changed:

  • Batch calls to thread.when to preserve performances, warn when using thread.when too intensively (#4832)
  • Added pretty-print of telnet help list of commands. This might break compatibility with automated telnet readers! (Remember: telnet is a user-facing API, not designed for machine consumption!).

Fixed:

  • Fixed sources leaks in source.dynamic (#4835)
  • Optimized Queues implementation: fast, atomic access, slow, mutex-protected mutation (#4831)

Liquidsoap 2.4.1

Choose a tag to compare

@github-actions github-actions released this 10 Jan 18:09

⚠️ This release has issues, please head over to https://github.com/savonet/liquidsoap/releases/tag/v2.4.2 ⚠️

This is the first bugfix release of the 2.4.x release cycle!

Most of the heavy lifting in terms of internal rewrite and new features has now been done we are now fully committed to bringing more stability and long-term enhancements to the framework.

This release should be safe to upgrade to for all users on the 2.4.0 release. In general, we strongly suggest migrating your code to our latest release: our resources are limited and the latest stable release if where we put all our efforts to fix bugs.

As usual, we do recommend testing the release on a staging/testing environment before pushing it to your production runtime.

A few new things with this release, mostly to facilitate user's life:

  • Initial metadata support for the %ffmpeg encoder to help support container-level setup such as DVB Service and Provider names (see: #4665)
  • start/stop server/telnet commands for outputs
  • A new settings.syslog.level to help set the syslog level.

Other important enhancements concern clocks and dynamic source collection, which is still a hotspot for us. If you're using a lot of dynamic sources and outputs, make sure to keep in touch with us, we want to keep making this as stable and usable as possible but we do not always think about all the possible use-case!

Lastly, the issues where large covert art binary data kept showing up in logs when logging metadata should finally be fixed! These strings are now tagged as binary internally and filtered out during logging/printing!

Here's the full changelog:

Liquidsoap 2.4.1 (2025-01-10)

New:

  • Added support for explicit metadata to pass to the output
    when creating a %ffmpeg encoder (#4667)
  • Added start/stop telnet commands for outputs.
  • Added settings.syslog.level to set syslog level (#4686)
  • Added active parameter to stereotool and output.stereotool (#4749)
  • Added file.mime.extension to get the file extension's associated
    with a MIME/content-type as registered in settings.http.mime.extnames

Changed:

  • Do not normalize sources in mix by default.
  • Added json.value to make it possible to mix different value
    types when returning json values (#4712)
  • Allow referring to pulseaudio devices by name (#4732)
  • output.shoutcast: make dj argument a getter.
  • Exclude metadata listed in settings.encoder.metadata.cover
    from automatic metadata recoding. (#4690)

Fixed:

  • Fix input.harbor initial metadata when switching with
    fades (#4736)
  • Fix audio artifact in crossfade transitions (#4739)
  • Make sure that sources re-used in source.dynamic are never
    inadvertently cleaned up (#4713)
  • Fix sources not being properly collected (#4670)
  • Raise a proper error on parse error raised during %include
    parsing.
  • Don't print metadata coverart string (#4730)
  • Make sure fetch always fetches a new request in request.dynamic (#4745)
  • Fixed start/stop logic in output.harbor (#4666)
  • Fixed fade.in/fade.out logic w.r.t. override metadata (#4759)
  • Fixed video.cover

Liquidsoap 2.4.0

Choose a tag to compare

@github-actions github-actions released this 18 Nov 04:39

The first release of the 2.4.x release cycle is out! 🎉✨

This release includes several new features focused on improving user's experience!

We have summarized the most important changes in our 2.4.0 blog post: https://www.liquidsoap.info/blog/2025-08-11-liquidsoap-2.4.0/

This release has been carefully tested and does not include any major rewrite of the core components. Therefore, we highly recommend switching to it as soon as possible.

As usual, however, we recommend testing your script in a staging environment before pushing to production. Please report any regression or issues to us and we will work on it as soon as time allows.

⚠️ Warning ⚠️
Assets in this release will be deleted. If you are looking for permanent links to release assets, please head over to https://github.com/savonet/liquidsoap-release-assets/releases

For more details about our release process, please checkout https://github.com/savonet/liquidsoap#release-details

2.4.0 (2025-09-01)

New:

Language:

  • Allow destructing function arguments using the same patterns as for
    variable assignment (#4562)
  • Enhanced labeled arguments syntax (#4526)
  • Add warning when erasing top-level variables (#4518)
  • null can now be used directly without having to call null().
    null(value) calls are still valid and can be used to create
    non-null values with nullable types. Calls to null() are marked
    as deprecated (#4516)
  • Added liquidsoap.script.path that contains the path to the current
    script's file, if available.

Core:

  • BREAKING: Most callbacks have been moved to source methods and are now
    executed asynchronously by default. See migration notes for all the
    details.
  • BREAKING: Added new file-to-file external decoder.add API. This
    makes it much easier and safer to write external decoders (#4531)
  • Deprecated insert_metadata, added default insert_metadata method on
    every source (#4541)
  • Added client certificate support to http.transport.tls (#4589, @DelilahHoare)

Utilities:

  • Added cron.parse, cron.{add,remove} and a cron thread
    to allow registration of cron-like asynchronous tasks (#4579)
  • Added LUFS-based per-track loudness correction (#4545)

Changed:

Language:

  • BREAKING: Error methods have been removed by default.
    Use error.methods to get them! (#4537)
  • Make sure that let { foo = gni } = v assigns a value to
    gni but not to foo (#4561)

Core:

  • Turned initial memory compaction on by default. This
    has show to greatly reduce initial memory consumption.
  • Improved source and clock naming (#4497)
  • Support for ImageLib has been removed. The library is not
    maintained anymore and causes issues with dangling external
    processes (#4595)

Utilities:

  • Deprecated replaygain operator, introduced unified
    normalize_track_gain which works with both ReplayGain
    and LUFS (#4545)

Fixed:

  • Fixed issues with autocue start_next. This brings autocue's behavior
    inline with its expectation but can change existing script's output (#4605)
  • Fix error when loading script path having non-ascii characters in them
    (#4343)
  • Fix concurrent inline encoders (#4638)
  • Fix error with interactive variables (#4592, @myeungdev)
  • Prevent concurrent reload and request fetch in playlists (#4316)
  • Don't mark source as ready until their clock has started. (#4496)
  • Fixed mutex deadlock caused by aggressive inlining (#4540)
  • Fixed segfault when using SRT on windows (#4538)
  • Fixed memleak in ffmpeg inline encoder (#4501)
  • Fixed tmp: protocol logic (#4544)
  • Fixed dangling file descriptors with file.*.stream (#4639, reported by @limebar)

Liquidsoap Rolling Release 2.3.x

Pre-release

Choose a tag to compare

This release provides liquidsoap assets before they are published as a new versioned release.

You can use it to install the latest stable code before it is published and test/prepare your production environment for it.

Rolling releases can also be useful for us to quickly detect and report bugs before the final published release!

⚠️ Warning ⚠️
Assets in this release will be deleted. If you are looking for permanent links to release assets, please head over to https://github.com/savonet/liquidsoap-release-assets/releases

For more details about our release process, please checkout https://github.com/savonet/liquidsoap#release-details
\n\n
2.3.4 (unreleased)

Changed:

  • Improved source and clock naming (#4497)

Fixed:

  • Don't mark source as ready until their clock has started. (#4496)

Liquidsoap 2.3.3

Choose a tag to compare

@github-actions github-actions released this 26 May 17:37

This is the third bug-fix release of the 2.3.x release cycle! 🎉

This release was triggered by a segfault caused by a memory corruption in the new lufs C code that was introduced with release 2.3.2. If you are using this code and this release, please consider upgrading.

Otherwise, the release includes minor fixes. It should be suitable for production but can be updated at your earliest convenience.

This release is also the first one to include builds for both versions of OCaml: 4.14.x and 5.x. As of now, the memory usage with Ocaml 5 is still significantly higher and not suitable for production in our opinion. However, we will need to make the switch one day or another so we decided to start providing both build to make sure that we stay compatible with the latest ocaml 5 code and can continuously test and improve memory optimization with this version.

⚠️ WHILE WE HAVE YOUR ATTENTION! ⚠️

Want to hear more from the liquidsoap community? Want to present your liquidsoap setup or the people using it?

Please consider attending our 5th liquidshop workshop!! More info: https://www.liquidsoap.info/liquidshop/5/

2.3.3 (2025-05-16)

New:

  • input.srt: add ipv6only to allow to bind only to ipv6 addresses.
    Set it to true when bind_address is ipv6.
  • Allow HLS segment names to contain sub-directories.
  • Implicitly convert ffmpeg raw audio data, making it much more practical
    to write scripts using the raw ffmpeg format (#4478)

Changed:

  • Made defer more user-friendly by operating directly on generic source(audio=pcm('a))
    sources. Renamed old defer to defer.pcm_s16
  • dtools, duppy and xmlplaylist have been moved into the liquidsoap code
    base and will no longer be developed or required as stand-alone packages (#12582)
  • Changed default value of metadata.map strip argument to true and insert_missing
    to false Added settings.metadata.map.strip and settings.metadata.map.insert_missing
    configuration keys to revert to previous defaults. (#4447)

Fixed:

  • Do not send empty metadata to shoutcast servers (#4408)
  • Automatically close file descriptor opened via scripted values with a log message
    warning of file descriptor leaks (#4481)
  • Fixed segfault in new lufs C code introduced with release 2.3.2 (#4490)