OP25 Most elegant way to have two broadcastify feeds on one instance of multi_rx?

telvana

Member
Joined
Nov 19, 2014
Messages
87
Greetings,

I’d like to provide two feeds off of the same instance of multi_rx. I already have two dongles, and a single feed already running. What’s required to get the second feed going? In theory I can of course use multi_rx to provide both feeds, but how do I run the output through liquid soap? I am not very well versed in how it works, and would rather just ask for the best practice on how to do this. I’ve looked around and it doesn’t seem to be very well documented, unless I’ve missed something somewhere.

I had thought just running two instances of liquid soap would suffice, but it also seems like that’s a really messy way of doing it, not to mention likely unreliable and complicated to setup that way.

TIA

Current setup is multi_rx running a single feed to broadcastify, using Boatbod’s OP25 (master) Fork, running on an Nvidia Jetson nano. OS is Armbian (Debian) bullseye.
 

wgbecks

Active Member
Joined
Jan 17, 2005
Messages
919
Location
NE Wisconsin
You can confgure both feeds in Liquidsoap to run with either multiple instances of rx.py, or from separate voice channels configured in
the multi_rx.py applications. However, you'll need to assigne unique UDP wireshark ports to each instance or voice channel.

The following example liquidsoap script assumes Feed-1 is assigned to UDP port 23450 while Feed-2 is assigned to UDP port 23460.


op25.liq

#!/usr/bin/liquidsoap

# Example liquidsoap streaming from op25 to icecast
# (c) 2019-2021 gnorbury@bondcar.com, wllmbecks@gmail.com
#

set("log.stdout", true)
set("log.file", false)
set("log.level", 1)

# Make the native sample rate compatible with op25
set("frame.audio.samplerate", 8000)


input_1 = mksafe(input.external(buffer=0.25, channels=2, samplerate=8000, restart_on_error=false, "./audio.py -u 23450 -x 1.25 -s"))
input_2 = mksafe(input.external(buffer=0.25, channels=2, samplerate=8000, restart_on_error=false, "./audio.py -u 23460 -x 1.25 -s"))


# Consider increasing the buffer value on slow systems such as RPi3. e.g. buffer=0.25
# Longer buffer results in less choppy audio but at the expense of increased latency.



# OPTIONAL AUDIO SIGNAL PROCESSING BLOCKS
# Uncomment to enable
#
# High pass filter
#input_1 = filter.iir.butterworth.high(frequency = 200.0, order = 4, input_1)
#input_2 = filter.iir.butterworth.high(frequency = 200.0, order = 4, input_2)

# Low pass filter
#input_1 = filter.iir.butterworth.low(frequency = 3250.0, order = 4, input_1)
#input_2 = filter.iir.butterworth.low(frequency = 3250.0, order = 4, input_2)

# Compression
#input_1 = compress(input_1, attack = 15.0, gain = 2.0, knee = 1.0, ratio = 3.0, release = 60.0, threshold = -24.0)
#input_2 = compress(input_1, attack = 15.0, gain = 2.0, knee = 1.0, ratio = 3.0, release = 60.0, threshold = -24.0)

# Normalization
input_1 = normalize(input_1, gain_max = 6.0, gain_min = -6.0, target = -16.0, threshold = -40.0)
input_2 = normalize(input_2, gain_max = 6.0, gain_min = -6.0, target = -16.0, threshold = -40.0)


# LOCAL AUDIO
# Uncomment the appropriate line below to enable local sound
#
# Default audio subsystem
#out (input)
#
# PulseAudio
#output.pulseaudio(input)
#
# ALSA
#output.alsa(input)


# ICECAST STREAMING
# Uncomment to enable output to an icecast server
# Change the "host", "password", and "mount" strings appropriately first!
# For metadata to work properly, the host address given here MUST MATCH the address in op25's meta.json file
#
output.icecast(%mp3(bitrate=16, samplerate=22050, stereo=false), description="op25", genre="FEED GENRE-1",
url="", fallible=false, icy_metadata="false", host="BCFY_ASSIGNED_SERVER-1", port=80, mount="FEED-1", password="PASSWORD-1", mean(input_1))

output.icecast(%mp3(bitrate=16, samplerate=22050, stereo=false), description="op25", genre="FEED GENRE-2",
url="", fallible=false, icy_metadata="false", host="BCFY_ASSIGNED SERVER-2", port=80, mount="FEED-2", password="PASSWORD-2", mean(input_2))
 

telvana

Member
Joined
Nov 19, 2014
Messages
87
Awesome, I have no idea why I didn’t think to just double up the .liq configuration … lol. Thanks, I’ll get working on that tomorrow and report back if I’ve got any issues.
 

boatbod

Member
Joined
Mar 3, 2007
Messages
3,338
Location
Talbot Co, MD
Basic concept for multi_rx is that you define one trunking system (or however many you need), then as many channels as you want discrete streams, and give each channel it's own (non-consecutive) UDP port. In the liquidsoap script you define as many input streams as you need, and tie these in with the appropriate UDP port number inside the "audio.py" helper app.
 
Top