The Problem
Automated camera capture is easy; making sense of what was captured is not. This repo solves the narrow problem of turning periodic webcam snapshots into a spoken, character-voiced narration of whatever the camera sees. It is a demo of a three-stage pipeline: capture an image, describe it with a vision model, and read the description aloud with a synthetic voice.
What This Does
capture.py grabs frames from a webcam and writes them to frames/. narrator.py is the core: it encodes a frame to base64, sends it to GPT-4's vision endpoint, gets a descriptive line, and plays it back as audio using ElevenLabs. Four pre-recorded MP3/WAV files in assets/ act as fallback or intro audio.
The repo is a fork of cbh123/narrator (4,427 stars) with no modifications beyond the original. It is a demo, not a library.
How It Is Wired
Execution starts at main in narrator.py:75. The call graph is linear and shallow:
main→encode_image(reads a file fromframes/)main→analyze_image→generate_new_line→client.chat.completions.create(the model call that leaves the process)main→play_audio(writes/plays audio)
There are 5 internal call edges total, and the two modules (capture.py, narrator.py) have zero imports between them—they are independent processes. narrator.py owns all five functions and handles every external effect: file I/O, the secret-generating operation (likely an API key or token), and the model inference. capture.py is a separate, standalone script.
The blast radius is contained: narrator.py is the only file that matters for the core loop, and it is small enough to rewrite in an afternoon. No cycles, no hubs, no hidden coupling.
How To Use It
The README documents the full flow. Setup is standard pip:
python3 -m pip install virtualenv
python3 -m virtualenv venv
source venv/bin/activate
pip install -r requirements.txt
Configuration requires three environment variables: OPENAI_API_KEY, ELEVENLABS_API_KEY, and a voice ID obtained from ElevenLabs' API. Run it in two terminals:
python capture.py
python narrator.py
capture.py writes frames to frames/; narrator.py picks them up and narrates.
Real-World Use
This is a demo, not a production system. A realistic use is a personal ambient monitor: point a webcam at a workspace, run capture.py every few seconds, and have narrator.py give a spoken status update ("You appear to be slouching"). The assets/ files (stop_slouching.mp3, wonderful_posture.wav) suggest exactly that use case. For anything beyond a toy, you would replace the file-based handoff with a queue and add error handling.
Code Health & Issues
Static analysis (deterministic, from the pipeline) found the following:
- Med/SDLC - No test files detected; untested code paths across the entire repo.
- Med/SDLC - No CI/CD pipeline; no automated build or test gate.
- Med/SDLC - No LICENSE file; unclear usage and redistribution rights.
- Low/Risk - Dependencies declared without a lockfile; non-reproducible builds from
requirements.txt.
Beyond the measured findings, the structure shows no Dockerfile, no committed secrets, and no documentation beyond the README. For a demo, this is acceptable; for anything long-lived, add tests and a lockfile.
The Bottom Line
A clean, minimal demo that does exactly one thing and does it in ~75 lines of Python. The code is readable and the architecture is trivially extensible, but it has no tests, no license, and no CI. Use it as a reference for a vision-to-speech pipeline, not as a foundation for production work.