Playing sound at the same time from Rhasspy (Docker) and the host

I really like the look of snapcast and how it does latency handling.
It also has codec support that can reduce bandwidth requirements substantially.
Maybe should also have an option for a lightweight codec like the ones bluetooth uses.
But it looks awesome but do you guys know if you can just stream single channels to devices or do you split them and create multiple streams?
If your setting up and playing with snapcast create a thread and let us know what and how your doing as my only criticism of snapchat is the documentation.

But I am interested in your setup, devices, speakers, AI and what you do.

I found that MQTT seemed a bit faster for me with my setup.

I use Rhasspy 2.5-pre with Home Assistant intents and it’s working great. See this other thread on how I’ve done it.

Thank you for observation.

I would preffer to keep my HA integration with Almond, which is conversation integration - which seems to be not yet finished in Rhasspy 2.5. This is actually free speach integration… You do not need to create intents at all and work supringly OK.

Thanks a lot for this thread. This helped me a lot. I managed to play sound from Rhasspy (Docker) and Squeezelite (Host) at the same time only by you !

1 Like

Hi,

maybe someone here can help me.
I have rhasspy (docker) and mopidy (host) running.
Once mopidy was on rhasspy can’t make a sound.
I have tried to take over my asound.conf in the container.
Unfortunately without success

The command “aplay /usr/share/sounds/alsa/Front_Center.wav” works on the host but not in the container

Error

ALSA lib pcm_dmix.c:1108:(snd_pcm_dmix_open) unable to open slave
aplay: main:828: audio open error: Device or resource busy

asound.conf

# use samplerate to resample as speexdsp resample is bad
defaults.pcm.rate_converter "samplerate"

pcm.!default {
    type asym
    playback.pcm "playback"
    capture.pcm "capture"
}

pcm.playback {
    type plug
    slave.pcm "dmixed"
}

pcm.capture {
    type plug
    slave.pcm "array"
}

pcm.dmixed {
    type dmix
    ipc_perm 0666
    slave.pcm "hw:seeed2micvoicec"
    ipc_key 555555
}

pcm.array {
    type dsnoop
    slave {
        pcm "hw:seeed2micvoicec"
        channels 2
    }
    ipc_key 666666
}

Haaa, I was solving same issue. And with help of others I solved it. As far as I remember I needed to do several things:

  1. Create two playback devices in alsa asound.conf and dmix them to given HW card (one is for Rhasspy playback TTS and second for music playback - in my case snapcast client)
  2. Share same asound.conf between host and Rhasspy Docker container
  3. Share host IPC Rhasspy Docker container

asound.conf (with independent sof volume control for both playback channels)

pcm.mix {
    type dmix
    ipc_key 1024
    ipc_perm 0666
    slave {
        pcm "hw:0,0"
        period_time 0
        period_size 1024
        buffer_size 4096
        rate 48000
        format S24_3LE
    }
    bindings {
        0 0
        1 1
    }
}


pcm.snapcast {
    type plug
    slave.pcm "snapcast_vol"
}


pcm.snapcast_vol {
    type softvol
    slave.pcm "mix"
    control {
        name "Snapcast"
        card 0
    }
}


pcm.rhasspy {
    type plug
    slave.pcm "rhasspy_vol"
}


pcm.rhasspy_vol {
    type softvol
    slave.pcm "mix"
    control {
        name "Rhasspy"
        card 0
    }
}


pcm.snoop {
    type dsnoop
    ipc_key 2048
    ipc_perm 0666
    slave {
        pcm "hw:0,0"
        channels 1
        period_size 1024
        buffer_size 4096
        rate 48000
        format S16_LE
    }
    bindings {
        0 0
    }
}


pcm.mic {
    type plug
    slave.pcm "mic_vol"
}


pcm.mic_vol {
    type softvol
    slave.pcm "snoop"
    control {
      name "Mic"
      card 0
    }
    min_dB -10.0
    max_dB 30.0
}

