A lightweight, dependency-free interactive audio drama and fiction podcast framework with dynamic state-driven branching, Web Audio API visualizers, and automatic TTS/procedural sound fallback.
By : SAMUELSON G
The Descent bridges traditional fiction podcasting with dynamic, choice-driven video game storytelling. Built entirely in vanilla JavaScript with zero external runtime dependencies, the engine renders synchronous audio-transcript experiences, tracks persistent session variables, and branches narrative pathways seamlessly based on player decisions.
If external audio files fail to load or face CORS restrictions, the system gracefully degrades to a procedural synthesis fallback layer utilizing the Web Speech API (SpeechSynthesis) for dialogue and Web Audio API (OscillatorNode, BiquadFilterNode) for sound effects.
- Stateful Decision Graph: Interactive choice nodes modify persistent session variables, dynamically altering downstream conditional plot points.
- Dual-Layer Audio Engine:
- Primary: Native HTML5
Audioplayback with millisecond-accurate transcript synchronization. - Fallback: Built-in
SpeechSynthesisvoice parameterization (pitch/rate per character) and procedural synthesis for SFX.
- Primary: Native HTML5
- 6-Band Logarithmic FFT Visualizer: Hardware-accelerated real-time audio spectrum analyzer built on
AnalyserNode. - WCAG 2.1 AAA Accessibility Compliance:
- Full keyboard navigation and tab-focus trapping in modals (
Tab/Shift+Tab). Escapekey listeners and focus restoration.- Dynamic ARIA live-region and slider updates (
aria-valuenow,aria-valuemax).
- Full keyboard navigation and tab-focus trapping in modals (
- Sub-Millisecond UI Sync Loop: Driven by
requestAnimationFramefor smooth transcript scrolling, visualizer updates, and progress bar synchronization. - Defensive Local Persistence: Encapsulated state storage with error-guarded
localStorageserialization. - Responsive Dark/Light System: CSS custom-property theme switcher with memory retention.
βββββββββββββββββββββββββββ
β Episode Data Graph β
ββββββββββββββ¬βββββββββββββ
β
βΌ
βββββββββββββββββββββββββββ
β Engine Controller β
ββββββββ¬ββββββββββββ¬βββββββ
β β
ββββββββββββββββββββ ββββββββββββββββββββ
βΌ βΌ
βββββββββββββββββββββββββ βββββββββββββββββββββββ
β Primary HTML5 Audio β β Synthesis Fallback β
β (CORS / File Stream) β β (Speech & Web Audio)β
ββββββββββββ¬βββββββββββββ ββββββββββββ¬βββββββββββ
β β
ββββββββββββββββββββ ββββββββββββββββββββ
βΌ βΌ
βββββββββββββββββββββββββββ
β rAF Render Loop & Sync β
ββββββββββββββ¬βββββββββββββ
β
ββββββββββββββββββββββββΌβββββββββββββββββββββββ
βΌ βΌ βΌ
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
β 6-Band FFT Viz β β Active Transcriptβ β State Mutations β
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
the-descent/
βββ assets/
β βββ audio/ # Audio assets (.mp3 / .wav)
β βββ scene1_entrance.mp3
β βββ scene2_water.mp3
β βββ scene2_wind.mp3
β βββ scene3_reunion.mp3
β βββ scene4_escape.mp3
β βββ scene4_lost.mp3
βββ index.html # Core application entry point (HTML, CSS, JS)
βββ LICENSE # MIT License
βββ README.md # System documentation
Because the project relies on native Web APIs without build steps or npm packages, you can launch it immediately using any local web server.
- Clone the repository:
git clone [https://github.com/Samuelson777/the-descent-interactive-audio.git](https://github.com/Samuelson777/the-descent-interactive-audio.git)
cd the-descent-interactive-audio
- Serve the directory using Python:
# Python 3
python3 -m http.server 8000
- Open in browser:
Navigate to
http://localhost:8000in Google Chrome, Mozilla Firefox, or Apple Safari.
- Open the project folder in Visual Studio Code.
- Right-click
index.htmland select Open with Live Server.
Narratives are configured as JSON node graphs inside index.html. You can add new scenes or choices by defining nodes in episodeData:
const episodeData = {
showId: "my-custom-story",
title: "Episode 1: Into the Dark",
initialNode: "scene_01",
nodes: {
"scene_01": {
audioSrc: "assets/audio/scene1.mp3",
transcript: [
{ start: 0.0, end: 4.0, speaker: "Narrator", text: "The rain pounded against the window." },
{ start: 4.5, end: 8.0, speaker: "Alex", text: "Do we open the lock or keep running?" }
],
onComplete: {
type: "branch",
prompt: "What should we do?",
choices: [
{
label: "Unlock the door",
nextNode: "scene_02_unlock",
mutations: [{ key: "hasKey", value: true }]
},
{
label: "Keep running",
nextNode: "scene_02_run",
mutations: [{ key: "hasKey", value: false }]
}
]
}
}
}
};continue: Immediately proceeds tonextNode.branch: Renders interactive decision buttons on screen.conditional: Evaluates state variables to route the player automatically.
The Descent successfully demonstrates a production-grade, stateful interactive audio drama framework that bridges traditional fiction podcasting with dynamic choice-driven video game storytelling. By pairing a state-variable choice graph with dual-layer audio rendering (native HTML5 Audio with an automated Web Speech API / procedural Web Audio synthesis fallback), the engine achieves resilient, sub-millisecond transcript and visualizer synchronization. Integrated with WCAG 2.1 AAA modal accessibility, seamless theme toggling, and resilient local storage recovery, the architecture delivers an immersive, fault-tolerant experience across all desktop and mobile browsers.
- Spatial & Binaural 3D Audio Processing: Integrate
PannerNodeandAudioListenerspatialization into the Web Audio graph to position voices and sound effects in 3D binaural space for headphone listeners. - Dynamic Multitrack Stem Layering: Transition from static single-track audio files to stem-based mixing (separating Dialogue, Ambient SFX, and Music), enabling real-time music tension shifts and dynamic atmospheric ducking based on player state variables.
- Generative AI Voice Streaming Integration: Upgrade the Web Speech synthesis fallback to stream low-latency, emotive AI voice models via WebRTC or Server-Sent Events for realistic voice rendering during dynamic content generation.
- Visual Story Tree & Branch Replayer: Add an interactive WebGL narrative node map that lets listeners visually inspect unlocked paths, view decision statistics, and jump back to previous decision forks without clearing session state.
- Visual & Haptic Sync Engine: Expand the time-indexed transcript schema to trigger synchronized haptic feedback patterns (via the Navigator Vibration API) and screen-shake canvas effects during high-intensity audio cues or ambient transitions.
- Progressive Web App (PWA) & Offline Pre-caching: Implement Service Worker audio chunk caching and offline support so users can stream or pre-download episodic audio packages seamlessly on mobile devices.
Contributions are welcome! Please follow these steps:
- Fork the repository.
- Create a feature branch (
git checkout -b feature/AmazingFeature). - Commit your changes (
git commit -m 'Add some AmazingFeature'). - Push to the branch (
git push origin feature/AmazingFeature). - Open a Pull Request.
Distributed under the MIT License. See LICENSE for more information.