Playing BBC radio stations


56 posts   Page 1 of 3   1, 2, 3
by ktinkerer » Wed May 10, 2017 12:21 pm
I've spent a while trying to get my box to play the radio and finally have it working. I took some tips from this post: https://www.raspberrypi.org/forums/viewtopic.php?f=114&t=182665

It uses vlc to play the radio so first that needs to be installed:
Code: Select all
sudo apt-get install vlc


Edit ~voice-recognizer-raspi/src/actions.py
Add this to the imports:
Code: Select all
import RPi.GPIO as gpio
import time


Then further down you need to add this class:
Code: Select all
# =========================================
# Makers! Implement your own actions here.
# =========================================

class playRadio(object):

    def __init__(self, say, keyword):
        self.say = say
        self.keyword = keyword

    def run(self, voice_command):

        logging.info("starting " + voice_command)
        self.say("tuning the radio in to " + voice_command)
        if voice_command == 'Radio 1':
            station = "http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio1_mf_p?s=1494265262"
        elif voice_command == 'Radio 2':
            station = "http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio2_mf_p?s=1494265194"
        elif voice_command == 'Radio 3':
            station = "http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio3_mf_p?s=1494265402"
        elif voice_command == 'Radio 4':
            station = "http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio4fm_mf_p?s=1494265402"
        elif voice_command == 'Radio 5':
            station = "http://open.live.bbc.co.uk/mediaselector/5/redir/version/2.0/mediaset/http-icy-mp3-a-stream/proto/http/vpid/bbc_radio_five_live"
        elif voice_command == 'Radio 6':
            station = "http://bbcmedia.ic.llnwd.net/stream/bbcmedia_6music_mf_p?s=1494265223"
        elif voice_command == 'Radio 1Xtra':
            station = "http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio1xtra_mf_p?s=1494265403"
        elif voice_command == 'Radio 4 Extra':
            station = "http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio4extra_mf_q?s=1494265404"
        else:
            station = "http://bbcmedia.ic.llnwd.net/stream/bbcmedia_6music_mf_p?s=1494265223"

        p = subprocess.Popen(["/usr/bin/cvlc",station],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
        p.poll()
       
        gpio.setmode(gpio.BCM)
        gpio.setup(23, gpio.IN)

        while True:
            if gpio.input(23):
                logging.info("stopping radio")
                p.kill()
                break
            time.sleep(0.1)

I've also put a gist on github in case the formatting gets messed up.) https://gist.github.com/ktinkerer/70c68f0ba7db06e81a4b0811d7748b94#file-playradio-py

Finally add the action:
Code: Select all
# =========================================
# Makers! Add your own voice commands here.
# =========================================
actor.add_keyword(_('radio'), playRadio(say,_('radio')))


Restart the service:
Code: Select all
sudo systemctl restart voice-recognizer.service

Check the logs for errors:
Code: Select all
sudo journalctl -u voice-recognizer -e


Now your box will play BBC radio on command eg "Radio 1".

It should be really simple to add further radio stations if you have the stream address.

Note: I've set it up to stop the radio when the button is pressed, otherwise it's listening to the radio and starts trying to do all sorts of odd searches. :)

I've written this all up on my blog, not sure if I'm allowed to link to that, pretty much says the same as this anyhow!
Posts: 35
Joined: Wed May 10, 2017 8:31 am
by scotty101 » Wed May 10, 2017 1:01 pm
Looks good. If I can suggest an improvement... rather than using VLC, try MPD. It is specifically designed to run in the background as a service and deal with playing media.
There is also a python binding to save you from having to use subprocess to control it.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter
Posts: 2165
Joined: Fri Jun 08, 2012 6:03 pm
by ktinkerer » Wed May 10, 2017 1:14 pm
That would be great because it could also play other music files, but I cannot get mpd to work alongside the voice-recognizer service. It seems to be either one or the other. I think it may be something to do with the audio output and the voicehat soundcard. When I do get mpd to play I can't change the volume, it's stuck on loud!
Posts: 35
Joined: Wed May 10, 2017 8:31 am
by scotty101 » Wed May 10, 2017 1:46 pm
I think you need to change the MPD config to use the software mixer to control the volume.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter
Posts: 2165
Joined: Fri Jun 08, 2012 6:03 pm
by ktinkerer » Wed May 10, 2017 3:36 pm
scotty101 wrote:I think you need to change the MPD config to use the software mixer to control the volume.

