How to: Run Wyoming Satellite on Android

I just managed to get wyoming-satellite to work on Android. My goal was to add voice assistant capabilities (always running in he background) to my wall mounted tablet which is primarily used as a Home Assistant panel. And I needed to achieve this with open source software only.

image

Here are the steps I took in order to get this to work:

  1. Install Termux (open source terminal emulator app)
  2. Install Termux:API (necessary to get mic access)
  3. Open Termux and run the following commands one by one by typing them and pressing enter:
# Update packages
pkg up
# Install required packages
pkg install git python sox pulseaudio termux-api
# Start test recording to trigger mic permission prompt
termux-microphone-record -f ./tmp.wav
# It should ask you for mic access now. Select `Always Allow`.
# Now quit the test recording
termux-microphone-record -q`
# And delte the test recording
rm -f ./tmp.wav
# Temporarily load PulseAudio moule for mic access
pactl load-module module-sles-source
# Verify that there is at least one microphone detected
pactl list short sources | grep "module-sles-source.c" && echo success || echo failure
# Clone Wyoming Satellite repo
git clone https://github.com/rhasspy/wyoming-satellite.git
# Enter Wyoming Satellite direcotry
cd wyoming-satellite
# Run Wyoming Satellite setup script
./script/setup
# Write down the IP address (most likely starting with `192.`) of your device, you will find it in the output of this command:
ifconfig
# Load PulseAudio moule for mic access again (just in case it got unloaded already)
pactl load-module module-sles-source
# Start Wyoming Satellite by running this entire multi-line command at once:
script/run \
  --name 'Android Satellite' \
  --uri 'tcp://0.0.0.0:10700' \
  --mic-command 'rec -r 16000 -c 1 -b 16 -e signed-integer -t raw --no-show-progress - ' \
  --snd-command ' play -r 22050 -c 1 -b 16 -e signed-integer -t raw --no-show-progress -' \
  --awake-wav ./sounds/awake.wav \
  --done-wav ./sounds/done.wav \
  --timer-finished-wav ./sounds/timer_finished.wav \
  --timer-finished-wav-repeat 5 0.5 \
  --debug
  1. Open Home Assistant go to Settings ā†’ Integrations ā†’ Add Integration ā†’ Wyoming Protocol
  2. It should ask you for a host and a port now. Enter the IP address you noted in step 3 from the output of ifconfig into the host-field and enter 10700 in the port-field.

You should now be able to find it under Settings ā†’ Devices:
image

It would probably make sense to run Wyoming OpenWakeWord in parallel on that Android device as well so that you are not constantly sending a mic stream to HA, but for my purposes it doesnā€™t really matter. I might expand this how-to in the near future for that use-case though.

Another thing that could be done is utilizing Termux:Boot to automatically start the Wyoming Satellite again when the device is restarted.

Iā€™m not 100% confident that I didnā€™t miss a step here, so Iā€™ll keep an eye on this thread for a while in case anyone is running into issues.

3 Likes

Could you expand on the following, for example is the uri the ip of the phone or do we leave it as 0.0.0.0?

script/run
ā€“name ā€˜Android Satelliteā€™
ā€“uri ā€˜tcp://0.0.0.0:10700ā€™
ā€“mic-command ā€˜rec -r 16000 -c 1 -b 16 -e signed-integer -t raw --no-how-progress - ā€™
ā€“snd-command ā€™ play -r 22050 -c 1 -b 16 -e signed-integer -t raw --no-show-progress -ā€™

Of corse.
0.0.0.0 simply means ā€œall network interfacesā€. It makes the service available to your entire network over all your network interfaces (i.e. Wifi and Ethernet). You could replace it with the IP address of your Android deviceā€™s Wifi interface and thus ensure that it only exposes the service through that interface. But if that IP changes, it will break, thus 0.0.0.0 is the recommended approach.

In regards the the rest of the command:

  • script/run is the script that starts the wyoming service
  • ā€“name ā€˜Android Satelliteā€™ sets the name as seen by Home Assistant to Android Satellite. You can replace it with whatever you want.
  • ā€“uri ā€˜tcp://0.0.0.0:10700ā€™ specifies where the service should be exposed. 10700 is the Port that you have to enter in the Wyoming Protocol Integration in HA. You can use any other Port if you want, but I recommend using the defaults to avoid potential interference with other services.
  • ā€“mic-command This parameter expects a bash command that streams the audio input of a mic to its stdout. The audio stream must be a raw PCM stream in this format:
    • Sample rate: 16000hz
    • Sample size: 16 bytes
    • Endianess: little-endian
    • Data Type: signed integer
    • Channel count: 1
      Iā€™m using the sox command rec for this purpose, but other commands like arecord, parecord, pw-record or maybe even termux-microphone-record could theoretically be used as well.
  • ā€“snd-command This parameter expects a bash command that can take an audio stream over stdin and play it back on a speaker or headphoneā€¦ The audio stream is a raw PCM stream is this format:
    • Sample rate: 22050hz
    • Sample size: 16 bytes
    • Endianess: little-endian
    • Data Type: signed integer
    • Channel count: 1
      Iā€™m using the sox command play for that purpose, but other commands would probably work too.

I hope this answers you question.

Yes, thank you.

will I need to keep the termux app open?

Yes and no. It needs to be running, but it can just stay in the background. I alway have the Home Assistant app running in the foreground and Termux running in the background always listening.

This is fantastic. I have a project called View Assist that uses (mostly) Android tablets in conjunction with Stream Assist integration to connect to HA Assist. The Stream Assist method does work but have always wanted to try to get Wyoming running on these tablets and also to integrate the Wyoming satellites into View Assist as well.

Weā€™ve got a few hundred folks that have joined our Discord server and it would be great to chat with you there if youā€™re interested.

Thanks for sharing this!

1 Like

When I get to this step

I get

Failure: Module initialization failed

I am running this on a 10" Fire Tablet. Everything up to this point worked.

Impressive work, @randomuser123! I wouldnā€™t have guessed this was possible :astonished:

Good work. Iā€™m glad you were able to do this. I managed to install on my Lenovo ThinkSmart View.
This line should be corrected --mic-command 'rec -r 16000 -c 1 -b 16 -e signed-integer -t raw --no-how-progress - ' \ to --no-show-progress - to detect the microphone.

I managed to connect it to Home Assistant, but I couldnā€™t get the wake word to work with this satellite, even though it says INFO: root Streaming audio in the log.

Sorry for the typo. I will update the command in my post.
There are also additional useful options for audio feedback like --wake-wav and --done-wav which I will add.

I have an old Amazon Fire tablet somewhere. Iā€™ll dig it out and try to get this to work on it as well.

I installed it on a Lenovo TSV tablet and a Samsung A7 tablet with Android 12 and I still canā€™t get it to recognize the wake word. It connects to Home Assistant but in the log from Termux it says ā€œPing enabledā€ then after a while it says ā€œDid not receive ping response within timeoutā€. And in the Home Assistant logs, there are many disconnections of the Wyoming satellite.

Source: components/wyoming/satellite.py:139
integration: Wyoming Protocol (documentation, issues)
First occurred: 08:23:00 (492 occurrences)
Last logged: 11:58:15

Satellite has been disconnected. Reconnecting in 10 second(s)```