docker run (with both 2. + 3. requirements)

docker run -d -p 12101:12101
           --name rhasspy \
           --restart unless-stopped \
           -v "$HOME/.config/rhasspy/profiles:/profiles" \
           -v "/etc/localtime:/etc/localtime:ro" \
           -v "/etc/asound.conf:/etc/asound.conf" \
           --device /dev/snd:/dev/snd \
           --ipc="host" \
           rhasspy/rhasspy --user-profiles /profiles  --profile en

2 Likes

Thank you.
With this asound.conf and docker command it works now.
But explain me something.
Wich parameter in your docker command makes it work?
It dosen’t work with mine.

docker run -it 
    --name rhasspy \
    --restart always \
    -v "$HOME/.config/rhasspy/satellite:/profiles"  \
    -v "/etc/asound.conf:/etc/asound.conf" \
    --network host \
    --device /dev/snd \
    rhasspy/rhasspy --profile de --user-profiles /profiles --local-mqtt-port 13183

The one missing :slight_smile:

 --ipc="host" \

Hello guys, thank you for all the hints here!

I’ve quite achieve my goal on my laptop: playing audio from Rhasspy docker and my base OS at the same time.

I’m saying quite because if I use rhasspy TTS (based on my “rhasspy” audio device) or other audio output flows from Rhasspy while using “speaker-test -D host” from a terminal on my computer (my “host” audio device ), the audio is mixed and played correctly (TTS sentence mixed with pink noise).

But if I’m using my computer normally while rhasspy is saying something through the TTS system then I got a “resource busy” (eg: while rhasspy is talking, if i’m opening a youtube video, this got stuck with loading loader icon)

I’m on Ubuntu 18.04 and this is my .asoundrc file (or asound.conf).

Maybe I’m just missing some basic step to do on my host or maybe I need to use the PulseAudio features as described here https://github.com/TheBiggerGuy/docker-pulseaudio-example ?

pcm.!default {
    type plug
    slave.pcm "host_vol"
}


pcm.host_vol {
    type softvol
    slave.pcm "mix"
    control {
        name "default"
        card 0
    }
}


pcm.rhasspy {
    type plug
    slave.pcm "rhasspy_vol"
}


pcm.rhasspy_vol {
    type softvol
    slave.pcm "mix"
    control {
        name "Rhasspy"
        card 0
    }
}

pcm.mix {
    type dmix
    ipc_key 1024
    ipc_perm 0666
    slave {
        pcm "hw:0,0"
        period_time 0
        period_size 1024
        buffer_size 4096
        rate 48000
        format S24_3LE
    }
    bindings {
        0 0
        1 1
    }
}

ctl.!default {
        type hw           
        card 0
}

Notice:

It took me too long to figure out, what was the problem and I couldn’t have rhasspy read my “virtual channels”.

So if you have rhasspy with docker-compose running and you have already added the /etc/asound.conf binded that in docker-compose.yml added also the line ipc: host then you should delete the volumes from container with:

docker-compose down -v

And then start the container.

docker-compose up -d

Just to make sure nobody else tries only to restart the rhasspy container without deleting the volumes…

The above is almost correct

So the docker run will be

docker run -d -p 12101:12101 \
    --ipc=host \
    --name rhasspy \
    --restart unless-stopped \
    -v "$HOME/.config/rhasspy/profiles:/profiles" \
    -v "/etc/asound.conf:/etc/asound.conf:ro" \
    -v "/etc/localtime:/etc/localtime:ro" \
    --device /dev/snd:/dev/snd \
    rhasspy/rhasspy \
    --user-profiles /profiles \
    --profile en

So you will have to stop the container rm to remove then docker run again
The /etc/asound.conf for the 2mic is as so

# The IPC key of dmix or dsnoop plugin must be unique
# If 555555 or 666666 is used by other processes, use another one


# use samplerate to resample as speexdsp resample is bad
defaults.pcm.rate_converter "samplerate"