Yes that works for the volume, but I'm still struggling to get it to run at the same time as the voice recogniser.
Posts: 35
Joined: Wed May 10, 2017 8:31 am
by Pipecock » Wed May 10, 2017 5:52 pm
The iPlayer URLs in your code are for 128kbps mp2. 320kbps AAC streams are available
: http://www.meridianunplugged.com/ubbthr ... ber=242138 but I'm unable test ATM.

The sound quality advantage probably doesn't count for much when using a £1 speaker in a cardboard box, it will matter later on when hooked up to decent sound equipment.
Posts: 8
Joined: Tue Sep 04, 2012 8:35 pm
Location: South Wales
by groundcontroltom » Thu May 11, 2017 6:50 am
Thanks for the gist ktinkerer, got me started with figuring out how to stream music from Google Music. Hope to post some results this evening!
Posts: 48
Joined: Sun Dec 06, 2015 10:16 am
by ktinkerer » Thu May 11, 2017 7:27 am
Pipecock wrote:The iPlayer URLs in your code are for 128kbps mp2. 320kbps AAC streams are available
: http://www.meridianunplugged.com/ubbthr ... ber=242138 but I'm unable test ATM.

The sound quality advantage probably doesn't count for much when using a £1 speaker in a cardboard box, it will matter later on when hooked up to decent sound equipment.


Great! Thanks for the link, I'll test those out later on. I found when I was setting this up that not all the streaming links I found worked. There are also lists of radio stations on https://beebotron.org/listings/ and http://www.radiofeeds.co.uk/hifi.asp
Posts: 35
Joined: Wed May 10, 2017 8:31 am
by ktinkerer » Thu May 11, 2017 7:28 am
groundcontroltom wrote:Thanks for the gist ktinkerer, got me started with figuring out how to stream music from Google Music. Hope to post some results this evening!

That sounds brilliant! Looking forward to hearing more!
Posts: 35
Joined: Wed May 10, 2017 8:31 am
by philicibine » Thu May 11, 2017 10:50 am
Ive been trying to get this working but when I ask for a station it says tuning to, and then nothing happens.

Can you point me in the right direction to fix it?
Code: Select all
May 11 11:40:51 raspberrypi python3[525]: [2017-05-11 11:40:51,392] INFO:main:listening...
May 11 11:40:51 raspberrypi python3[525]: [2017-05-11 11:40:51,394] INFO:main:recognizing...
May 11 11:40:53 raspberrypi python3[525]: [2017-05-11 11:40:53,791] INFO:speech:event_type: 1
May 11 11:40:53 raspberrypi python3[525]: [2017-05-11 11:40:53,797] INFO:main:thinking...
May 11 11:40:53 raspberrypi python3[525]: [2017-05-11 11:40:53,804] INFO:speech:transcript: Radio 1
May 11 11:40:54 raspberrypi python3[525]: [2017-05-11 11:40:54,585] INFO:root:starting Radio 1
May 11 11:40:54 raspberrypi kernel: [   32.636155] voicehat-codec voicehat-codec: Enabling audio amp...
May 11 11:40:57 raspberrypi kernel: [   34.982795] voicehat-codec voicehat-codec: Disabling audio amp...
May 11 11:40:57 raspberrypi python3[525]: [2017-05-11 11:40:57,201] INFO:root:stopping radio
May 11 11:40:57 raspberrypi python3[525]: [2017-05-11 11:40:57,203] INFO:main:handled local command: Radio 1
Posts: 3
Joined: Thu May 11, 2017 10:44 am
by corris » Thu May 11, 2017 11:43 am
I had the same problem, probably caused by noise on GPIO 23. Easy to fix. In the class playRadio(object): code in action.py, just change the line near the end from

if gpio.input(23):

to

if gpio.input(23) ==0:
Posts: 3
Joined: Thu May 11, 2017 11:18 am
by philicibine » Thu May 11, 2017 12:57 pm
thanks, thats got it
Posts: 3
Joined: Thu May 11, 2017 10:44 am
by n8kowald » Sat May 13, 2017 10:31 pm
I am absolutely loving this, thank you @ktinkerer!

After failing to add new stations I realised it was not matching my voice commands due to case mismatches.
For example: When I viewed the logs I could see that "Radio london" - my condition - was stored in 'voice_command' as "radio London" so would drop into the else condition every time.

