Explanation
This script will take 4 streams from a local running MistServer and combine them into a 2x2 grid for 1920x1080 resolution. Both the video compositor and the encoding are done through software, meaning the CPU will be used for both tasks. The encoding can be set to use a specific hardware encoder, however the compositor will be software only.
When streams are offline/unavailable an offline.ts
video can be loaded, shown and looped. If no valid path is given a black screen will be given until the source stream is available.
Usage
This script is meant to be ran using the executable input, ts-exec
specifically as:
ts-exec:/path/to/script.sh stream1 stream2 stream3 stream4
You will need to provide the stream names
within MistServer as stream1
, stream2
, stream3
, stream4
.
Need to knows
This script has the following dependencies:
- Gstreamer
- fallbacksrc
- A downloadable version of fallbacksrc is provided. Should your OS not be compatible you will need to try and compile your own. Steps how to do this in Ubuntu24 are provided.
Behaviour is as follows:
- First the offline video will be spawned in each grid
- Then a local MistServer will be contacted to load in every source
- Should a source go offline, the offline video will be shown
- Should a source go back online, the online video will be shown
- Only the first stream given will provide audio to the multiview.
- Sync is NOT guaranteed, a best effort will be done
- Expected delay is 3-10 seconds
Script
Make sure to save this in a location MistServer can reach & don't forget to make it executable through chmod +x script
#!/bin/bash
#Offline video file to show if a stream goes offine. Grabbed from VoD. Replace the path.
# For offline video pats it needs to contain `file://` and add another `/` for the starting path
OFFLINE="file:///media/vod/offline.ts"
#HTTP Port takes 8080 as default, replace if something else should be used
HTTPPORT=8080
#FALLBACKSRC - grabs internal streams using HTTP-TS. Inserts an offline image when not available
# To remove audio: Set the SRC1 stream to have ?audio=none and remove `! audioconvert ! audio/x-raw,channels=2,rate=48000,format=F32LE ! queue ! audmix.`
# To add other audio to the mux, remove ?audio=none and add `! audioconvert ! audio/x-raw,channels=2,rate=48000,format=F32LE ! queue ! audmix.` to the SRC2/3/4 lines.
SRC1="fallbacksrc immediate-fallback=true restart-on-eos=true uri=http://localhost:${HTTPPORT}/${1}.ts fallback-uri=${OFFLINE} name=s1 ! videoconvert ! videorate ! vidmix. s1. ! audioconvert ! audio/x-raw,channels=2,rate=48000,format=F32LE ! queue ! audmix. "
SRC2="fallbacksrc immediate-fallback=true restart-on-eos=true uri=http://localhost:${HTTPPORT}/${2}.ts?audio=none enable-audio=false fallback-uri=${OFFLINE} name=s2 ! videoconvert ! videorate ! vidmix."
SRC3="fallbacksrc immediate-fallback=true restart-on-eos=true uri=http://localhost:${HTTPPORT}/${3}.ts?audio=none enable-audio=false fallback-uri=${OFFLINE} name=s3 ! videoconvert ! videorate ! vidmix."
SRC4="fallbacksrc immediate-fallback=true restart-on-eos=true uri=http://localhost:${HTTPPORT}/${4}.ts?audio=none enable-audio=false fallback-uri=${OFFLINE} name=s4 ! videoconvert ! videorate ! vidmix."
#Compositor grabs src1 and src2 sets their width/height and places them into a 1920x1080 frame. Due to fallbacksrc they will never be removed upon disconnect and reappear.
MIX="compositor name=vidmix background=black \
sink_0::xpos=0 sink_0::ypos=0 sink_0::width=960 sink_0::height=540 \
sink_1::xpos=960 sink_1::ypos=0 sink_1::width=960 sink_1::height=540 \
sink_2::xpos=0 sink_2::ypos=540 sink_2::width=960 sink_2::height=540 \
sink_3::xpos=960 sink_3::ypos=540 sink_3::width=960 sink_3::height=540 \
"
# Make sure audio gets converted to audio/x-raw,channels=2,rate=48000,format=F32LE for avenc_aac compatibility.
# other audio encoders might be better depending on OS. faac is usuallly the default, however Ubuntu24 doesn't have it.
AUD="audiomixer name=audmix force-live=true ! avenc_aac ! queue ! muxer. "
gst-launch-1.0 -q \
${SRC1} \
${SRC2} \
${SRC3} \
${SRC4} \
${AUD} \
${MIX} ! video/x-raw, format=I420, width=1920, height=1080, framerate=60/1 ! x264enc speed-preset=ultrafast bframes=0 key-int-max=60 bitrate=6000 ! queue ! mpegtsmux name=muxer ! fdsink