You cannot flash the proprietary Google Home OS onto a Raspberry Pi. However, you can build a fully functional, always-listening Google Assistant voice satellite using the Google Assistant Embedded API (gRPC). This setup turns your Pi into a custom smart speaker that responds to "Hey Google," controls your smart home, and answers queries exactly like a commercial Google Nest Audio.
This guide targets the Raspberry Pi 5 (8GB variant) running Raspberry Pi OS (64-bit, Bookworm). We will use the Seeed Studio ReSpeaker 2-Mic HAT for I2S audio input/output and map a physical GPIO LED to indicate listening states. Expect to spend about $125 on parts and 2 to 3 hours on the bench.
Hardware BOM & Pin Mapping
The Raspberry Pi 5 requires a robust power delivery system to handle continuous audio processing and I2S streaming without brownouts. Do not use a standard 15W phone charger.
| Component | Exact Variant / Spec | Est. Cost |
|---|---|---|
| Microcontroller | Raspberry Pi 5 (8GB RAM) | $80.00 |
| Audio HAT | Seeed Studio ReSpeaker 2-Mics Pi HAT (V2.0) | $35.00 |
| Power Supply | Official 27W USB-C PD Power Supply (5V/5A) | $12.00 |
| Storage | 32GB microSD (SanDisk Extreme A2) | $9.00 |
| Indicator | 5mm Blue LED + 330Ω Resistor | $0.10 |
GPIO & I2S Pin Mapping
The ReSpeaker HAT sits directly on the 40-pin header, but it consumes specific BCM GPIO pins for the I2S audio bus. We will use a free pin for our status LED.
| BCM GPIO | Function | Physical Pin | Notes |
|---|---|---|---|
| GPIO 17 | Status LED | 11 | Connect via 330Ω resistor to LED Anode |
| GPIO 18 | I2S PCM_CLK | 12 | ReSpeaker HAT (Bit Clock) |
| GPIO 19 | I2S PCM_FS | 35 | ReSpeaker HAT (Frame Sync) |
| GPIO 20 | I2S PCM_DIN | 38 | ReSpeaker HAT (Data In / Mic) |
| GPIO 21 | I2S PCM_DOUT | 40 | ReSpeaker HAT (Data Out / Speaker) |
Google Cloud & API Configuration
Before writing code, you must register the Pi as an embedded device in the Google Cloud Platform (GCP). The Google Assistant SDK requires OAuth 2.0 credentials and a registered device_model_id.
- Enable the API: Go to the GCP Console, create a new project (e.g.,
pi-voice-satellite), and enable the Google Assistant API. - Configure OAuth: Navigate to APIs & Services > Credentials. Create an OAuth Client ID (select "Other" or "Desktop App"). Download the JSON file and rename it to
client_secret.json. - Register the Device: Use the Google Assistant SDK registration tool to generate a
device_model_id. You will need this exact string in your Python code. - Generate User Credentials: Run the
google-oauthlib-toolon the Pi to exchange the client secret for a localcredentials.jsontoken. This token grants the Pi permission to act on your Google account.
Python Assistant Implementation
We will use the google-assistant-grpc package alongside sounddevice for low-latency audio streaming and gpiozero for the LED indicator. Install the dependencies in a virtual environment:
sudo apt install portaudio19-dev libffi-dev libssl-dev
python3 -m venv ~/assistant-env
source ~/assistant-env/bin/activate
pip install google-assistant-grpc sounddevice gpiozero
Below is the complete, runnable script. It establishes a gRPC channel, streams microphone chunks to Google's servers, and plays back the synthesized response.
import sounddevice as sd
import grpc
import json
import os
from gpiozero import LED
from google.assistant.embedded.v1alpha2 import embedded_assistant_pb2
from google.assistant.embedded.v1alpha2 import embedded_assistant_pb2_grpc
# --- Pin Definitions & Config ---
STATUS_LED = LED(17) # BCM GPIO 17
SAMPLE_RATE = 16000
BLOCK_SIZE = 512
DEVICE_MODEL_ID = 'your-registered-model-id-123'
PROJECT_ID = 'pi-voice-satellite'
CREDENTIALS_PATH = os.path.expanduser('~/.config/google-oauthlib-tool/credentials.json')
def load_credentials():
"""Loads the local OAuth2 token generated by google-oauthlib-tool."""
try:
with open(CREDENTIALS_PATH, 'r') as f:
creds = json.load(f)
return creds['access_token']
except (FileNotFoundError, KeyError) as e:
print(f"[FATAL] Credential error: {e}. Run google-oauthlib-tool to refresh.")
exit(1)
def audio_generator():
"""Yields raw audio chunks from the ReSpeaker I2S microphone."""
stream = sd.RawInputStream(samplerate=SAMPLE_RATE, blocksize=BLOCK_SIZE,
dtype='int16', channels=1)
with stream:
while True:
data, overflowed = stream.read(BLOCK_SIZE)
if overflowed:
print("[WARN] Audio buffer overflowed")
yield data
def main():
access_token = load_credentials()
STATUS_LED.off()
# Setup gRPC Channel
channel = grpc.secure_channel('embeddedassistant.googleapis.com',
grpc.ssl_channel_credentials())
assistant = embedded_assistant_pb2_grpc.EmbeddedAssistantStub(channel)
config = embedded_assistant_pb2.AssistantConfig(
audio_in_config=embedded_assistant_pb2.AudioInConfig(
encoding=embedded_assistant_pb2.AudioInConfig.Encoding.LINEAR16,
sample_rate_hertz=SAMPLE_RATE),
audio_out_config=embedded_assistant_pb2.AudioOutConfig(
encoding=embedded_assistant_pb2.AudioOutConfig.Encoding.LINEAR16,
sample_rate_hertz=SAMPLE_RATE),
device_config=embedded_assistant_pb2.DeviceConfig(
device_model_id=DEVICE_MODEL_ID)
)
print("[INFO] Google Assistant gRPC stream active. Say 'Hey Google'...")
try:
while True:
# Create the request generator
def request_gen():
yield embedded_assistant_pb2.AssistRequest(config=config)
for chunk in audio_generator():
yield embedded_assistant_pb2.AssistRequest(audio_in=chunk)
STATUS_LED.on() # Indicate listening/streaming
# Stream to Google and process responses
for resp in assistant.Assist(request_gen(), metadata=[('authorization', f'Bearer {access_token}')]):
if resp.event_type == embedded_assistant_pb2.AssistResponse.ON_CONVERSATION_TURN_STARTED:
print("[EVENT] Conversation started")
if resp.audio_out.audio_data:
# Play audio back through ReSpeaker DAC
sd.play(resp.audio_out.audio_data, samplerate=SAMPLE_RATE)
sd.wait()
STATUS_LED.off() # Return to idle
except grpc.RpcError as e:
print(f"[ERROR] gRPC Failure: {e.code()} - {e.details()}")
except KeyboardInterrupt:
print("\n[INFO] Shutting down assistant.")
finally:
STATUS_LED.off()
channel.close()
if __name__ == '__main__':
main()
Debugging: gRPC & Audio Failures
When building voice satellites, 90% of your debugging time will be spent on authentication tokens and I2S driver conflicts. If the script crashes immediately upon calling assistant.Assist(), check the terminal output.
The Most Common Error
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with: status = StatusCode.UNAUTHENTICATED, details = "Request had invalid authentication credentials.">
First three things to check when this fails:
- Device Model ID Mismatch: The
DEVICE_MODEL_IDstring in the Python script must exactly match the one you registered in the GCP Console. A single typo triggers an UNAUTHENTICATED state. - Expired OAuth Token: The local
credentials.jsontoken expires. Re-rungoogle-oauthlib-tool --refresh --client-secrets client_secret.json --scope https://www.googleapis.com/auth/assistant-sdk-prototypeto generate a fresh token. - API Not Enabled: Verify that the Google Assistant API (not just the Cloud Speech-to-Text API) is explicitly enabled in your GCP project dashboard.
pactl list sinks to verify the Seeed I2S card is the default sink, or temporarily kill the PipeWire daemon (systemctl --user stop pipewire) during testing.
Extending and Simplifying the Build
The continuous streaming model used above consumes significant bandwidth and requires Google's cloud servers to process the wake word. Depending on your deployment environment, you may want to alter this behavior.
- Simplify (Push-to-Talk): If you want to eliminate the "Hey Google" wake word and save bandwidth, wire a momentary push-button to GPIO 27. Modify the
audio_generator()to only yield audio chunks whilebutton.is_pressedis True. This turns the Pi into a high-fidelity walkie-talkie. - Extend (Local Wake Word): Integrate Picovoice Porcupine. Porcupine runs locally on the Pi's CPU, listening for a custom wake word (like "Computer"). Once detected, it triggers the gRPC stream to Google. This drastically reduces cloud API calls and improves privacy, as audio is only streamed after the local wake word triggers.
Frequently Asked Questions
Can I run the official Google Home app directly on Raspberry Pi OS?
No. The Google Home app is compiled for Android and iOS ARM architectures and relies on proprietary Google Play Services. While you can run Android emulators on a Pi, the performance is unusable for real-time smart home control. The gRPC Embedded API used in this guide is the only supported, performant method to integrate Google Assistant natively on Linux.
Why does my ReSpeaker HAT show "no soundcard found" on Pi 5?
The Raspberry Pi 5 uses a completely new RP1 I/O controller, which broke older I2S kernel overlays. If aplay -l returns no devices, you are likely using an outdated Seeed kernel driver. You must use the updated seeed-voicecard DKMS package specifically patched for the Pi 5's Bookworm kernel, or manually configure the dtoverlay=seeed-2mic-voicecard in /boot/firmware/config.txt after pulling the latest Seeed Studio GitHub repository.
How do I connect this Pi Google Home to my existing smart home devices?
You do not need to program MQTT or Zigbee bridges into the Python script. Because the Pi authenticates via your personal Google account OAuth token, it automatically inherits your Google Home ecosystem. Simply open the Google Home app on your phone, go to Settings > Assistant > Devices, and your Pi will appear as a new speaker. Any smart lights or thermostats linked to your Google account can be controlled by voice through the Pi immediately.






