{"id":46937899,"url":"https://github.com/herrkaefer/snowman","last_synced_at":"2026-03-11T06:04:14.544Z","repository":{"id":293684413,"uuid":"946412719","full_name":"herrkaefer/snowman","owner":"herrkaefer","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-06T21:53:56.000Z","size":436,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-06T22:36:50.798Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/herrkaefer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-11T05:15:29.000Z","updated_at":"2026-03-06T21:54:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"eea50836-1da6-4359-8dba-11ec7e14cc78","html_url":"https://github.com/herrkaefer/snowman","commit_stats":null,"previous_names":["herrkaefer/snowman"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/herrkaefer/snowman","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herrkaefer%2Fsnowman","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herrkaefer%2Fsnowman/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herrkaefer%2Fsnowman/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herrkaefer%2Fsnowman/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/herrkaefer","download_url":"https://codeload.github.com/herrkaefer/snowman/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herrkaefer%2Fsnowman/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30372564,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"online","status_checked_at":"2026-03-11T02:00:07.027Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-03-11T06:03:47.564Z","updated_at":"2026-03-11T06:04:14.531Z","avatar_url":"https://github.com/herrkaefer.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"./assets/snowman_retro.png\" width=\"240\" height=\"240\" alt=\"Snowman Retro Pixel\"\u003e\n  \u003ch1\u003eSnowman\u003c/h1\u003e\n  \u003cp\u003e\u003cstrong\u003eThe Home Voice Agent for Raspberry Pi\u003c/strong\u003e\u003c/p\u003e\n\u003c/div\u003e\n\n---\n\nSnowman now has two separate apps:\n\n- `pipeline/`: the existing local-first assistant, frozen as a baseline\n- `realtime/`: a new OpenAI Realtime API version for Raspberry Pi voice-agent work\n\n## Pipeline vs Realtime\n\n### Design Difference\n\n- `pipeline/` is a classic custom pipelined stack: wake word, VAD, STT, LLM, and TTS are stitched together..\n- `realtime/` is a realtime speech-to-speech voice agent: the Pi handles wake word detection and audio playback, while the live conversation runs through a realtime speech session via websocket. Tool use and memory are also equipped.\n\n### Tradeoffs\n\n| App | Strengths | Weaknesses |\n| --- | --- | --- |\n| `pipeline/` | Lower cost and easier to run as a baseline | Noticeably higher latency, with weaker non-English STT performance |\n| `realtime/` | Better overall responsiveness and a more natural voice experience | More expensive for heavy use |\n\n### Which One To Choose\n\n- Choose `pipeline/` for cost-sensitive usage, debugging, benchmarking, or as a fallback when you want tighter control over each stage of the stack.\n- Choose `realtime/` for the primary home voice-agent experience, especially when low latency, more natural turn-taking, and future tool / memory / device-control features matter more than cost.\n\n## Pipeline App\n\nThe original app was moved intact into [`pipeline/`](./pipeline/README.md). It remains the fallback and comparison target while the new realtime path is developed.\n\n### Components\n\n- Porcupine wake word detection\n- Cobra VAD\n- faster-whisper STT\n- LLM for response generation\n- Edge TTS\n- Tavily search\n\n### Architecture\n\n```mermaid\nflowchart LR\n    user[\"User\"] --\u003e wake[\"Porcupine wake word\"]\n    wake --\u003e session[\"Conversation session controller\"]\n    session --\u003e record[\"PvRecorder + Cobra VAD\"]\n    record --\u003e stt[\"faster-whisper STT\"]\n    stt --\u003e llm[\"Gemini response generation\"]\n    llm --\u003e tts[\"Edge TTS\"]\n    tts --\u003e speaker[\"Speaker playback\"]\n    llm -. optional .-\u003e search[\"Tavily web search\"]\n    search -. context .-\u003e llm\n    speaker --\u003e next[\"Next turn in session\"]\n    next --\u003e session\n    session -. timeout / goodbye .-\u003e wake\n```\n\n## Realtime App\n\nThe new app lives in [`realtime/`](./realtime/README.md). \n\n### Components\n\n- Porcupine for wake word detection \n- realtime speech-to-speech via websocket (OpenAI realtime API /  Gemini Live API)\n- Tools: web search, memory search / update, and GPIO operation, etc.\n\n### Architecture\n\n```mermaid\nflowchart LR\n    user[\"User\"] --\u003e wake[\"Porcupine wake word\"]\n    wake --\u003e session[\"Session controller\"]\n    session --\u003e rt[\"Realtime audio over WebSocket\"]\n    rt --\u003e tools[\"Tool registry\"]\n    tools --\u003e webTool[\"web_search\"]\n    webTool --\u003e web[\"Web\"]\n    tools --\u003e memoryTool[\"memory tools\"]\n    memoryTool --\u003e memory[\"Persistent memory\"]\n    tools --\u003e gpioTool[\"GPIO tools\"]\n    gpioTool --\u003e gpio[\"GPIO devices\"]\n    tools --\u003e rt\n    rt --\u003e speaker[\"Streamed reply playback\"]\n    speaker --\u003e next[\"Next turn in session\"]\n    next --\u003e session\n```\n\nIt is designed to run on the Raspberry Pi hardware that is already connected and reachable over SSH.\n\n### First Install and Configuration On Pi\n\nOn a fresh Raspberry Pi, run:\n\n```bash\ncurl -O https://raw.githubusercontent.com/herrkaefer/snowman/main/install-snowman.sh\nbash install-snowman.sh --target realtime\n```\n\nThe installer will:\n\n- install system dependencies\n- clone the repo to `~/voice-assistant-realtime`\n- install the realtime services\n- start the config UI on port `3010`\n\n### Access the Config UI\n\nThe config UI runs as the always-on `snowman-config-ui.service`, so you can reopen it later any time to change settings.\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"./assets/screenshot-config.png\" height=\"500\" alt=\"Snowman Config UI\"\u003e\n\u003c/div\u003e\n\nOpen it from another device on the same network:\n\n- `http://\u003cpi-ip\u003e:3010`\n- or, if local hostname resolution works on your network, `http://raspberrypi.local:3010`\n\nTo find the current Pi IP, run:\n\n```bash\nhostname -I\n```\n\nThen fill in the required fields and click `Save And Restart`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fherrkaefer%2Fsnowman","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fherrkaefer%2Fsnowman","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fherrkaefer%2Fsnowman/lists"}