Automated narrated Marp presentations with Google Cloud Text-to-Speech
Marptalk can also generate videos using ffmpeg, with sound and subtitles -- check it out!
I believe a good slide presentation isn't just the slides on the screen, but what's being said at the same time, so generating both simultaneously and being able to see and iterate on both simultaneously, produces better presentations.
Since Marp presentations are just text, the first draft can be easily generated by an LLM, then edited by a human.
Using an AI agent, you can request a high-level presentation topic and get a complete first draft in minutes, complete with spoken content.
This can be useful for generating presentations to learn a new topic, with visual guides and spoken narration.
You could also use these tools to generate a presentation in another language, to localize a presentation to an international audience.
- 
Install dependencies:
npm install
 - 
Set up Google Cloud authentication:
# Option 1: Use gcloud CLI (recommended) gcloud auth application-default login # Option 2: Use service account key file export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account-key.json"
 - 
Run the demo:
npm run demo
 - 
Open the result:
open dist/index.html
 
node src/generate.js <input.md> [options]-o, --output <dir>: Output directory (default:dist)--voice <voice>: GCP TTS voice name (default:en-US-Journey-D)--language <code>: Language code (default:en-US)--key-file <path>: Path to Google Cloud service account key file--max-slides <num>: Maximum slides for testing--generate-tts: Generate TTS audio files (default: false)--generate-srt: Generate SRT subtitle file for video captions (default: false)--generate-chapters: Generate YouTube chapter markers file (default: false)--srt-filename <name>: Custom filename for SRT file (default:subtitles.srt)--chapters-filename <name>: Custom filename for chapters file (default:chapters.txt)--generate-video: Generate MP4 video of the presentation with synchronized audio (default: false)--video-filename <name>: Custom filename for video file (default:presentation.mp4)--video-width <pixels>: Video width in pixels (default: 1920)--video-height <pixels>: Video height in pixels (default: 1080)--video-fps <number>: Video frames per second (default: 30)--video-subtitles <mode>: Subtitle mode:"off","soft"(toggleable), or"hard"(burned-in) (default:soft)
English (en-US):
en-US-Journey-D- Natural, conversational (default)en-US-Journey-F- Warm, friendly female voiceen-US-Neural2-A- Professional male voiceen-US-Neural2-C- Clear female voiceen-US-Neural2-J- Energetic male voice
Other Languages:
es-ES-Neural2-A- Spanish (Spain)fr-FR-Neural2-A- Frenchde-DE-Neural2-B- Germanja-JP-Neural2-B- Japanese
Create a .md file with Marp frontmatter and speaker notes:
---
marp: true
theme: default
---
# My Slide Title
Some slide content here.
<!--
This is the speaker note that will be converted to audio.
Make sure to write natural, conversational text that sounds
good when spoken aloud.
-->
---
# Second Slide
More content...
<!--
Another speaker note for the second slide.
--># Basic generation
node src/generate.js my-presentation.md
# With custom voice and language
node src/generate.js my-presentation.md --voice en-US-Journey-F --language en-US
# Test with first 3 slides only
node src/generate.js my-presentation.md --max-slides 3
# Skip TTS generation (use existing audio files, saves money)
node src/generate.js my-presentation.md --no-generate-tts
# Generate with SRT subtitles and YouTube chapters
node src/generate.js my-presentation.md --generate-srt --generate-chapters
# Generate complete video with subtitles and chapters
node src/generate.js my-presentation.md --generate-video --generate-srt --generate-chapters
# Quick video generation using existing audio
node src/generate.js my-presentation.md --no-generate-tts --generate-video --generate-srt
# Custom subtitle and chapter filenames
node src/generate.js my-presentation.md --generate-srt --generate-chapters --srt-filename "my-captions.srt" --chapters-filename "my-chapters.txt"Open dist/index.html in your browser and use the controls:
- ▶ Start: Begin automated playback
 - ⏸ Pause: Pause/resume presentation
 - ⏹ Stop: Stop and return to manual mode
 - 🔊 Sound: Toggle audio on/off
 
Space: Start/pause presentationEscape: Stop presentationM: Toggle muteArrow keys: Navigate slides (when stopped)
Marptalk uses a multi-stage pipeline:
- Stage A: Extract speaker notes from Marp markdown
 - Stage B: Generate audio files using Google Cloud TTS
 - Stage C: Create self-playing HTML presentation
 - Stage D (Optional): Generate SRT subtitles, YouTube chapters, and MP4 videos
 
Marptalk can generate additional outputs to help with video publishing:
Generate standard SRT subtitle files for video captions:
node src/generate.js my-presentation.md --generate-srtThe SRT file includes:
- Sequential numbering
 - Precise timestamps (HH:MM:SS,mmm format)
 - Speaker notes as caption text
 - Automatic duration calculation based on word count (150 words/minute)
 
