A real-time story that reads your face through a webcam and rewrites itself as you feel. Smile and the world warms up. Look sad and it turns gentle. No controller, no dialogue choices, just your expression.
"What if the story could see how you feel?"
The AI Director watches your face, classifies your mood in real time, and uses it to choose which version of each story scene you see, while the background, particles, and mood of the world shift to match.
No buttons to press. No menus. Just react.
Most interactive stories ask you to tell them what you want through menus, dialogue trees, or button presses. But the strongest reactions are the ones you never type.
This project explores a different input: your emotional state.
- Webcam is the only controller, so there is nothing to learn
- Every scene has four emotional variants, so the same story plays differently for different people
- A director layer decides when to advance and which mood to follow, instead of a fixed script
- Everything runs locally, so no video is stored or sent anywhere
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Webcam โโโโโโถโ EmotionDetector โ
โ (live frames)โ โ FER โ DeepFace โ Haar cascade (fallback) โ
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโ
โ raw emotions mapped to
โ happy ยท uplift ยท sad ยท neutral
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Temporal smoothing โ
โ rolling average over recent frames โ
โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโ
โ stable emotion + scores
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ AI Director (StorySystem) โ
โ picks scene variant ยท decides when to advanceโ
โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ GameWindow โ
โ gradient ยท particles ยท character ยท story ยท HUDโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Detection pipeline:
- OpenCV grabs a mirrored webcam frame
- A Haar cascade finds the largest face and crops it with a little padding
- FER (or DeepFace, or a smile heuristic) scores the emotions on that crop
- Raw emotions are folded into four categories
- Scores are averaged over the last few frames so the result does not flicker
- A smile detector nudges "neutral" toward "happy" when the model is unsure
Director pipeline:
- Current scene line is chosen from the stable emotion
- Every few seconds, if a face is present and confidence is high enough, the story advances
- The director biases gently toward warmer outcomes when you have been neutral or sad
- If your emotion changes mid-scene, a short reaction line appears without skipping the scene
| Parameter | Value |
|---|---|
| Input | Webcam (VideoCapture(0)) |
| Emotion categories | 4 (happy, uplift, sad, neutral) |
| Story structure | 8 scenes ร 4 emotional variants + ending |
| Detector chain | FER โ DeepFace โ Haar face + smile heuristic |
| Smoothing | Rolling buffer of 10 frames, averaged over the latest 6 |
| Auto-advance interval | 3.5 seconds |
| Min. confidence to advance | 0.25 |
| Window size | 960 ร 540 |
| Motion threshold (walking) | Mean frame difference > 7.0 |
| History display | Last 30 detected emotions |
| Character sprite | 160 ร 160 px at 10 FPS (optional) |
Detectors report many raw emotions. The engine folds them into four story moods.
| Raw emotion | Story mood | Effect on the world |
|---|---|---|
| happy, joy, content | happy | Green gradient, warm and friendly scenes |
| surprise, excited, shocked | uplift | Bright blue gradient, particles drift upward, mysterious and hopeful scenes |
| sad, angry, fear, disgust, worried | sad | Purple gradient, gentle and comforting scenes |
| neutral, calm, bored, serious | neutral | Grey gradient, calm and observational scenes |
| Feature | Detail |
|---|---|
| Live emotion detection | FER as primary, DeepFace as second choice, Haar smile cue as last resort |
| Never crashes on missing models | Each detector is optional; the next one in the chain takes over |
| Adaptive storyline | Each scene has a distinct line for every mood |
| Emotion-reactive visuals | Background gradient, vignette, and particles change with your mood |
| Motion-based walking | Moving in front of the camera speeds up the on-screen character |
| Live HUD | Circular webcam preview, emotion + confidence, emotion history bars |
| Custom character | Drop transparent PNG frames in a folder to replace the default orb |
| Fully local | No network calls at runtime, no video stored |
Procedural-Narrative-Engine/
โ
โโโ simple_ai_director.py Entry point
โ Story scenes, director logic, main loop
โ
โโโ emotion_detector.py EmotionDetector class
โ FER / DeepFace / Haar chain, smoothing
โ
โโโ game_window.py GameWindow class
โ Gradients, particles, HUD, story text box
โ
โโโ player_animation.py PlayerAnimation class
โ Sprite frame loader, alpha-blended overlay
โ
โโโ requirements.txt Python dependencies
โโโ __init__.py Package marker
- Python 3.8+
- A working webcam
- Even lighting on your face for the best results
git clone https://github.com/alwin-mj/Procedural-Narrative-Engine.git
cd Procedural-Narrative-Engine
# Recommended: virtual environment
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txtNote:
feranddeepfacedepend on TensorFlow, so the first install is large. Model weights may also download on the first run.
python simple_ai_director.py| Key | Action |
|---|---|
S |
Start the adventure |
SPACE |
Manually advance to the next scene |
Q |
Quit |
- Sit in front of the webcam with your face clearly visible
- Press S to begin
- Watch the first scene, and let your face do the talking
- The story advances by itself every few seconds while you are detected
- Change your expression and the scene text, colours, and particles respond
- After the last scene, the story closes with an ending line
Place transparent PNG frames here to replace the default glowing orb:
assets/player/walk/
โโโ frame_01.png
โโโ frame_02.png
โโโ ...
Frames are loaded in alphabetical order and resized to 160 ร 160.
Edit the SCENES list in simple_ai_director.py. Every scene needs one line per mood:
{
"neutral": "...",
"happy": "...",
"uplift": "...",
"sad": "..."
}The engine handles detection, smoothing, progression, and visuals for you.
| What | Where | Default |
|---|---|---|
| Window size | GameWindow(width, height) in main() |
960 ร 540 |
| Auto-advance interval | now - last > 3.5 in main() |
3.5 s |
| Min. confidence | conf > 0.25 in main() |
0.25 |
| Walking sensitivity | motion > 7.0 in main() |
7.0 |
| Smoothing window | deque(maxlen=10) and [-6:] in EmotionDetector |
6 frames |
Cause: The app opens camera index 0. Another app may be using it, or your webcam has a different index.
Fix: Close other apps that use the camera, or change cv2.VideoCapture(0) in simple_ai_director.py to 1.
Cause: Poor lighting, face too small, or the ML models failed to load and only the Haar fallback is running.
Fix: Face a light source, move closer, and check that fer installed correctly (pip install fer).
Cause: Newer DeepFace versions return a list from analyze() instead of a single dict, which the current fallback code does not unpack. The detector then drops to the Haar fallback.
Fix: Use FER as the primary detector, or update the DeepFace branch to read analysis[0].
Cause: FER and DeepFace load large models on startup.
Fix: Wait a few seconds. Set FER(mtcnn=False) in emotion_detector.py for a faster (but less accurate) face box.
- Voice narration โ text-to-speech that matches the mood of each scene
- Branching paths โ multiple routes and endings, not just one line per scene
- LLM-generated scenes โ replace pre-written variants with generated ones
- Audio emotion โ tone of voice as a second signal alongside the face
- Session recap โ save a "story of your session" at the end
- Music layer โ adaptive soundtrack that shifts with detected mood
- All processing happens locally. No video or images are stored or sent anywhere.
- Facial emotion recognition is approximate and can misread people, lighting, and camera angles. Treat it as an interaction mechanic, not a measure of how someone truly feels.
| Name | GitHub |
|---|---|
| Alwin John Shajan | @AlwinJCOde667 |
| Alwin M J | @alwin-mj |
B.Tech Computer Science & Engineering, Sahrdaya College of Engineering and Technology
MIT License โ see LICENSE for details.