pcm.!default {
    type asym
    playback.pcm "playback"
    capture.pcm "capture"
}

pcm.playback {
    type plug
    slave.pcm "dmixed"
}

pcm.capture {
    type plug
    slave.pcm "array"
}

pcm.dmixed {
    type dmix
    slave.pcm "hw:seeed2micvoicec"
    ipc_key 555555
    ipc_perm 0666
}

pcm.array {
    type dsnoop
    slave {
        pcm "hw:seeed2micvoicec"
        channels 2
    }
    ipc_key 666666
    ipc_perm 0666
}

The respeaker install for some reason misses the ipc_perm 0666 and without permissions you will get an ipc error.

So to recap you need to add --ipc=“host” which uses the ipc of the host so also share a copy of /etc/asound.conf in the docker run as -v "/etc/asound.conf:/etc/asound.conf:ro" \ that way the same IPC and settings are on the host and in the container and rhasspy should be set to use default as the /etc/asound.conf sets that.

If on the cli I run speaker-test I get that horrid pink noise test and if I sudo docker exec -it rhasspy /bin/bash and run speaker-test in the container I get double the horrid pink noise test, running at the same time but mixed.

I added --ipc="host" to my docker command and added ipc_perm 0666 to pcm.array in asound.conf

I made several docker stop, rm, runs and some reboots.
Seems like now rhasspy only play sound if i had not yet used squeezelite, after start/stop squeezelite rhasspy dont play sound anymore.

Before changing rhasspy played sound after stopping the player
I remember the above behavior from the past, dont know how/when it changed to be usable after player stop.

I hear nothing from speaker-test, probably because it uses the other pi soundcard rather the respeaker one.

speaker-test -Ddmix:seeed2micvoicec -c2
gives a device busy error, after restart there is an error about 48000 Hz not supported.

docker run -d -p 12101:12101 -p 12183:12183 
  --ipc="host" --name rhasspy --restart unless-stopped 
  -v "$HOME/.config/rhasspy/profiles:/profiles" 
  -v "/etc/localtime:/etc/localtime:ro" 
  -v "/etc/asound.conf:/etc/asound.conf" 
  --device /dev/snd:/dev/snd rhasspy/rhasspy 
  --user-profiles /profiles --profile de
# The IPC key of dmix or dsnoop plugin must be unique
# If 555555 or 666666 is used by other processes, use another one


# use samplerate to resample as speexdsp resample is bad
defaults.pcm.rate_converter "samplerate"

pcm.!default {
    type asym
    playback.pcm "playback"
    capture.pcm "capture"
}

pcm.playback {
    type plug
    slave.pcm "dmixed"
}

pcm.capture {
    type plug
    slave.pcm "array"
}

pcm.dmixed {
    type dmix
    ipc_perm 0666       # Andere Benutzer können ebenfalls dmix gleichzeitig nutzen
    slave.pcm "hw:seeed2micvoicec"
    ipc_key 555555.
    ipc_key_add_uid false
}

pcm.array {
    type dsnoop
    slave {
        pcm "hw:seeed2micvoicec"
        channels 2
    }
    ipc_key 666666
    ipc_perm 0666
}
$ aplay -l
card 0: Headphones [bcm2835 Headphones], device 0: bcm2835 Headphones [bcm2835 Headphones]
  Subdevices: 8/8
  ...

