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

@litinoveweedle are you gonna pipe everything from /tmp/snapfifo to rhasspy output?

I’ve opened a thread about streaming radio on the same machine as rhasspy is running. Maybe we are both trying something pretty similiar? So far my mopidy isn’t working properly. How do you feed snapserver with music in your scenario?

Hello I do not know if I understand your question correctly, but lets discuss it in your thread.

1 Like

OK, I am lost.

I tried for last 2 days to get working alsa config to allow me to dmix and softvol two sources - one from host an second from Docker. And I can’t get it to work. Here is what I have:

  • Respeaker USB MIc Array v2 card (with 48kHz + 1 channel input fw), which can only play audi when recoded into 48kHz, S24_3LE, 2channel stream.

  • Snapcast client on host, which is unable to recode (include server) into S24_3LE, and therefore I do receive 48kHz, S16_LE, 2 channel stream.

  • Rhasspy in Docker, using aplay.

I want both application to output simultaneously, playing to Respeaker card. Also I want to be able to set volume independently for each application. I tried almost any combination I can think of, but I failed.

It seems that problem is Docker, which is not able to share alsa dmix device, so even if dmix is working locally (i.e. on the host I can play from both apps in the same time) this doesn’t work in Docker.

So my snapcast client started on system boot will start playing music, but from rhasspy Docker when I try to play any file I get:

root@b4a24c1da87d:/# aplay -D rhasspy /usr/share/rhasspy/etc/wav/beep_hi.wav -v
ALSA lib pcm_dmix.c:1108:(snd_pcm_dmix_open) unable to open slave
aplay: main:828: audio open error: Device or resource busy

Using same command on host:

pi@speakerliving:~/rhasspy $ aplay -D rhasspy beep_error.wav
Playing WAVE ‘beep_error.wav’ : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo

works like a charm. So the only problem is dmix alsa plugin shared via Docker. :frowning: From this source:

For ALSA sound just share sound devices with --device /dev/snd . You would not need the more advanced Pulseaudio setup, but will have trouble if more than one application tries to access the sound hardware. x11docker provides this setup with option --alsa .

And no, I don’t want to try Pulse Audio on RPi. :stuck_out_tongue_closed_eyes:

I would be glad for any help/hint/idea. Only one in my mind now is to install snapcast client into Rhasspy docker. But hat meant starting maintain my own Docker forks.:upside_down_face:

FYI: my current asound.conf:

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
    }
}

A couple of questions:

  1. What’s your run line or what’s in your docker-compose.yaml for Rhasspy?
  2. Are you mapping the host’s asound.conf inside the Rhasspy docker container?

Hello,

I map both /dev/snd and /etc/asound.conf.

docker run -d -p 12101:12101 --restart unless-stopped --name rhasspy -v "/home/pi/rhasspy/profiles:/profiles" -v "/etc/asound.conf:/etc/asound.conf" --device /dev/snd:/dev/snd synesthesiam/rhasspy-server:latest --user-profiles /profiles --profile en

The issue seems to be docker limitation.

Also create a copy of your asound.conf somewhere and the one in the docker run command give it a unique IPC.

@hawkeye217 has his running that way I think and all is hunky dory.

But also your not setting the defaults with an asym.

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


pcm.eci {
    type plug
    slave {
        format S16_LE
        rate 16000
        channels 1
        pcm {
            type file
            slave.pcm null
            file "/tmp/ec.input"
            format "raw"
        }
    }
}

pcm.eco {
    type plug
    slave.pcm {
        type fifo
        infile "/tmp/ec.output"
        rate 16000
        format S16_LE
        channels 2
    }
}

Just posted all of mine as using software EC but thought I would ask as your calling it snapcast but just seems to point at your card.
The card also is hw:0 you sure about that as no pi embedded?

Try adding --ipc="host" to your command line.

2 Likes

YES, thank you! This done the trick. :slight_smile:

2 Likes

Now I am missing last thing, some hook to mute snapcast on wake word recognition. To mute snapcast is easy as snapcast server has API, only to find some Rhasspy trigger to use. :slight_smile:

Great! Glad it worked.

You could probably do this with a little bash script listening on the appropriate MQTT topics and through the amixer command line tool.

Thank you again. Well so far I am using Rhasspy http API for integration. Is there any other benefit using MQTT for client/server integration?

Not 100% sure, but from what I can tell, Rhasspy’s websocket API isn’t as robust as MQTT to be able to get in and hack something together.

Because of what rhasspy is, a ai voice controlled hmi it does make sense to use MQTT

http://mqtt.org/

MQTT is a machine-to-machine (M2M)/“Internet of Things” connectivity protocol. It was designed as an extremely lightweight publish/subscribe messaging transport. It is useful for connections with remote locations where a small code footprint is required and/or network bandwidth is at a premium. For example, it has been used in sensors communicating to a broker via satellite link, over occasional dial-up connections with healthcare providers, and in a range of home automation and small device scenarios. It is also ideal for mobile applications because of its small size, low power usage, minimised data packets, and efficient distribution of information to one or many receivers

Has some well defined core building blocks and its prob wise to continue to use MQTT due to it likely being the default machine-to-machine (M2M)/“Internet of Things” connectivity protocol of practically everything.

If https://docs.snips.ai/reference/hermes should be implemented or used as a guide to the base use of opensource MQTT I guess needs some clarrification.
As to the Hermes audio transport I am beginning to think audio might be a bad format when there are so many advantages in sending and processing Mel Filter (MFCC) Spectrograms and audio distribution via Snapcast which is really great for that purpose.
But again Hermes audio has already been defined, but passing wavs is anything but lightweight.

MQTT is prob a really good idea to follow.

Thank you both for reply. I know MQTT as I use it for Homeassistant integrations, I did even wrote few integrations for my home bred Raspberry Pi devices. My question was more like if there are any drawbacks (for example speed, resources consumption, etc of MQTT vs HTTP)

I checked on Rhasspy 2.5 (i.e. Voltron) and I saw that MQTT seems to be primary way how all component are integrated. But right now, as I use Homeassistant conversation integration for intent recognition (with Almond), I can’t use Rhasspy 2.5 (as by the docs this integration is not yet complete). So I will wait until I will be able to test it.

Than it should be no problem to write MQTT client which will subscribe for Hermes topics and could do things like snapcast client muting, or Respeaker Array LED control. :slight_smile:

1 Like

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