DISCLAIMER: I am not a programmer, but only a copy-paster-enthusiast who shares what he could figure out. Therefore, it is possible that knowledgeable experts may find some points or formulations incorrect or ridiculous. The submission of this material assumes that you have a some level of knowledge of Liquidsoap. This example is relevant for Liquidsoap version 2.2.3 The library for converting text to graphics is GDI. Anyway, the following articles and tutorials will help you figure it out: Creating a 24/7 stream (Liquidsoap) Creating a 24/7 stream part 2(Liquidsoap)
Adding more and more images and text to the scene of my 24/7 stream, at some point I came across the fact that Liquidsoap stopped coping with the synchronization of all sources, giving out in the log “We must catchup n
seconds”.
This became especially critical when switching from the live stream (where there are no overlays added via Liquidsoap) back to the playlist (input.rtmp -> playlist
): in some cases, “We must catchup” began to occur indefinitely, which led to severe lags and, as a result, restarting the script.
It is likely that this problem concerns cases where video files are used as a playlist – where audio and video are a single source. Or in view of the features of a specific system assembly. At least, when I tried to cause this situation, where looped animation and an mp3 playlist are used on another VPS, then no matter how many layers of text I add, nothing like this happened.
Auxiliary Buffer
I immediately thought that it would be nice to group some of the graphic elements and calculate them separately. After some time of unsuccessful attempts to build crutches or move the group to a separate clock
, I still decided to approach the issue from the other side:
- create an empty source –
blank()
- put all the necessary graphic elements on it –
video.add_image() / video.add_text()
- create a buffer for this source –
buffer()
, to relieve the load on Liquidsoap - superimpose this source on the main video source via the
add()
operator
I did not immediately come up with this idea, because I was not sure that blank()
creates a transparent video source, and the add
operator will work correctly when the buffer and main sources are superimposed. But, as you know, everything worked out and the problem with “We must catchup” was solved!
In the script, it looks something like this:
#playlist with video:
videos = playlist('/path/to/mp4/')
#an "empty" source:
overlay = blank()
#graphic elements attached to the overlay
overlay = video.add_image(..., overlay)
overlay = video.add_rectangle(..., overlay)
overlay = video.add_text(..., overlay)
#buffer assignment
overlay = buffer(max=2., overlay)
#overlay on top of a video playlist
videos = add([videos, overlay])
Delay
The buffer, depending on its maximum size, will create a delay when displaying elements equal to the max parameter set in seconds (a number with a dot). The minimum value I experienced is 2 seconds. But it is quite possible that it can be made even smaller. For example, 1.5 seconds or 0.75.
Based on this, all timing-sensitive elements should be superimposed on the main video source. Such as metadata (current/next tracks/covers), countdown and so on.
videos = playlist('/path/to/mp4/')
videos = video.add_text(..., current_song, videos)
videos = video.add_image(..., cover, videos)
overlay = blank()
overlay = video.add_image(..., overlay)
overlay = video.add_text(..., overlay)
overlay = buffer(max=2., overlay)
videos = add([videos, overlay])
If this material is useful to you and you have the opportunity,
then support the author and the site with a small tip:
https://app.lava.top/mikulski
Thanks💛