OP25 (boatbod) audio over network

Status
Not open for further replies.

jschmall

Member
Premium Subscriber
Joined
Jul 15, 2017
Messages
84
Location
Anderson, CA
I have a well functioning OP25 instance that has been up and running for some time. I also have a network PulseAudio server up and running as well as a liquidsoap server. That liquidsoap server is also the end point for my RTLSDR-Airband server and works fantastically.

I'd like to pipe the audio directly to Pulse from OP25 so that I can manipulate it in my liquidsoap server. What is the easiest way of doing this? Is it in the "destination:" line or would it be done a different way? Also, how can I ensure the tags move with that audio?
 

boatbod

Member
Joined
Mar 3, 2007
Messages
3,502
Location
Talbot Co, MD
I have a well functioning OP25 instance that has been up and running for some time. I also have a network PulseAudio server up and running as well as a liquidsoap server. That liquidsoap server is also the end point for my RTLSDR-Airband server and works fantastically.

I'd like to pipe the audio directly to Pulse from OP25 so that I can manipulate it in my liquidsoap server. What is the easiest way of doing this? Is it in the "destination:" line or would it be done a different way? Also, how can I ensure the tags move with that audio?
OP25 boatbod has pulse audio as a native capability; just change the audio "device_name" parameter to "pulse". Note that this may not work if you are running on a headless server because the pa daemon usually doesn't get started until log-on. With much fiddling around you can change that, but it's a serious PITA compared to jsut streaming direct to liquidsoap.

Your other option for sending the audio over a network is to change the UDP destination and run liquidsoap on a remote machine. That would require having a copy of audio.py and sockaudio.py python files on the remote machine too.
 

jschmall

Member
Premium Subscriber
Joined
Jul 15, 2017
Messages
84
Location
Anderson, CA
OP25 boatbod has pulse audio as a native capability; just change the audio "device_name" parameter to "pulse". Note that this may not work if you are running on a headless server because the pa daemon usually doesn't get started until log-on. With much fiddling around you can change that, but it's a serious PITA compared to jsut streaming direct to liquidsoap.

Your other option for sending the audio over a network is to change the UDP destination and run liquidsoap on a remote machine. That would require having a copy of audio.py and sockaudio.py python files on the remote machine too.
I will play around with the second option. I also thought about keeping the local liquidsoap instance in play and using a liquidsoap tunnel to send the audio to my other server. I’ll work on this later today.
 

boatbod

Member
Joined
Mar 3, 2007
Messages
3,502
Location
Talbot Co, MD
I will play around with the second option. I also thought about keeping the local liquidsoap instance in play and using a liquidsoap tunnel to send the audio to my other server. I’ll work on this later today.
For the remote UDP option, I recommend you first set up op25 to deliver the UDP across the network and get that working with audio.py on the remote machine. Once that's running, add the liquidsoap layer. Basically all you have to do is get audio.py running in a terminal on the appropriate udp port and it sits there listening for incoming packets and sends them to the sound subsystem.
 

jschmall

Member
Premium Subscriber
Joined
Jul 15, 2017
Messages
84
Location
Anderson, CA
For the remote UDP option, I recommend you first set up op25 to deliver the UDP across the network and get that working with audio.py on the remote machine. Once that's running, add the liquidsoap layer. Basically all you have to do is get audio.py running in a terminal on the appropriate udp port and it sits there listening for incoming packets and sends them to the sound subsystem.

So I have successfully moved one of my channels over to the new LS server. Had to move 3 python scripts, audio.py, sockaudo.py, and log_ts.py. Things seem to be working well including audio. However, I'm seeing the following in my LS logs:

Code:
2023/02/07 08:13:48 [input.external.rawaudio_0:5] Activations changed: static=[], dynamic=[mksafe:iir_filter_0:iir_filter_1:rms_0:on_frame_0:on_track_0:amplify_0:amplify_1:Redding_Public_Safety/Utilities:Reddin>
2023/02/07 08:13:48 [safe_blank:5] Activations changed: static=[mksafe:iir_filter_0:iir_filter_1:rms_0:on_frame_0:on_track_0:amplify_0:amplify_1:Redding_Public_Safety/Utilities:Redding_Public_Safety/Utilities],>
2023/02/07 08:13:59 [input.external.rawaudio_0:5] Not ready: need more buffering (320/4000).
2023/02/07 08:14:09 [input.external.rawaudio_0:5] Not ready: need more buffering (640/4000).

Is the "need more buffering" something I should be concerned with? If it rolls over past 4000, things seem to keep working but it begins the count again.
 

boatbod

Member
Joined
Mar 3, 2007
Messages
3,502
Location
Talbot Co, MD
I've not directly encountered this, but would suppose it relates to liquidsoap buffering of the input stream created by audio.py.
Try tweaking the "buffer=" parameter in the .liq file.
Code:
input = mksafe(input.external(buffer=0.25, channels=2, samplerate=8000, restart_on_error=false, "./audio.py -x 1.5 -s"))
 

jschmall

Member
Premium Subscriber
Joined
Jul 15, 2017
Messages
84
Location
Anderson, CA
I've not directly encountered this, but would suppose it relates to liquidsoap buffering of the input stream created by audio.py.
Try tweaking the "buffer=" parameter in the .liq file.
Code:
input = mksafe(input.external(buffer=0.25, channels=2, samplerate=8000, restart_on_error=false, "./audio.py -x 1.5 -s"))
I think we can safely ignore this log entry. I noticed that it only appears when there's silence on the channel. When I whitelisted all TG's on that channel, I hardly saw it, and when I blacklisted everthing, it was constant.

Doing some further digging, if I up the log level to 5 on my OP25 instance, I see the EXACT same log entries. If I bring logging back down to 3, it goes away so I'm going to assume it's not too big of a deal?

If I find anything further I'll update.
 

jschmall

Member
Premium Subscriber
Joined
Jul 15, 2017
Messages
84
Location
Anderson, CA
As long as the audio isn't all chopped up and stuttery you can ignore the message.
Audio seems to be just fine.

I do have a question regarding metadata. It's my understanding that if I'm sending UDP frames to a LS server (wether that be local to the machine or elsewhere) the metadata is part of those frames, yes? I seem to have lost all metadata for both of my channels. Nothing has changed in regards to the OP25 json config except for the destination field , or the icecast server. Icymeta is set to true in my LS config just like it was originally.
 

boatbod

Member
Joined
Mar 3, 2007
Messages
3,502
Location
Talbot Co, MD
I do have a question regarding metadata. It's my understanding that if I'm sending UDP frames to a LS server (wether that be local to the machine or elsewhere) the metadata is part of those frames, yes? I seem to have lost all metadata for both of my channels. Nothing has changed in regards to the OP25 json config except for the destination field , or the icecast server. Icymeta is set to true in my LS config just like it was originally.
The metadata is sent in parallel to the UDP audio stream and it never passes through liquidsoap. Normally you configure op25 to send the metadata to the icecast server at the same mount point as the liquidsoap stream destination. The icecast stream needs to be "up" before metadata will be accepted.
 

jschmall

Member
Premium Subscriber
Joined
Jul 15, 2017
Messages
84
Location
Anderson, CA
The metadata is sent in parallel to the UDP audio stream and it never passes through liquidsoap. Normally you configure op25 to send the metadata to the icecast server at the same mount point as the liquidsoap stream destination. The icecast stream needs to be "up" before metadata will be accepted.
Ok that makes sense. I'm gonna have to dig into this more. I'll have to get wireshark up and running to watch that traffic.
 

wgbecks

Active Member
Joined
Jan 17, 2005
Messages
1,102
Location
NE Wisconsin
There’s a bit of a fly in the ointment sending metadata to an Icecast server in that the server expects the audio stream and the metadata to originate from the same source address. Therefore, If you have Liquidsoap running on a different machine than op25 is running on, Icecast will
not accept and process the metadata.

There might be a configuration setting in Icecast to allow different source address but I haven't had a need to investigate that possibility.
 

jschmall

Member
Premium Subscriber
Joined
Jul 15, 2017
Messages
84
Location
Anderson, CA
There’s a bit of a fly in the ointment sending metadata to an Icecast server in that the server expects the audio stream and the metadata to originate from the same source address. Therefore, If you have Liquidsoap running on a different machine than op25 is running on, Icecast will
not accept and process the metadata.

There might be a configuration setting in Icecast to allow different source address but I haven't had a need to investigate that possibility.
It's interesting that you say that because I'm watching the logs on my icecast server and OP25. I'm seeing the requests coming across with a valid 200 response but I'm not seeing any metadata changes actually taking place. I am already looking into the icecast settings so I will continue down that route.
 

wgbecks

Active Member
Joined
Jan 17, 2005
Messages
1,102
Location
NE Wisconsin
I don't know if this behavior is a hardcoded security measure or if there is a configuration that will allow different audio stream and metadata source addresses.

The text shown below was extracted from Wireshark while sniffing the communications between the host running op25 and the
host running Icecast in response to a metadata update.

Wireshark PCAP (Packet Capture)

HTTP/1.0 200 OK
Server: Icecast 2.4.3
Date: Wed, 08 Feb 2023 21:57:08 GMT
Content-Type: text/xml; charset=utf-8
Cache-Control: no-cache
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Pragma: no-cache
Access-Control-Allow-Origin: *
Content-Length: 125


<?xml version="1.0"?>
<iceresponse><message>Mountpoint will not accept URL updates</message><return>1</return></iceresponse>
 

boatbod

Member
Joined
Mar 3, 2007
Messages
3,502
Location
Talbot Co, MD
That's an interesting observation and I guess it makes perfect sense when you think about it from a security standpoint.

Liquidsoap has the capability to accept metadata from a telnet connection, so I suppose it should be possible to create a different version of icemeta.py that can communicate with liquidsoap rather than an icecast server. That way op25 can communicate with liquidsoap and then liquidsoap can send the metadata on to the streaming server along with the audio stream.
 

wgbecks

Active Member
Joined
Jan 17, 2005
Messages
1,102
Location
NE Wisconsin
Here are a couple of Wireshark packet captures demonstrating the Icecast metadata update security. The first packet capture (Successful)
has op25 and Liquidsoap running on the same host while the second (Failed) has Liquidsoap running on a different host on the local network.

Successful Metadata Update (OP25 Reset)

Successful Metadata Update.png

Failed Metadata Update (OP25 Reset)

Failed Metadata Update.png
 

jschmall

Member
Premium Subscriber
Joined
Jul 15, 2017
Messages
84
Location
Anderson, CA
That's an interesting observation and I guess it makes perfect sense when you think about it from a security standpoint.

Liquidsoap has the capability to accept metadata from a telnet connection, so I suppose it should be possible to create a different version of icemeta.py that can communicate with liquidsoap rather than an icecast server. That way op25 can communicate with liquidsoap and then liquidsoap can send the metadata on to the streaming server along with the audio stream.


Theoretically this would allow for an easier way to move alpha tags around yeah? For example, a locally (local to the LAN) installed icecast instance and Broadcastify instance since liquidsoap can send that stream to multiple sources.

Here are a couple of Wireshark packet captures demonstrating the Icecast metadata update security. The first packet capture (Successful)
has op25 and Liquidsoap running on the same host while the second (Failed) has Liquidsoap running on a different host on the local network.

Successful Metadata Update (OP25 Reset)

View attachment 136061

Failed Metadata Update (OP25 Reset)

View attachment 136062

Since these servers are on a different VLAN in my network I'll have to do some work to get my PC on that VLAN to sniff packets. I'll work on this tonight.

In the mean time, here are a few snippets from the logs:

Icecast:
Code:
[2023-02-08  18:21:06] DBUG admin/admin_handle_request Admin request (/admin/metadata)
[2023-02-08  18:21:06] DBUG admin/admin_handle_request Got command (metadata)
[2023-02-08  18:21:06] INFO admin/admin_handle_request Received admin command metadata on mount "/rpd"
[2023-02-08  18:21:06] DBUG admin/command_metadata Got metadata update request

OP25:
Code:
02/08/23 18:23:28.061324 metadata update: "http://REDACTED:8000/admin/metadata?mount=/rpd&mode=updinfo&song=[201]+RPD+Patrol+1"
02/08/23 18:23:28.064510 metadata result: "200"
02/08/23 18:23:28.164758 metadata update: "http://REDACTED:8000/admin/metadata?mount=/rpd&mode=updinfo&song=[idle]"
02/08/23 18:23:28.167979 metadata result: "200"
 

wgbecks

Active Member
Joined
Jan 17, 2005
Messages
1,102
Location
NE Wisconsin
Unfortunately, Icecast, even at debug level, doesn’t log anything to suggest that it’s rejecting a metadata update and op25 returns result: "200" regardless if the metadata update was successful or not and is why I resorted to packet sniffing with Wireshark.

@boatbod has an excellent suggestion to develop a different version of icemeta.py with an option to send metadata directly to Liquidsoap that I believe will have an added benefit of improving metadata (tags) synchronization over the way Icecast handles these updates.
 
Status
Not open for further replies.
Top