OP25 Raspberry Pi Streaming Part 2

So I finally figured out OP25 and I have this brand new Raspberry Pi 3 B + laying around doing nothing.  In this segment we’ll install OP25 on Raspberry Pi and then take our police scanner feed and send it to the internet on Broadcastify.

As someone pointed out to me yesterday, “There’s an app for that” they are indeed correct.  You can get Police Scanner Apps for IOS and Android.   Guess where the feeds in those apps comes from?  If you said Broadcastify you’d be correct.  So if no one is feeding your municipality   then there will be no feed in the app.  We will be that feed.

So the assumption is that you have a Pi with Raspbian installed and you kind of know how to use it.

The first thing we will do is to install GQRX.  GQRX is not a requirement but I like GQRX, it pulls down all the rtl-sdr drivers and GNURadio which IS a requirement and I use GQRX to hone in on the signals from the Control Channels, so it is a useful tool to me anyway.  Boot your pi, open a terminal and type the following commands.

sudo apt update

sudo apt install gnuradio libvolk1-bin libusb-1.0-0 gr-iqbal

sudo apt install qt5-default libqt5svg5 libportaudio2

sudo cp udev/*.rules /etc/udev/rules.d/

Now make a directory and download gqrx

mkdir gqrx
cd gqrx
wget https://github.com/csete/gqrx/releases/download/v2.11.5/gqrx-sdr-2.11.5-linux-rpi3.tar.xz

Unzip the file (I just did a VNC session and did it in the GUI) otherwise you need a program called xz-utils

sudo apt-get install xz-utils

Once unzipped the program is installed. We’re not going to open or use it now. We got what we want. All you do is navigate to the folder that has the gqrx executable in it and double click or type ./gqrx to launch the program in a terminal.

Now install OP25. Go back to Part 1 of this blog to learn how to do that. Installing and configuring OP25 is the same on Raspberry Pi as it is on Ubuntu Linux.

Ok the assumption here is that you are up and running and decoding a stream.

You have to have a RadioReference or Broadcastify account now and you have to apply for a stream.  I’m going to use RR as an example.  Under RadioReference go to this link  to apply to stream a channel.  Fill out the requested information EXACTLY as they request or they will kick your request back.  Mine got kicked back once.

Once approved they’ll give you a link which contains a server address, a mount point, and a password.

Now go to this page to get the directions to stream to Broadcastify

All the directions come from his page.  I DID NONE OF THIS.

sudo nano /etc/modprobe.d/bcm2835.conf

Insert the following:

softdep snd-bcm2835 post: snd-aloop
options snd-aloop enable=1 index=1 pcm_substreams=2

Hit CTL key + X key then Y to save the file

Now make an asound.conf file:

sudo nano /etc/asound.conf

# output device
pcm.loopout0 {
  type plug
  slave.pcm "hw:Loopback,0,0"

# input device
pcm.loopin0 {
  type dsnoop
  ipc_key 686592
  slave.pcm "hw:Loopback,1,0"

# duplex plug device
pcm.loop0 {
  type plug
  slave {
    pcm {
      type asym
      playback.pcm "loopout0"
      capture.pcm "loopin0"

# output device
pcm.loopout1 {
  type plug
  slave.pcm "hw:Loopback,0,1"

# input device
pcm.loopin1 {
  type dsnoop
  ipc_key 686593
  slave.pcm "hw:Loopback,1,1"

# duplex plug device
pcm.loop1 {
  type plug
  slave {
    pcm {
      type asym
      playback.pcm "loopout1"
      capture.pcm "loopin1"

Hit CTL key + X key then Y to save the file

You just made a loopback device.  On Windows this is kind of similar to Virtual Cable where you take your audio and pipe it into another program.  Because you changed the audio source you need to change a couple things in the way you invoke OP25.  I went back to my script file and changed the stuff in bold:

./rx.py --args 'rtl' -N 'LNA:47' -S 250000 -f 857.2625e6 -o 17e3 -q -2 -O loop0 -T trunk.tsv -V -2 -U 2> stderr-stream0.2

So your sound device is now the loopback device and you’re passing the stream.

Now get darkice

sudo apt-get install darkice

Now make a config file:

sudo nano /etc/darkice-stream0.cfg

Paste in the following making sure to change all your data in red:

# sample DarkIce configuration file, edit for your needs before using
# see the darkice.cfg man page for details

# this section describes general aspects of the live streaming session
duration        = 0        # duration of encoding, in seconds. 0 means forever
bufferSecs      = 1         # size of internal slip buffer, in seconds
reconnect       = yes       # reconnect to the server(s) if disconnected

# this section describes the audio input that will be streamed
device          = loop0  # OSS DSP soundcard device for the audio input
sampleRate      = 22050  # sample rate in Hz. 22050 is the RR Standard
bitsPerSample   = 16     # bits per sample. 16 for mono feeds, 32 for stereo feeds
channel         = 1      # channels. 1 = mono, 2 = stereo

# this section describes a streaming connection to an IceCast server
# there may be up to 8 of these sections, named [icecast-0] ... [icecast-7]
# these can be mixed with [icecast2-x] and [shoutcast-x] sections
# If you want to send to your own icecast server, you basically copy
# this whole section and put in the values to point the feed to your own
# server instead of the RR information below
# Don't forget, the name [icecast2-0] needs to change to [icecast2-1]
# and 2 and 3 as you add more feed destinations.
# The audio format to encode to, we're using mp3 here
format          = mp3

# The bit rate mode to use, the commented out lines are for a fixed bit
# rate "constant bit rate" at 16 bits.  I prefer the variable bit rate
# for the sound quality it has and the throughput is very similar on avg

#bitrateMode    = cbr 
#bitrate        = 16 

sampleRate      = 22050     # sample rate in Hz. 22050 is the RR Standard
bitrateMode     = cbr
bitrate		= 16

# Quality at .1, max is 1.0, but as you increase, so does the bandwidth
# used.  For mono scanner audio .1 is totally fine.
quality         = 0.1

# Takes the input and mixes it down to a mono output for the feed.
channel         = 1

# Cuts frequency response over 5kHz.  For scanner feed this mostly
# eliminates hiss and harshness on paging tones.  Saves a bunch of
# bandwidth as well.
lowpass         = 5000

# Server shown on your RR feed owner page that hosts your feed
# You need to log in to RR, go to Account -> My Live Audio Feeds ->
# click the feed owner page icon at the far right of your feed listing.
# Then you will see all this information.

# From Feed Technical Details, the "Server"
server          = SERVER.broadcastify.com

# From Feed Technical Details, the "Port"
port            = 80      # port of the IceCast server, usually 8000

# From Feed Technical Details, the Password exactly as shown
password        = PASSWORD

# From Feed Technical Details, the mount...remove the leading "/", it's
# not needed in this file.  So if it is /999999 make it just 999999
mountPoint      = MOUNTPOINT

# name of the stream
# On My Live Audio Feeds, it's the first part ending in a colon ":"
name            = Short name

# On My Live Audio Feeds, it's the part in parentheses in the Feed name
description     = Description

Hit CTL key + X key then Y to save the file

Now start your OP25 instance as you did from lesson 1.  I used a script file.  I tried and tried and tried to use the start at boot systemd script on the tutorial page but it just wouldn’t work.  My script file is called “op25.sh” and is located in the /home/pi/op25 folder.  I finally figured out to start it at boot I call it from a crontab.  OP25 needs to run in a terminal so I installed screen and did the following command from crontab -e

@reboot /usr/bin/screen -d -m /home/pi/op25/op25.sh

Or you can start it like this:

I finally figured out I could invoke that from the service file as well.

sudo nano /etc/systemd/system/op25-stream0.service

After=syslog.target network.target nss-lookup.target network-online.target

ExecStart=/usr/bin/screen -d -m /home/pi/op25/op25.sh


Ctl + X then Y to save

sudo systemctl enable op25-stream0.service
sudo systemctl start op25-stream0.service

Now to start darkice is pretty easy.  From a terminal type the following:

darkice -c /path/to/darkice.cfg

In my case that is

darkice -c /home/pi/darkice/darkice.cfg

If you followed the Tutorial from the other page it is probably in /etc. It doesn’t matter where it is or what you call it as long as you point to it after running the darkice command.

To launch it automatically at boot type

sudo nano /etc/systemd/system/darkice-stream0.service

Paste in the following making sure to get the darkice.cfg path right:

After=syslog.target network.target nss-lookup.target network-online.target

ExecStart=/usr/bin/darkice -c /etc/darkice-stream0.cfg 


Now enable and start the service

sudo systemctl enable darkice-stream0.service

sudo systemctl start darkice-stream0.service

Now when you reboot OP25 should start and run, and darkice should be streaming to your feed.

Here’s my feed.

New Bern Public Safety

20 thoughts on “OP25 Raspberry Pi Streaming Part 2

  1. Derrick

    Thank you for the guide! Took a few hours of trial and error, but got it working!
    Now I’m wondering, is it possible to encode the alpha-tags and send those to broadcastify, or is that going to involve an entirely different setup?

  2. Alex Bowman

    Thanks for this guide! I followed it and have my set up working in Oxford NC.

    A few thing that I had issues with that might help others:
    When you talk about installing screen, Users will need to:
    sudo apt install screen
    Also I had an issue that the gnuradio didn’t find the RTL-2832U SDR due to bug #528 The following website solved that issue:
    Modify or create a file: etc/modprobe.d/rtlsdr.conf
    and add:
    blacklist dvbusbrt128xxu
    blacklist e4000
    blacklist rtl2832
    Then reboot
    Also I have found that my stream cuts every 12 hours (which I still need to investigate) I have made a new .sh and added to my aliases to quickly bring the stream back up.
    first create a file broadcastify.sh
    sudo nano /home/pi/broadcastify.sh
    #! /bin/sh

    sudo systemctl start op25-stream0.service

    sudo systemctl start op25-stream0.service

    bash /home/pi/op25/op25.sh
    [CTRL]+[X], [Y], [ENTER}
    Create alias
    sudo nano .bashrc
    ##OP25 alias

    alias op25=’bash /home/pi/op25/op25.sh’

    alias bcst=’bash broadcastify.sh’
    Whenever my stream crashes, I can bring it up easily by typing this in terminal:
    Lastly, you may want to make a white list to allow certain talkgroups. In the same folder as your trunk.tsv file make a .csv with a list of talkgroups in column A that you want (Talkgroup # only) save the csv as {whatever}.wlist(do not leave .csv as the extension, delete it out), in my case oxford.wlist. Open up Trunk.tsv and add the wlist file under the column whitelist, if you wnat only one TG, you dont need to add .wlist file you can simply typ the TG you want decode.

    Again, thank you for making this guide. I have a few issues but it seems to be minor. I figured I’d add this with the hope it will help someone else.

    1. John Hagensieker Post author

      Thanks. I added your alias trick to my other page. Soon as I get a chance I’ll look this over as well. I also had some crashing but I set a cron to reboot daily which seems to do the trick. Thanks again!

      1. Alex Bowman

        Right on! I’ve got it working perfectly. no need to log in and run the alias. I’ve got my pi rebooting a 8AM and 8PM everyday to prevent crashing. Thanks for the idea. This is what I did:

        crontab -e

        @reboot /usr/bin/screen -d -m bash /home/pi/op25/op25.sh

        0 8 * * * /sbin/shutdown -r now

        0 20 * * * /sbin/shutdown -r now

        [CTRL]+[X] [ENTER] [Y] [ENTER]

  3. Guy Hale

    This was a great guide! I got my setup going and I’m currently streaming to a private Icecast server until I’m sure it works solidly, then I’ll look into adding my site to Broadcastify. Thanks for the Raspberry Pi guides, the last time I tried to use one it just couldn’t keep up. Seems to work great now!

    1. Danesh

      1. cd to directory where op25.sh file is
      2. ls -lt ./op25.sh #this should show the perm settings(r=read, w=write, x=execute) for the owner, group, and other users for op25.sh
      3. make sure that the execute (x) permission is set. If not, use the chmod command to set the ‘execute’ permission for op25.sh. You must be either the ‘owner’ of the file, or use ‘sudo’ or ‘root’ id to chmod the file.
      4. Another alternative to step 3 is to call/execute op25.sh using ‘bash op25.sh’ or ‘bash /path/to/op25.sh’

      Disclaimer, I have not installed any of the software. My answer is based on my experience when your can not execute a shell file (and get a permission denied error msg).


  4. Matteo

    On Raspberry Pi 3 B+ with fresh copy of Raspbian Buster with desktop “2019-06-20-raspbian-buster”
    After issuing step four, or the command:
    sudo cp udev/*.rules /etc/udev/rules.d/
    I get the error:
    cp: cannot stat ‘udev/*.rules’: No such file or directory

    1. Matteo

      I got it to work, the solution as to revert to a prior version of Raspbian, and AFTER Gqrx cd the proper directory.

      After Gqrx is installed:
      cd /home/pi/gqrx-sdr-2.11.5-linux-rpi3/
      sudo cp udev/*.rules /etc/udev/rules.d/

  5. Matteo

    I really appreciate this tutorial. I was able to get the latest Raspbian Buster to work with the instructions.
    The only change is this.
    After unzipping the gqrx-sdr-2.11.5-linux-rpi3.tar.xz file:
    cd /home/pi/gqrx/gqrx-sdr-2.11.5-linux-rpi3/
    sudo cp udev/*.rules /etc/udev/rules.d/

  6. Ken Schmidt

    You will pardon me if this sounds naive in nature, but I am intrigued by the use of a Raspberry Pi. However, in your instructions, you seem to refer to programing the Pi.

    Being that the Raspberry Pi has no monitor or keyboard, how on earth do you see what the device is doing, or not doing? Plus as I was able to gather, there is no audio jack on the Pi, so how does one listen to the output of OP25?

    I asked the same questions when FlightAware dropped Windows based feeding, but got absolutely no response. So I chucked the Pi since at that time it was useless.

    None the less, I am willing to purchase another one IF I can figure out how one can observe what the device is doing, and listen to it.

    1. Ken Schmidt

      Please note that I currently have OP25 operating in Ubuntu via VirtualBox (and it runs flawlessly). It took 3 months of toying with it, but oh well.

      I was going have the shop in town convert a laptop to Ubuntu, however the Tech had no idea what or why one would want dump Windows and run Linux, so I just gave up that idea.

    2. John Hagensieker Post author

      From your other post I’d guess you have the stick to it – ness to work your way through the Pi. My directions are made on the assumption that you are setting the pi up headless (no mouse, keyboard, Monitor). You have to program the Pi from another computer hooked up across the network via Secure Shell (SSH). On Windows most use a program called Putty. In Mac I just use the Terminal program.

      Dig around on SSH and your answer lies there. Once you figure it out you can do ANYTHING with a Pi.

  7. Billy H

    Awesome write ups (this one and your others). Much appreciated, especially as someone who touches Linux once a year and then forgets everything.

    Once update you may want to make to the post, and one question.

    The asound.conf you pasted includes smart-quotes/curly-quotes/whatever you call them (“these” vs “these”). Tracking down the reason my audio wouldn’t start was easy once I saw there was an illegal char at the end of each line with quotes – but threw me for a few.

    I understand the concept of screen to the extent one would use it from a command line so they could open something and switch “instances” of shell if you will. I’m not clear on how it works when used in a service. For example, I see it in my list of services, and I know it’s running, but I can’t quite figure out how to “see” or open that terminal. Typing “screen” and then hot-keying for all open sessions shows none are open, as I suspect it’s a different instance of screen (rather than a different shell instance within screen). Any tips here? In short – if I were to set up the service like you have, and wanted to log into the box to see what talkgroups were active (for example), how would I actually see the running op25 terminal instance?

    Thanks again!

  8. Scott Miller

    Excellent article. I’m now streaming my local Police P25 system via Pi 3 Buster/OP25 thanks to you! Works like a champ!

  9. Gared Roessel

    Did you ever find a solution to get op25 to open at startup? I tried the screen method, but when I use screen it disables my mic input ( I have no idea why ). Basically I am streaming the op25 to discord on the same machine, I just ran the stereo cable from the headphone out to the mic in and adjusted levels and it works great, I just can’t get it automated because if I dont reboot it every day it just locks up completely.


Leave a Reply to Alex Bowman Cancel reply

Your email address will not be published. Required fields are marked *