Example SRT output:
1
00:00:00,000 --> 00:00:13,599
Welcome to Marptalk, a revolutionary system for creating automated narrated presentations.
2
00:00:13,599 --> 00:00:38,399
Traditional presentation narration faces several challenges...
Generate YouTube-compatible chapter markers:
node src/generate.js my-presentation.md --generate-chaptersThe chapters file includes:
- Timestamps in YouTube format (M:SS or H:MM:SS)
 - Slide titles as chapter names
 - Ready to copy-paste into YouTube video descriptions
 
Example chapters output:
0:00 - Welcome to Marptalk
0:13 - The Problem
0:38 - The Marptalk Solution
1:01 - Key Features
Generate both SRT and chapters together:
node src/generate.js my-presentation.md --generate-srt --generate-chaptersSpecify custom output filenames:
node src/generate.js my-presentation.md \
  --generate-srt --srt-filename "my-captions.srt" \
  --generate-chapters --chapters-filename "my-chapters.txt"- Upload your video file to YouTube
 - In YouTube Studio, go to "Subtitles" and upload the generated 
.srtfile - Copy the contents of the chapters file and paste into your video description
 - Save changes - your video now has both captions and chapter markers!
 
Generate complete MP4 videos of your presentations with synchronized audio, subtitles, and perfect timing:
# Basic video generation
node src/generate.js my-presentation.md --generate-video
# Video with soft subtitles and chapters (subtitles can be toggled)
node src/generate.js my-presentation.md --generate-video --generate-srt --generate-chapters
# Video without subtitles
node src/generate.js my-presentation.md --generate-video --video-subtitles off
# Video with hard-coded subtitles (always visible)
node src/generate.js my-presentation.md --generate-video --generate-srt --video-subtitles hard
# Custom video settings
node src/generate.js my-presentation.md \
  --generate-video \
  --video-filename "my-presentation.mp4" \
  --video-width 1920 \
  --video-height 1080 \
  --video-subtitles softMarptalk uses an efficient static slide approach:
- Slide Capture: Takes high-quality screenshots of each slide
 - Audio Analysis: Analyzes each slide's audio file to get precise durations
 - Video Assembly: Uses FFmpeg to combine slides with perfect timing
 - Audio Sync: Each slide displays for exactly its audio duration
 - Subtitle Integration: Embeds SRT subtitles directly into the video
 
- Perfect Synchronization: Each slide shows for its exact audio duration
 - High Quality: 1920×1080 H.264 video with AAC audio
 - Flexible Subtitles: Choose between soft (toggleable), hard (burned-in), or no subtitles
 - Efficient Processing: Static slides, not screen recording
 - Fast Generation: Typical presentation renders in under 30 seconds
 
Generated files:
presentation.mp4- Complete MP4 video with audio and subtitlesvideo_info.json- Recording metadata (durations, slide count, etc.)video_frames/- Individual slide screenshotsvideo_frame_*.jpg- Sample frames for verificationcombined_audio.wav- Combined audio trackslides.txt- FFmpeg timing configuration
soft(default): Subtitles are embedded as a separate stream that viewers can turn on/offhard: Subtitles are burned into the video and always visibleoff: No subtitles are included in the video
Recommendation: Use soft subtitles for most cases as they provide accessibility while allowing viewers to control visibility.
- FFmpeg: Must be installed and available in PATH
 - Chrome/Chromium: For slide screenshot capture
 - Audio Files: Generated by previous stages
 
{
  "slides": 7,
  "actualDuration": 163.728,
  "slideDurations": [15.528, 28.008, 23.856, 19.488, 28.824, 22.488, 25.536],
  "dimensions": { "width": 1920, "height": 1080 },
  "method": "static-slides"
}Your generated MP4 files are ready for direct upload to:
- YouTube: With embedded subtitles and chapter markers
 - Vimeo: Professional quality with captions
 - Social Media: Optimized format for most platforms
 - Learning Platforms: Compatible with LMS systems
 
- Node.js 16+
 - Google Cloud account with Text-to-Speech API enabled
 - Modern web browser
 - Chrome/Chromium browser (for video generation)
 - FFmpeg (for video generation) - Install with:
- macOS: 
brew install ffmpeg - Ubuntu/Debian: 
apt-get install ffmpeg - Windows: Download from ffmpeg.org
 
 - macOS: 
 
- Write speaker notes in a conversational tone
 - Keep notes concise but informative
 - Test different voices to find what works best
 - Use 
--no-generate-ttsfor faster iteration when updating slides/styles - Use the pause/resume controls during live presentations
 - The system handles browser autoplay restrictions gracefully
 - Soft subtitles are recommended for accessibility and viewer choice
 
- Check browser autoplay settings
 - Try clicking the start button instead of letting it auto-start
 - Verify audio files were generated in 
dist/audio/ 
- Verify 
gcloud auth application-default loginworked - Check that Text-to-Speech API is enabled in your GCP project
 - Ensure billing is set up (free tier available)
 
- Check GCP TTS documentation for supported voices
 - Verify language code matches voice name (e.g., 
en-USwithen-US-Journey-D) 
- Make sure notes are enclosed in 
<!-- -->comments - Verify the Marp CLI extracted notes to 
.temp/