A modern, production-ready Python Flask web service for sending text-to-speech notifications and playing audio files on Google Home, Chromecast, and Chromecast Audio devices.
Note: This project is based on harperreed/google-home-notifier-python but has been extensively modernized and enhanced with production features including Kubernetes support, configurable volume control, improved network detection, and robust error handling.
- 🔊 Text-to-Speech (TTS) - Convert text to speech using Google's TTS service
- 🎵 Audio Playback - Play MP3 files from local storage or external URLs
- 🎛️ Configurable Volume - Set custom volume levels for different environments
- 🔍 Auto-Discovery - Automatically find and connect to Chromecast devices
- 📡 Direct IP Connection - Connect to specific Chromecast IP addresses
- 🌐 Network Detection - Intelligent network IP detection for containerized environments
- 📦 Production Ready - Docker and Kubernetes deployment configurations
- 💾 TTS Caching - Cache generated audio files for faster playback
- 🔄 Background Discovery - Continuous device discovery with reconnection support
- 🧪 Test Endpoints - Built-in testing and debugging endpoints
-
Clone the repository
git clone https://github.com/your-username/google-home-notifier-python.git cd google-home-notifier-python -
Install dependencies
pip install -r requirements.txt
-
Configure environment variables
cp .env.example .env # Edit .env with your Chromecast settings -
Run the service
python main.py
The service will start on http://localhost:5000
# Basic TTS in English
curl "http://localhost:5000/say/?text=Hello World"
# TTS in different languages
curl "http://localhost:5000/say/?text=Bonjour le monde&lang=fr"
curl "http://localhost:5000/say/?text=こんにちは世界&lang=ja"# Play a local MP3 file
curl "http://localhost:5000/play/doorbell.mp3"Create a .env file in the project root with the following configuration:
# Chromecast Configuration
# Set the exact name of your Chromecast device (optional)
GRP_NAME="Living Room speaker"
# Set the IP address of your Chromecast if discovery fails (recommended)
CHROMECAST_IP=192.168.1.100
# External host/IP for Chromecast to access files (useful for K8s, Docker, etc.)
# Examples:
# EXTERNAL_HOST=192.168.1.100 # Local network IP
# EXTERNAL_HOST=myapp.mydomain.com # Domain name
# EXTERNAL_HOST=10.43.0.15 # K8s service IP
# EXTERNAL_HOST= # Leave empty for auto-detection
EXTERNAL_HOST=
# Volume level for playback (0.0 to 1.0, where 1.0 is maximum)
# Examples: 0.3 = 30% (office), 0.6 = 60% (home), 1.0 = 100% (demos)
PLAYBACK_VOLUME=0.6
# Discovery settings (optional)
DISCOVERY_RETRY_SEC=10
DISCOVERY_WAIT_TIMEOUT=30
PLAYBACK_TIMEOUT=300CHROMECAST_IP=192.168.1.100
EXTERNAL_HOST=192.168.1.50
PLAYBACK_VOLUME=0.6CHROMECAST_IP=10.0.1.100
EXTERNAL_HOST=10.0.1.50
PLAYBACK_VOLUME=0.3CHROMECAST_IP=172.16.1.100
EXTERNAL_HOST=172.16.1.50
PLAYBOOK_VOLUME=1.0Convert text to speech and play on Chromecast.
Parameters:
text(required) - Text to convert to speechlang(optional) - Language code (default: "en")
Examples:
curl "http://localhost:5000/say/?text=Hello World"
curl "http://localhost:5000/say/?text=Bonjour&lang=fr"Play an MP3 file from the static directory.
Parameters:
filename- Name of the MP3 file in the static directory
Example:
curl "http://localhost:5000/play/notification.mp3"Check current Chromecast discovery status.
Response:
{
"cast_found": true,
"target_name": "Living Room speaker",
"chromecast_ip": "192.168.1.100",
"cast_name": "Living Room speaker"
}Force restart of the discovery process.
Force reconnection to the Chromecast device.
Get detailed debugging information about the current Chromecast connection.
Perform manual discovery test and return debugging information.
Test playback with an external audio file.
Test playback using local network IP instead of localhost.
Test different audio format compatibility.
Test and adjust Chromecast volume.
Direct MP3 playback test.
Starts the background discovery thread for automatic Chromecast detection.
Main discovery loop that runs in a background thread. Handles both direct IP connection and network discovery.
Returns the discovered Chromecast device, waiting up to timeout seconds if needed.
Generates TTS audio file (or uses cached version) and plays it on the Chromecast.
Parameters:
text- Text to convert to speechlang- Language code (ISO 639-1)slow- Whether to use slow speech rate
Plays an MP3 URL on the Chromecast with configurable volume and automatic volume restoration.
Parameters:
mp3_url- URL of the MP3 file to playplayback_timeout- Maximum time to wait for playback completion
Intelligently determines the best host URL for Chromecast to access files.
Priority order:
EXTERNAL_HOSTenvironment variable- Auto-detected network IP
- Request URL with localhost replacement
Generates a stable, unique filename for TTS cache files.
Stops current discovery and starts a fresh discovery process.
Create a docker-compose.yml file:
version: '3.8'
services:
google-home-notifier:
build:
context: .
dockerfile: Dockerfile
container_name: google-home-notifier
restart: unless-stopped
network_mode: host
environment:
- CHROMECAST_IP=192.168.1.100
- EXTERNAL_HOST=192.168.1.50
- PLAYBACK_VOLUME=0.6
- GRP_NAME=Living Room speaker
ports:
- "5000:5000"
volumes:
- ./static:/app/staticFor production/secure deployments, use:
# Secure version with localhost-only binding
docker-compose -f docker-compose.secure.yml up -dSee docker-compose.secure.yml for security-hardened configuration.
FROM python:3.11-slim
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y \
gcc \
&& rm -rf /var/lib/apt/lists/*
# Copy requirements and install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application code
COPY . .
# Create static directory for cache
RUN mkdir -p static/cache
# Environment variables with defaults
ENV CHROMECAST_IP=""
ENV EXTERNAL_HOST=""
ENV PLAYBACK_VOLUME=0.6
ENV GRP_NAME="Google Home"
ENV DISCOVERY_RETRY_SEC=10
ENV DISCOVERY_WAIT_TIMEOUT=30
ENV PLAYBACK_TIMEOUT=300
# Expose port
EXPOSE 5000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:5000/discover/status || exit 1
# Run application
CMD ["python", "main.py"]# Build the image
docker build -t google-home-notifier .
# Run the container
docker run -d \
--name google-home-notifier \
--network host \
-e CHROMECAST_IP=192.168.1.100 \
-e EXTERNAL_HOST=192.168.1.50 \
-e PLAYBACK_VOLUME=0.6 \
-p 5000:5000 \
google-home-notifier
# Run with Docker Compose
docker-compose up -d🔒 Network Security:
- Bind to specific interfaces:
-p 127.0.0.1:5000:5000(localhost only) - Use firewall rules to restrict access
- Consider VPN access for remote control
🔐 Authentication Options:
- Add reverse proxy with authentication (nginx, Traefik)
- Use API keys or tokens
- Implement IP whitelisting
🛡️ Production Deployment:
# Secure local-only binding
docker run -d \
--name google-home-notifier \
-p 127.0.0.1:5000:5000 \
-e CHROMECAST_IP=192.168.1.100 \
-e EXTERNAL_HOST=192.168.1.50 \
google-home-notifierCreate a k8s-deployment.yaml file:
apiVersion: apps/v1
kind: Deployment
metadata:
name: google-home-notifier
labels:
app: google-home-notifier
spec:
replicas: 1
selector:
matchLabels:
app: google-home-notifier
template:
metadata:
labels:
app: google-home-notifier
spec:
# hostNetwork: true # Option 1: Required ONLY for automatic Chromecast discovery
# Alternative: Use specific IPs instead (more secure)
containers:
- name: google-home-notifier
image: google-home-notifier:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5000
env:
# Method 1: Direct IP configuration (recommended for K8s)
- name: CHROMECAST_IP
value: "192.168.1.100" # Your Chromecast IP
- name: EXTERNAL_HOST
value: "192.168.1.50" # Your K8s node IP or service IP
# Method 2: For auto-discovery, uncomment hostNetwork above and remove CHROMECAST_IP
- name: PLAYBACK_VOLUME
value: "0.6"
- name: GRP_NAME
value: "Living Room speaker"
livenessProbe:
httpGet:
path: /discover/status
port: 5000
initialDelaySeconds: 30
periodSeconds: 30
readinessProbe:
httpGet:
path: /discover/status
port: 5000
initialDelaySeconds: 5
periodSeconds: 10
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
volumeMounts:
- name: cache-volume
mountPath: /app/static/cache
volumes:
- name: cache-volume
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: google-home-notifier-service
spec:
type: NodePort
selector:
app: google-home-notifier
ports:
- port: 5000
targetPort: 5000
nodePort: 30500Option 1: Direct IP Configuration (Recommended)
- Set
CHROMECAST_IPto your Chromecast's IP address - Set
EXTERNAL_HOSTto your Kubernetes node IP - No
hostNetwork: trueneeded - More secure and predictable
Option 2: Auto-Discovery Mode
- Enable
hostNetwork: truein the pod spec - Remove
CHROMECAST_IPenvironment variable - Service will automatically discover Chromecast devices
- Less secure but more flexible
Create a k8s-configmap.yaml file:
apiVersion: v1
kind: ConfigMap
metadata:
name: google-home-notifier-config
data:
CHROMECAST_IP: "192.168.1.100"
EXTERNAL_HOST: "192.168.1.50"
PLAYBACK_VOLUME: "0.6"
GRP_NAME: "Living Room speaker"
DISCOVERY_RETRY_SEC: "10"
DISCOVERY_WAIT_TIMEOUT: "30"
PLAYBACK_TIMEOUT: "300"Then reference the ConfigMap in your deployment:
envFrom:
- configMapRef:
name: google-home-notifier-config# Create namespace (optional)
kubectl create namespace home-automation
# Apply ConfigMap
kubectl apply -f k8s-configmap.yaml -n home-automation
# Apply Deployment
kubectl apply -f k8s-deployment.yaml -n home-automation
# Check status
kubectl get pods -n home-automation
kubectl logs -f deployment/google-home-notifier -n home-automation
# Test the service
kubectl port-forward service/google-home-notifier-service 5000:5000 -n home-automationFor production/secure deployments:
# Use the security-hardened configuration
kubectl apply -f k8s-secure-deployment.yamlSee k8s-secure-deployment.yaml for security-hardened Kubernetes deployment with:
- No
hostNetworkrequirement - Security contexts and non-root user
- Resource limits and network policies
- ClusterIP service (internal access only)
- No Authentication: This service has no built-in authentication
- Public Exposure: Never expose this service directly to the internet without proper security measures
- Internal Use Only: Recommended for internal networks or behind VPN/firewall
- Alternative Access: Use
kubectl port-forwardor VPN for external access
If you need external access, consider:
- Adding authentication (API keys, OAuth, etc.)
- Using VPN or private network access
- Implementing rate limiting
- Adding input validation and sanitization
- Verify the Chromecast IP address:
CHROMECAST_IP=192.168.1.100 - Check network connectivity:
ping 192.168.1.100 - Ensure devices are on the same network
- Try the discovery test:
curl http://localhost:5000/discover/test
- Check volume levels:
curl http://localhost:5000/test/volume - Test with external audio:
curl http://localhost:5000/test/external - Verify network accessibility from Chromecast to the service
- Check firewall settings (Windows: allow port 5000)
- Use
EXTERNAL_HOSTfor containerized environments - For Docker: set
EXTERNAL_HOSTto the host machine's IP - For Kubernetes: set
EXTERNAL_HOSTto the node IP - Test local IP detection:
curl http://localhost:5000/test/local-ip
- Use
hostNetwork: truein Kubernetes for Chromecast discovery - Ensure proper volume mounts for TTS cache
- Set appropriate resource limits
- Check pod logs:
kubectl logs -f pod-name
Use these endpoints to diagnose issues:
# Check discovery status
curl http://localhost:5000/discover/status
# Get detailed debug info
curl http://localhost:5000/discover/debug
# Test discovery manually
curl http://localhost:5000/discover/test
# Test different audio formats
curl http://localhost:5000/test/audio-formats
# Test volume control
curl http://localhost:5000/test/volume# Allow inbound connections on port 5000
New-NetFirewallRule -DisplayName "Google Home Notifier" -Direction Inbound -Protocol TCP -LocalPort 5000 -Action Allowsudo ufw allow 5000/tcpsudo iptables -A INPUT -p tcp --dport 5000 -j ACCEPT# Install dependencies
pip install -r requirements.txt
# Set environment variables
export CHROMECAST_IP=192.168.1.100
export PLAYBACK_VOLUME=0.6
# Run in debug mode
python main.pyThe application is structured with clear separation of concerns:
- Discovery: Background thread for device discovery
- Audio: TTS generation and playback functions
- Network: Intelligent host detection for different environments
- API: Flask routes for HTTP endpoints
Test the application using the built-in test endpoints:
# Test TTS functionality
curl "http://localhost:5000/say/?text=Testing"
# Test MP3 playback
curl "http://localhost:5000/test/mp3"
# Test volume control
curl "http://localhost:5000/test/volume"
# Test network connectivity
curl "http://localhost:5000/test/local-ip"This project is based on harperreed/google-home-notifier-python and maintains the same open-source spirit.
Contributions are welcome! Please feel free to submit a Pull Request.
For issues and questions:
- Check the troubleshooting section
- Use the debug endpoints to gather information
- Open an issue with detailed information about your environment