To match more accurately I converted 'voice_command' to lowercase first:

Code: Select all
voice_command_lc = voice_command.lower()

# Add logging
logging.info("Looking for station with case: " + voice_command_lc)

# Use lowercase
if voice_command_lc == 'radio london':
            station = "http://media-ice.musicradio.com/LBCLondonMP3Low.m3u"

Another thing I added was to say whenever a voice search is not found:
Code: Select all
else:
           # Default radio station
            self.say("Radio search not found. Playing default station: LBC London")
            station = "http://media-ice.musicradio.com/LBCLondonMP3Low.m3u"

BTW does anyone know if you can tail the voice-recognizer log instead of needing to run 'sudo journalctl -u voice-recognizer -e'?

Update: To see a stream of voice-recognizer logs you can run:
Code: Select all
sudo journalctl -u voice-recognizer --pager-end --follow

I set up a new alias in my ~/.bashrc for this
Code: Select all
alias voice_log='sudo journalctl -u voice-recognizer --pager-end --follow'
Posts: 6
Joined: Sat May 13, 2017 8:36 pm
Location: London, UK
by ktinkerer » Sun May 14, 2017 8:41 am
Thanks @n8kowald! I will add those modifications, I'm also thinking about stripping the keyword radio before looking for the station, then it wouldn't matter what order you said it in, so you could issue a command like "Absolute radio" as it is now you'd need to say "Radio absolute", which sounds weird.

Thank you for the follow tip, seems you can shorten it to just -f so
Code: Select all
sudo journalctl -u voice-recognizer -f
works! (ctrl -c to get out of it).

Also if people want to share their radio station lists I can add them, use the format
Code: Select all
'radio 1': 'http://a.files.bbci.co.uk/media/live/manifesto/audio/simulcast/hls/uk/sbr_high/ak/bbc_6music.m3u8',
there is a list here http://www.radiofeeds.co.uk/hifi.asp I'll do it myself if I get time.
Posts: 35
Joined: Wed May 10, 2017 8:31 am
by ktinkerer » Sun May 14, 2017 9:32 am
I've made those modifications so now it doesn't matter what order you say the keyword in, but the format of the stations list now needs to be:
Code: Select all
'1': 'http://a.files.bbci.co.uk/media/live/manifesto/audio/simulcast/hls/uk/sbr_high/ak/bbc_radio_one.m3u8',
.
Posts: 35
Joined: Wed May 10, 2017 8:31 am
by n8kowald » Sun May 14, 2017 9:49 am
@ktinkerer I can see why you'd want to strip the "radio" keyword.
I like that it's a "namespaced" action so have left it for myself.

I've been getting great ideas from your modifications to action.py. Thanks for publishing these!
I can't see your recent radio modifications however, are they available anywhere?

Because I loved seeing your modifications, I've added mine: https://github.com/n8kowald/raspi-voice-actions

Added a "radio stations" command that loops over the radio stations in a dictionary list and "says" them. Need to work out how to preserver order. I'm new to Python.

The next thing I want to do is to move these classes from action.py into their own modules, then import them in action.py.
That seems neater.
Last edited by n8kowald on Sun May 14, 2017 8:48 pm, edited 1 time in total.
Posts: 6
Joined: Sat May 13, 2017 8:36 pm
Location: London, UK
by ktinkerer » Sun May 14, 2017 10:43 am
@n8kowald You should be able to see the mods on this branch https://github.com/ktinkerer/aiyprojects-raspbian/blob/pause_resume_actions/src/action.py

