Build · 1h · ₹0
A hands-free voice-driven workout companion built in Streamlit that generates dynamic exercise routines, manages synchronized set countdowns, and speaks audio cues via pyttsx3.
What it does
The mechanics, data flow, and user interaction model behind FitBuddy.
Say a muscle group ('chest', 'legs', 'back') or a trigger command ('okay start'), and FitBuddy generates a targeted routine (3 randomized exercises per muscle group), then guides you through 30-second set timers with audio countdowns and spoken feedback via local text-to-speech — keeping your hands free and eyes off the screen mid-set. Workout logs track duration, calories burned, and frequency, rendered on an interactive Altair dashboard.
Technical Highlights
- Full hands-free audio loop: Google Speech Recognition paired with offline pyttsx3 text-to-speech cues
- Synchronized set timers with voice alerts at halfway mark (15s) and final 5-second countdown
- Dynamic workout generator sampling 3 non-repetitive exercises per muscle group with rest intervals
- Interactive session analytics dashboard powered by Altair charts measuring workout intensity and volume
- Transparent state framing: clearly documents in-memory Streamlit session state architecture with SQLite upgrade path
Why it matters
The architectural judgment, practical engineering decisions, and core problems solved.
Touching a phone screen with sweaty hands mid-set breaks training cadence and momentum. Voice interaction is the natural ergonomic modality for physical training. FitBuddy demonstrates how to implement a complete bi-directional voice loop (Speech-to-Text input → Intent state machine → Text-to-Speech audio cues) inside Streamlit, turning a lightweight Python framework into an interactive workout companion.
Home gym training and bodyweight HIIT workouts where hands are occupied on floor or equipment
Accessibility-focused fitness companion for visually impaired trainees
Compact reference pattern for embedding bi-directional voice interaction into Streamlit apps
Interval timing and voice-guided stretch routines for desk workers
System architecture
End-to-end execution pipeline running across Streamlit, SpeechRecognition, pyttsx3, Altair, Python.
Captures microphone audio and transcribes spoken commands via Google Speech API
Generates randomized 3-exercise sets mapped to target muscle groups with rest intervals
Drives 30-second interval state machines with real-time Streamlit progress bars
Speaks countdown triggers, exercise transitions, and motivational encouragement
Renders session duration, exercise breakdown, and estimated energy expenditure
The path
Step-by-step implementation guide. Verbatim code snippets, configurations, and prompts.
Configuring Speech Recognition & Microphone Stream
Initialize SpeechRecognition with ambient noise calibration and timeout thresholds to capture short voice commands cleanly.
Verbatim Code / Config
recognizer = sr.Recognizer()
with sr.Microphone() as source:
recognizer.adjust_for_ambient_noise(source, duration=0.8)
audio = recognizer.listen(source, timeout=5, phrase_time_limit=4)
command = recognizer.recognize_google(audio).lower()Building Offline pyttsx3 Speech Synthesizer
Configure the offline text-to-speech engine with custom voice rate (160 wpm) and pitch properties for crisp gym audio cues.
Verbatim Code / Config
engine = pyttsx3.init()
engine.setProperty('rate', 165)
def speak(text: str):
engine.say(text)
engine.runAndWait()Synchronized Interval Timer & Streamlit Progress Loop
Create a non-blocking countdown loop updating Streamlit UI progress bars while speaking milestone announcements at 15s and 5s marks.
Verbatim Code / Config
for remaining in range(duration, 0, -1):
progress_bar.progress((duration - remaining) / duration)
time_placeholder.markdown(f'## {remaining}s')
if remaining == 15: speak('Halfway there! Keep pushing!')
elif remaining <= 3: speak(str(remaining))
time.sleep(1)Altair Session History Visualizer
Track completed exercises and set durations in Streamlit session_state, plotting cumulative volume and muscle group distribution in Altair.
Verbatim Code / Config
chart = alt.Chart(df_history).mark_bar().encode(
x=alt.X('exercise:N', title='Exercise'),
y=alt.Y('duration_sec:Q', title='Time Under Tension (s)'),
color='muscle_group:N'
).properties(height=280)Where it broke
The failure mode, root-cause breakdown, and resolution discovered during development.
The Tell
“Microphone listener hung indefinitely in noisy environments, freezing the entire Streamlit UI thread.”
Why it failed
Default SpeechRecognition.listen() blocks until silence is detected. Background music or heavy breathing prevented silence thresholds from triggering, locking the main execution thread.
The Fix
Added strict phrase_time_limit=4.0 and timeout=3.0 parameters to SpeechRecognition.listen(), paired with automatic ambient noise calibration on each turn, ensuring the listener never hangs.
What it cost
₹0 to build and run permanently within verified free tiers.
| Service / Tool | Cost | Free Tier Limits |
|---|---|---|
| Streamlit Framework | ₹0 | Open-source Apache 2.0 web framework |
| Google Speech API (SpeechRecognition) | ₹0 | Free default endpoint for SpeechRecognition library |
| pyttsx3 Engine | ₹0 | 100% offline local system text-to-speech with zero cloud dependencies |
| Altair Visualization | ₹0 | Open-source declarative statistical visualization library |
| Local Python Runtime | ₹0 | Runs locally on standard CPU hardware |
Make it yours
Three concrete variations you can build and ship using this exact foundation.
- 01
Tabata & HIIT Voice Interval Coach: Runs high-intensity 20s work / 10s rest cycles with custom audio beeps and interval stats.
- 02
Yoga & Pranayama Breath Pacer: Speaks calming inhalation/exhalation pacing cues with gentle background chimes.
- 03
Physiotherapy Rep Counter & Form Reminder: Guides rehabilitation patients through slow eccentric holds with verbal form cues.
Where next
Ready to ship FitBuddy?
Review the architecture, clone the prompt and implementation steps, and deploy your live URL for ₹0.