card 1: seeed2micvoicec [seeed-2mic-voicecard], device 0: bcm2835-i2s-wm8960-hifi wm8960-hifi-0 [bcm2835-i2s-wm8960-hifi wm8960-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

Did you delete the container and do the docker run again as the speaker-test not giving an output means /etc/asound.conf must not be active as if it was the default would be set.

pcm.!default {
    type asym
    playback.pcm "playback"
    capture.pcm "capture"
}

I have never tried speaker-test -Ddmix:seeed2micvoicec -c2 but it would never use the IPC of -Ddmixed and on its own like that has no IPC set, so don’t think that would work anyway as a dmix and if it does it would be the same as hw: or plug: due to no IPC

At a guess somewhere in the config be it squeezelite, rhasspy web config likely there is something not using the default and has a hw: or plughw: that is likely locking others out maybe.

I haven’t got that image up and running now and also never tried squeezelite but thinking how I have it, it will prob work.
I might get round to setting it up with squeezelite later or tomorrow

I deleted the container several times.
I dont know how to do testing with a non-default device, i found the speaker-test command in my shell history.
How should i do the test?

Pi sound card was not deactivated, maybe i need them later (if i find a small speaker not needing extra power).

Btw, i have squeezelite on the host, not in a docker.
I think ifollowed http://www.gerrelt.nl/RaspberryPi/wordpress/tutorial-installing-squeezelite-player-on-raspbian/#Starting_Squeezelite_on_startup
SL_SOUNDCARD is commented out in config and there seems no changed value, most comments. Squeezlite uses the seeed card.

$ squeezelite -l
Output devices:
  null                           - Discard all samples (playback) or generate zero samples (capture)
  jack                           - JACK Audio Connection Kit
  pulse                          - PulseAudio Sound Server
  playback                      
  capture                       
  dmixed                        
  array                         
  default                       
  output                        
  sysdefault:CARD=Headphones     - bcm2835 Headphones, bcm2835 Headphones - Default Audio Device
  dmix:CARD=Headphones,DEV=0     - bcm2835 Headphones, bcm2835 Headphones - Direct sample mixing device
  dsnoop:CARD=Headphones,DEV=0   - bcm2835 Headphones, bcm2835 Headphones - Direct sample snooping device
  hw:CARD=Headphones,DEV=0       - bcm2835 Headphones, bcm2835 Headphones - Direct hardware device without any conversions
  plughw:CARD=Headphones,DEV=0   - bcm2835 Headphones, bcm2835 Headphones - Hardware device with all software conversions
  usbstream:CARD=Headphones      - bcm2835 Headphones - USB Stream Output
  sysdefault:CARD=seeed2micvoicec - seeed-2mic-voicecard, bcm2835-i2s-wm8960-hifi wm8960-hifi-0 - Default Audio Device
  dmix:CARD=seeed2micvoicec,DEV=0 - seeed-2mic-voicecard, bcm2835-i2s-wm8960-hifi wm8960-hifi-0 - Direct sample mixing device
  dsnoop:CARD=seeed2micvoicec,DEV=0 - seeed-2mic-voicecard, bcm2835-i2s-wm8960-hifi wm8960-hifi-0 - Direct sample snooping device
  hw:CARD=seeed2micvoicec,DEV=0  - seeed-2mic-voicecard, bcm2835-i2s-wm8960-hifi wm8960-hifi-0 - Direct hardware device without any conversions
  plughw:CARD=seeed2micvoicec,DEV=0 - seeed-2mic-voicecard, bcm2835-i2s-wm8960-hifi wm8960-hifi-0 - Hardware device with all software conversions
  usbstream:CARD=seeed2micvoicec - seeed-2mic-voicecard - USB Stream Output

Dunno as never use squeezelite apt-get install squeezelite really but just setting it up now which I have but didn’t read any setup lols, I never read the instructions!

I just installed squeezelite and then went off at a tangent as it was failing but that was because asound2-plugins was not installed but presumed everything else 1st.
I haven’t installed rhasspy yet as think my OC Pi02W was dying as also to make things worse kept crashing with kernel messages so set to default speed but it seemed to be the network and confused

So with LMS on my PC I install squeezelite and do nothing more
Play some music in the web control and it plays
Play speaker-test or aplay file_example_WAV_2MG.wav Sample .wav download | File Examples Download

Rhasspy just installed

docker exec -it rhasspy /bin/bash

speaker-test and again its all mixed with squeezelite playing joy division merilly

your mum is fat speaks away via TTS or anything you can think of, whilst still playing joydivision

No problem so maybe that tutorial as I just installed.

/etc/asound.conf

 # The IPC key of dmix or dsnoop plugin must be unique
# If 555555 or 666666 is used by other processes, use another one


# use samplerate to resample as speexdsp resample is bad
defaults.pcm.rate_converter "samplerate"

pcm.!default {
    type asym
    playback.pcm "playback"
    capture.pcm "capture"
}

pcm.playback {
    type plug
    slave.pcm "dmixed"
}

pcm.capture {
    type plug
    slave.pcm "array"
}

pcm.dmixed {
    type dmix
    slave.pcm "hw:Device"
    ipc_key 555555
    ipc_perm 0666
}

pcm.array {
    type dsnoop
    slave {
        pcm "hw:Device"
        channels 2
    }
    ipc_key 666666
    ipc_perm 0666
}

Its a plugable usb device but has spaces in its naming so you just get the last word from /proc/asound/cards

I am thinking my pref for snapcast is going to stay snapcast, I am presuming groups and stuff can be added and setup, but all seems an after thought.
LMS is a media server whilst snapcast is network virtual audio cable and doesn’t have a media player that is from the go organised into rooms/zones with corresponding inputs for near anything and you use whatever media player or in/out you wish, whilst LMS is very concentric to the LMS media server and isn’t as simple for multiroom design purity that snapcast has.
Pretty sure you can add plugins to do the same with LMS but snapcast is setup from the get go and likely offers more in/out methods and has audiophile quality network latency compensation.

I think i need to do the test, but dont know how.
Can you help me with this? I posted the squeezebox devices so you can see my hardware.

Beside LMS i dont know other music systems. I tried volumio which does not work out of the box and then found LMS, which worked fine + i found a used squeezebox radio. I am in no way audiophile, but i like to have the same music in 2 rooms.

Squeezelite is OK for that the big difference comes if you plan to have active speakers or not as the latency tolerance to the speed of sound works out about 3 meters so really your talking a single multi-channel amp in each room than an active wireless speaker setup.
Snapcat is pure audio delivery so its setup to accept all audio whilst LMS is very focussed on its media player with plugins and not even worked out how you play music in each room, whilst snapcast feathers the latency adjust in a similar way to AGC (feathers in/out samples as agc does amplitude) and works at x10 smaller tolerance size.
Also its not just Snapcast it what other such as Hifiberry add such as GitHub - hifiberry/snapcastmpris: MPRIS interface to snapcast but squeezelite does run on esp32 whilst the snapcast client doesn’t look totally complete but if on Arm…

Start with a fresh image install your 2mic driver? Add the changes, install squeezelite and don’t pick or set an audio output leave all to default.
Reboot after installing squeezelite as can not remember if it runs auto on install.
speaker-test which is part of the alsa install run without -D so it uses default is a good a test as any.

Both should play at the same time and mix, if so then run the rhasspy docker install again keeping all to default.
docker exec -it rhasspy /bin/bash and also run speaker-test there and if that mixes then you are 100% but what you have done with your system now, who knows?

I have the same hat you do; which is what I did all my development on this with:

I also just setup squeezelite and alice_satellite to work together; I am working on adding support to control squeezelite from alice_satellite so that it will pause and resume any audio that is playing.

I am using the following in /etc/asound.conf

pcm.dmixed {
    type dmix
    slave {
	pcm "hw:seeed2micvoicec"
	rate 44100
    }
    ipc_key 555555 
    ipc_perm 0666
}

/etc/default/squeezelite

SL_SOUNDCARD="dmixed"

I also set alice_satellite to use dmixed and they both work simultaneously.

I can not just reinstall my raspi, i have some sensors served from there to my HA. I do not want them to become mixed up…

Yeah just going to have to let you sort it out as it works fine no problem, but somewhere in your setup you have something blocking it.
All you need is a single app to not access the default and correct dmixed pcm and it will block all else and what, only you can tell.