I get that error too sometimes, but you can ignore it. Wyoming Satellite recovers from it automatically.
What does your Home Assistant configuration regarding the Wyoming Protocol Integration look like? Do you have OpenWakeWord running somewhere?

You must at least have one instance of OpenWakeWord, one instance for SpeechToText like Wyoming Whisper and your Satellite of course:

image

I just tried it on my old Amazon Fire HD 7 and on that device I think Iā€™m running into an issue with it being 32bit rather than 64 bit. I opened a bug report for it and hope to hear back from a Termux dev: [Bug]: PulseAudio not working on 32bit Android Ā· Issue #21660 Ā· termux/termux-packages Ā· GitHub

But since your tablet is probably newer, you might have a better chance of getting it to work.
It would be helpful if you could provide the output of termux-info to get better insight.

But here is soemthing you can try:

Check if /system/lib64 exists, by running ls -la /system/lib64. If it does exist, run:

export LD_PRELOAD=/system/lib64/libskcodec.so

Then try pactl load-module module-sles-source again, if it still fails, try running pulseaudio --start and then pactl load-module module-sles-source.

It works very well for me wake word on other satellites, esp32, stream assist, assist microphone and wyoming sattelite on raspberry pi. I tried to open the wav file from the recording test and only a very short noise is heard.

Wyoming sattelite also has a graphical interface for the installer. Do you think we could access it?

Does OpenWakeWord show up in the Wyoming Protocol Integration on Home Assistant for you? If not, then you should add it. Otherwise the OpenWakeWord instance(s) will only run locally on your satellites and since I havenā€™t managed to get it to work on Termux, youā€™d be missing it there.

Regarding the graphical interface, Iā€™m not sure. Iā€™ve never used it before.

Okay, this looks good. What happens if you play the microphone straight to the speaker? (Turn your volume down first)

rec -r 16000 -c 1 -b 16 -e signed-integer -t raw --no-show-progress - | play -r 22050 -c 1 -b 16 -e signed-integer -t raw --no-show-progress -