I'm trying out mpd, I'd really like to get music working with that, there is a python library to control it and it has the advantage that you can control it remotely with apps etc but so far I've had no luck getting it working alongside the voice recognizer, and when I do get it to work on it's own it plays for a couple of seconds then stops :(
Posts: 35
Joined: Wed May 10, 2017 8:31 am
by sheridat » Sun May 14, 2017 10:57 am
Hi, I am a MPD user - I have a couple of pi's dedicated to MPD - one a classic radio with a justboom dac/amp and speakers and another that has an Iqaudio DAC+ that I use exclusively for listening via headphones.

I've been using my AIY "box" to send command to my headphones based box using the python-mpd2 bindings.

However you might find that it is easier to manipulate MPD using MPC. If you use MPC it is as simple as doing something like

import os

# MPC next - you just need to string whatever your action is onto the end of "mpc " space after mpc
action = "next"
cmd = "mpc " + action

p = os.popen(cmd)
Posts: 86
Joined: Sun May 07, 2017 11:18 am
by ktinkerer » Sun May 14, 2017 11:13 am
@sheridat Great! Someone who can work mpd!

I was hoping to get it working on the same pi but I'm struggling with getting the config right to use the google voice hat. Also it doesn't seem to want to work at the same time as the voicerecognizer service, maybe an alsa issue?
Posts: 35
Joined: Wed May 10, 2017 8:31 am
by n8kowald » Sun May 14, 2017 3:39 pm
ktinkerer wrote:@n8kowald You should be able to see the mods on this branch https://github.com/ktinkerer/aiyprojects-raspbian/blob/pause_resume_actions/src/action.py


Thank you!
Good luck with mpd.
Posts: 6
Joined: Sat May 13, 2017 8:36 pm
Location: London, UK
by bs_pi » Tue May 16, 2017 11:08 am
@sheridat: I also would be very intereste on learning your mpd config setup in order to make it work with the Google voice hat.

@ktinkerer: Thank you for your work on this, I have implemented it and works very well with the only exception that when playing a radio the volume goes all the way to maximum independently of what the original volume was set to. The same issue occurs when I use the Youtube playing code by @mikerr. Does anyone else have this issue?

Thanks!
Posts: 6
Joined: Tue May 16, 2017 9:26 am
by bs_pi » Tue May 16, 2017 11:15 am
I also thought it would be useful to add a link I found to an extensive database of international radio station streams: http://www.surfmusic.de/country/uk.html
In order to get the stream address open the 'Listen Live' link of the radio you want and then on the newly opened window click on 'Stand alone player' when you will be asked to open or save a playlist.m3u file containing the stream address.
Posts: 6
Joined: Tue May 16, 2017 9:26 am
by sheridat » Tue May 16, 2017 12:49 pm
bs_pi wrote:@sheridat: I also would be very intereste on learning your mpd config setup in order to make it work with the Google voice hat.

@ktinkerer: Thank you for your work on this, I have implemented it and works very well with the only exception that when playing a radio the volume goes all the way to maximum independently of what the original volume was set to. The same issue occurs when I use the Youtube playing code by @mikerr. Does anyone else have this issue?

Thanks!

Hi, We misunderstand each other - I don't have mpd installed on my "AIY" box. I have MPD installed on a couple of other PI's on the same lan. I use the "AIY" box to send those MPD instances commands using either mpc or the python-mpd2 library. I normally control those MPD instances using IR via LIRC - just thought it would be interesting to control them using voice commands...

Won't be using "AIY" as a music player until someone comes up with how to graft another DAC onto the voice hat to provide stereo.
Posts: 86
Joined: Sun May 07, 2017 11:18 am
by sheridat » Tue May 16, 2017 3:34 pm
bs_pi wrote:@sheridat: I also would be very intereste on learning your mpd config setup in order to make it work with the Google voice hat.

@ktinkerer: Thank you for your work on this, I have implemented it and works very well with the only exception that when playing a radio the volume goes all the way to maximum independently of what the original volume was set to. The same issue occurs when I use the Youtube playing code by @mikerr. Does anyone else have this issue?

Thanks!

Hi see my previous post - thought I would mess around with this so I installed mpd on my "AIY" box. 7

I stopped it running as a service using " sudo service mpd stop"

Created a folder /home/pi/mpd and inside it I created another folder /home/pi/mpd/playlists and knocked together a playlist
I copied /etc/mpd.conf to be /home/pi/mpd.conf
Changed the conf so that all the files are created in /home/pi/mpd for example - db_file "/home/pi/mpd/tag_cache"
Changed the conf so that the alsa output is
audio_output {
type "alsa"
name "google hat thingybob"
device "hw:0,0"
mixer_type "software"
# device "hw:0,0" # optional
# mixer_type "hardware" # optional
# mixer_device "default" # optional
# mixer_control "PCM" # optional
# mixer_index "0" # optional
}

started it in the /home/pi/mpd dir using the command - sudo mpd mpd.conf
loaded the playlist containing some radio stations
It plays the radio station - no problem - however the little green light now flashes in time to the music and pressing it has no effect whatsoever.

So you can get mpd to work with the voice - but it seems to kill the google code
Posts: 86
Joined: Sun May 07, 2017 11:18 am
by sheridat » Tue May 16, 2017 4:03 pm
Hi again see my last 2 posts - I rebooted and all was well. Said good afternoon and had a nice chat with the lady from google.

Did the command to view the journal - everything normal

started mpd again and once again it plays music but the google service is fried.

Did the command to view the journal again

Here it is:
May 16 16:52:23 raspberrypi python3[377]: DependencyWarning
May 16 16:53:00 raspberrypi python3[377]: [2017-05-16 16:53:00,885] INFO:audio:started recording
May 16 16:53:01 raspberrypi python3[377]: [2017-05-16 16:53:01,167] INFO:main:ready...
May 16 16:53:18 raspberrypi python3[377]: [2017-05-16 16:53:18,488] INFO:main:listening...
May 16 16:53:18 raspberrypi python3[377]: [2017-05-16 16:53:18,498] INFO:main:recognizing...
May 16 16:53:24 raspberrypi python3[377]: [2017-05-16 16:53:24,076] INFO:speech:event_type: 1
May 16 16:53:24 raspberrypi python3[377]: [2017-05-16 16:53:24,278] INFO:main:thinking...
May 16 16:53:24 raspberrypi python3[377]: [2017-05-16 16:53:24,297] INFO:speech:transcript: good afternoon
May 16 16:53:28 raspberrypi python3[377]: [2017-05-16 16:53:28,314] INFO:main:Playing 18.0613 seconds of audio...
May 16 16:53:47 raspberrypi python3[377]: [2017-05-16 16:53:47,198] INFO:main:ready...
May 16 16:57:22 raspberrypi python3[377]: [2017-05-16 16:57:22,785] INFO:main:listening...
May 16 16:57:22 raspberrypi python3[377]: [2017-05-16 16:57:22,802] INFO:main:recognizing...
May 16 16:57:31 raspberrypi python3[377]: [2017-05-16 16:57:31,665] INFO:speech:event_type: 1
May 16 16:57:31 raspberrypi python3[377]: [2017-05-16 16:57:31,682] INFO:main:thinking...
May 16 16:57:31 raspberrypi python3[377]: [2017-05-16 16:57:31,846] INFO:speech:transcript: good afternoon
May 16 16:57:36 raspberrypi python3[377]: [2017-05-16 16:57:36,756] INFO:main:Playing 16.5716 seconds of audio...

this is where I started mpd. as you can see in the second line gives the game away - the resource is busy


May 16 16:57:37 raspberrypi python3[377]: ALSA lib pcm_dmix.c:1022:(snd_pcm_dmix_open) unable to open slave
May 16 16:57:37 raspberrypi python3[377]: aplay: main:722: audio open error: Device or resource busy
May 16 16:57:39 raspberrypi python3[377]: Exception in thread Thread-2:
May 16 16:57:39 raspberrypi python3[377]: Traceback (most recent call last):
May 16 16:57:39 raspberrypi python3[377]: File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
May 16 16:57:39 raspberrypi python3[377]: self.run()
May 16 16:57:39 raspberrypi python3[377]: File "/usr/lib/python3.4/threading.py", line 868, in run
May 16 16:57:39 raspberrypi python3[377]: self._target(*self._args, **self._kwargs)
May 16 16:57:39 raspberrypi python3[377]: File "src/main.py", line 269, in _recognize
May 16 16:57:39 raspberrypi python3[377]: self._handle_result(self.recognizer.do_request())
May 16 16:57:39 raspberrypi python3[377]: File "src/main.py", line 282, in _handle_result
May 16 16:57:39 raspberrypi python3[377]: self._play_assistant_response(result.response_audio)
May 16 16:57:39 raspberrypi python3[377]: File "src/main.py", line 296, in _play_assistant_response
May 16 16:57:39 raspberrypi python3[377]: sample_rate=sample_rate_hz)
May 16 16:57:39 raspberrypi python3[377]: File "/home/pi/voice-recognizer-raspi/src/audio.py", line 152, in play_bytes
May 16 16:57:39 raspberrypi python3[377]: aplay.stdin.write(audio_bytes)
May 16 16:57:39 raspberrypi python3[377]: BrokenPipeError: [Errno 32] Broken pipe
Posts: 86
Joined: Sun May 07, 2017 11:18 am