Just my blog
Blog about everything, mostly about tech stuff I made. Here is the list of stuff I'm using at my blog. Feel free to ask me about implementations.
- Mobaxterm SSH RDP FTP...
- Thunderbird Email client
- Filezilla FTP client/server
- Nirsoft Win utils
- Sysinternals Win utils
- Pi-Hole AD block by DNS
- NUT UPS manager
- Rpi MON Raspberry monitoring
- Free CAD 3D modelling
- Free Commander Far-like filemanager
- Bitwarden Password manager
- Django web framework
- celery multi-tasking
- celery-beat Celery + Django
- celery-results Celery + Django
- Pillow Python image lib
- wsgi mod Apache + Python
- requests best in WEB requests
- openpyxl make Excell docs
- p4python Perforce + Python
- paramiko SSH + Python
- pyvmomi ESXi Vcenter + Python
I'm using these libraries so you can ask me about them.
Raspberry 5 test-to-speech using Piper
How to make your Raspberry 5 talking with python lib Piper?
I wanted to make my Raspberry tell me about power outages and air alerts near my location.
The setup is pretty simple and described ar the repo:
I didn't want to waste my time making yet another Python venv and that's why I've chosen a simple binary mode.
Setup
Now about the setup:
- Raspberry 5.
- USB sound card with 3.5 jack.
- USB-powered speaker with a 3.5 jack.
Sound
CMD to change the volume programmatically:
amixer set Master 80% >> /dev/null
Sound devices and controls
You may have a problem with playing generated WAV files and making voice directly. So you need to choose devices for a different output.
To list devices run:
# List devices
aplay -L
# I only have USB card:
hw:CARD=Audio,DEV=0
USB Audio, USB Audio
Direct hardware device without any conversions
plughw:CARD=Audio,DEV=0
USB Audio, USB Audio
Hardware device with all software conversions
sysdefault:CARD=Audio
USB Audio, USB Audio
Default Audio Device
front:CARD=Audio,DEV=0
USB Audio, USB Audio
Front output / input
iec958:CARD=Audio,DEV=0
USB Audio, USB Audio
IEC958 (S/PDIF) Digital Audio Output
dmix:CARD=Audio,DEV=0
USB Audio, USB Audio
Direct sample mixing device
usbstream:CARD=Audio
USB Audio
USB Stream Output
aplay --device="dmix:CARD=Audio,DEV=0" /home/USER/Music/notifications/generated/UPS_no_power.wav
Playing WAVE '/home/USER/Music/notifications/generated/UPS_no_power.wav' : Signed 16 bit Little Endian, Rate 22050 Hz, Mono
aplay: set_params:1358: Channels count non available
Play
- play synthetic voice
- play prerecorded voice
- play a regular WAV sound from the internet
# Playing:
sleep 5 && aplay --device="plughw:CARD=Audio,DEV=0" /home/USER/Music/notifications/generated/UPS_no_power.wav
sleep 5 && aplay --device="sysdefault:CARD=Audio" /home/USER/Music/notifications/generated/UPS_no_power.wav
# Not playing
aplay --device="hw:CARD=Audio,DEV=0" /home/USER/Music/notifications/generated/UPS_no_power.wav
aplay --device="front:CARD=Audio,DEV=0" /home/USER/Music/notifications/generated/UPS_no_power.wav
aplay --device="iec958:CARD=Audio,DEV=0" /home/USER/Music/notifications/generated/UPS_no_power.wav
aplay --device="dmix:CARD=Audio,DEV=0" /home/USER/Music/notifications/generated/UPS_no_power.wav
aplay --device="usbstream:CARD=Audio" /home/USER/Music/notifications/generated/UPS_no_power.wav
# Test ddownloaded WAV and prerecorded
sleep 10 && aplay --device="plughw:CARD=Audio,DEV=0" /home/USER/Music/notifications/generated/UPS_no_power.wav && aplay --device="plughw:CARD=Audio,DEV=0" /home/USER/Music/notifications/stop.wav
# Play the voice right away
sleep 4 && amixer set Master 60% >> /dev/null && echo "ей, увага, повітряна тривога у київській області." | /home/USER/text_to_speech/piper/piper --model /home/USER/text_to_speech/ukr/uk_UA-ukrainian_tts-medium.onnx --speaker 0 --output-raw | aplay -r 22050 -f S16_LE -t raw - && amixer set Master 10% >> /dev/null
# Eng
echo "Hey, Warning there is an air alert in Kyiv oblast" | /home/USER/text_to_speech/piper/piper --model /home/USER/text_to_speech/eng/en_GB-northern_english_male-medium.onnx --output-raw | aplay -r 22050 -f S16_LE -t raw -
Playing synthetic voice right away:
echo "Робота від батареї" | /home/USER/text_to_speech/piper/piper --model /home/USER/text_to_speech/ukr/uk_UA-ukrainian_tts-medium.onnx --speaker 1 --output_file UPS_no_power.wav
Recording the voice to a WAV file:
echo "Увага, робота від батареї, рівень заряду п'ятдесят відсотків" | /home/USER/text_to_speech/piper/piper --model /home/USER/text_to_speech/ukr/uk_UA-ukrainian_tts-medium.onnx --speaker 1 --output_file UPS_50_percent.wav
Volume levels
- Set new master volume
- Make an announcement
- Set previous or lower master volume back
sleep 4 && amixer set Master 50% >> /dev/null && echo "Hey, Hey, Warning there is an air alert in Kyiv oblast" | /home/USER/text_to_speech/piper/piper --model /home/USER/text_to_speech/eng/en_GB-northern_english_male-medium.onnx --output-raw | aplay -r 22050 -f S16_LE -t raw - && amixer set Master 10% >> /dev/null
Bonus
- locally run the script with the required parameters
- remotely you need to run a remote SSH command
#!/bin/bash
# Play notification sound at givel volume with given file
PATH_TO_NOTIFICATIONS="/home/USER/Music/notifications"
PATH_TO_DING="/home/USER/Music/notifications/stop.wav"
verbose=$3
sound_volume=$1
file_to_play=$2
play_sound_notification(){
# No verbose by default, and verbose if any arg!
if [ -z "$verbose" ]; then
verbose=false
else
verbose=true
echo "DEBUG: mode at any arg: $verbose"
fi
# Volume check if integer:
if [[ "$sound_volume" =~ ^[0-9]+$ || "$sound_volume" =~ ^[-][0-9]+$ ]]; then
# Volume check if GTE 101 or LT 1:
if [[ $sound_volume -ge 101 ]] || [[ $sound_volume -lt 0 ]]; then
echo "ERROR: Volume is incorrect not 1-100: $volume"
return 0
fi
# All correct:
if $verbose ; then echo "DEBUG: volume is OK: $volume"; fi
else
echo "ERROR: Volume is incorrect, not an integer: $volume"
return 0
fi
# Check if file exsists:
file_full_path="$PATH_TO_NOTIFICATIONS/$file_to_play"
if [ -f $file_full_path ]; then
if $verbose ; then echo echo "DEBUG: file exists: $file_full_path"; fi
else
echo "File: $file_to_play"
echo "ERROR: The file does not exist at path with this name: $file_full_path"
return 0
fi
# Set volume:
if $verbose; then
echo "Set volume at level: $sound_volume"
echo "============================"
amixer set Master $sound_volume%
echo "============================"
echo "Play initial ding to wake up USB Sound device: $PATH_TO_DING"
aplay --device="dmix:CARD=Audio,DEV=0" -q --nonblock --duration=1 $PATH_TO_DING
echo "Now play requested notification: $file_full_path"
aplay --device="dmix:CARD=Audio,DEV=0" -q $file_full_path
echo "Set volume back at level 10%"
echo "============================"
amixer set Master 10%
echo "============================"
else
amixer set Master $sound_volume% >> /dev/null
aplay --device="dmix:CARD=Audio,DEV=0" -q --nonblock --duration=1 $PATH_TO_DING
aplay --device="dmix:CARD=Audio,DEV=0" -q $file_full_path
amixer set Master 10% >> /dev/null
fi
# Play notification:
# End and exit
return 0
}
play_sound_notification $sound_volume $file_to_play $verbose
- you need to set SSH keys between HA and RPi
ssh -o UserKnownHostsFile=/config/.ssh/known_hosts -i /config/.ssh/id_rsa USER@IP_ADDR '/home/USER/play_sound_notification.sh {{volume}} {{file}}'
- PATH_TO_NOTIFICATIONS - folder where your WAV files located
- PATH_TO_DING - path to a short (1-2 sec) and quiet notification sound to wake up the speaker
In my case, my device is cutting a few seconds of any sound it plays. So I've added one "silent" notification sound before any real notification.
It must be a sound, I've tried to fool the device with a silent file and it doesn't help.