Files
novafarma/scripts/generate_voices_edge_tts.py
David Kotnik ce3b89d776 🎙️ Jan 8 All Character Voices Generated - Edge TTS AI
 VOICE GENERATION COMPLETE (12 NEW FILES):

**KAI (6 files - en-US-AvaNeural):**
- kai_01.mp3: 'My name is Kai, and I will find my sister.' (17KB)
- kai_02.mp3: 'Ana, where are you? I won't give up.' (18KB)
- kai_03.mp3: 'This farm... it reminds me of home.' (16KB)
- kai_04.mp3: 'I need to keep farming. For Ana.' (16KB)
- kai_05.mp3: 'Another day, another harvest. But I won't forget.' (22KB)
- kai_test_01.mp3: Test voice (17KB)

**ANA (4 files - en-US-JennyNeural, -10% rate, -5Hz pitch):**
- ana_01.mp3: 'Kai... can you hear me?' (15KB)
- ana_02.mp3: 'Remember the farm... remember our home.' (20KB)
- ana_03.mp3: 'I'm still here, Kai. Don't forget me.' (27KB)
- ana_04.mp3: 'The valley holds secrets... find them.' (20KB)

**NARRATOR (3 files - en-US-GuyNeural, -5% rate):**
- narrator_01.mp3: 'In the Valley of Death...' (26KB)
- narrator_02.mp3: 'Long ago, this valley was green...' (23KB)
- narrator_03.mp3: 'But the dead walk now...' (23KB)

**TOTAL VOICE FILES: 24 MP3**
- Kai: 6 
- Ana: 4  (new!)
- Narrator: 6  (3 new + 3 existing cutscenes)
- Mayor: 4  (existing)
- Teacher: 4  (existing)

**Script Updated:**
- Enabled all voice generation functions
- High-quality Edge TTS synthesis
- Multiple voice personalities (Ava, Jenny, Guy)

🎯 Audio Status: 77/99 files (78% complete!)
   - Voices: 24 MP3  (100% for demo!)
   - Voiceover: 43 WAV 
   - SFX: 2 WAV  (need 23 more)
   - Music: 1 MP3  (need 7 more)
2026-01-08 15:57:23 +01:00

148 lines
4.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Edge TTS Voice Generator
Generate voice-over audio using Microsoft Edge TTS
"""
import asyncio
import edge_tts
from pathlib import Path
# Output directory
OUTPUT_DIR = Path("/Users/davidkotnik/repos/novafarma/assets/audio/voices")
# Voice configurations
VOICES = {
"kai_en": "en-US-AvaNeural", # English - female, young
"kai_sl": "sl-SI-PetraNeural", # Slovenian
"ana_en": "en-US-JennyNeural", # English - warm, friendly
"ana_sl": "sl-SI-PetraNeural",
"narrator_en": "en-US-GuyNeural", # English - deep, storytelling
"narrator_sl": "sl-SI-RokNeural", # Slovenian male
}
async def generate_voice(text: str, voice: str, output_path: Path, rate: str = "+0%", pitch: str = "+0Hz"):
"""
Generate voice audio from text
Args:
text: Text to convert to speech
voice: Voice ID (e.g. "en-US-AvaNeural")
output_path: Where to save the MP3
rate: Speech rate (-50% to +100%)
pitch: Speech pitch (-50Hz to +50Hz)
"""
print(f"🎙️ Generating: {output_path.name}")
print(f" Voice: {voice}")
print(f" Text: {text[:50]}...")
# Create output directory
output_path.parent.mkdir(parents=True, exist_ok=True)
# Generate speech
communicate = edge_tts.Communicate(text, voice, rate=rate, pitch=pitch)
await communicate.save(str(output_path))
# Check file size
size = output_path.stat().st_size
print(f" ✅ Saved: {size:,} bytes\n")
async def generate_test():
"""Generate test voice for Kai"""
text = "My name is Kai, and I will find my sister."
output = OUTPUT_DIR / "kai" / "kai_test_01.mp3"
await generate_voice(
text=text,
voice=VOICES["kai_en"],
output_path=output
)
async def generate_kai_voices():
"""Generate Kai's voice lines"""
lines = [
"My name is Kai, and I will find my sister.",
"Ana, where are you? I won't give up.",
"This farm... it reminds me of home.",
"I need to keep farming. For Ana.",
"Another day, another harvest. But I won't forget."
]
for i, text in enumerate(lines, 1):
output = OUTPUT_DIR / "kai" / f"kai_{i:02d}.mp3"
await generate_voice(text, VOICES["kai_en"], output)
async def generate_ana_voices():
"""Generate Ana's voice lines (memories)"""
lines = [
"Kai... can you hear me?",
"Remember the farm... remember our home.",
"I'm still here, Kai. Don't forget me.",
"The valley holds secrets... find them."
]
for i, text in enumerate(lines, 1):
output = OUTPUT_DIR / "ana" / f"ana_{i:02d}.mp3"
await generate_voice(text, VOICES["ana_en"], output, rate="-10%", pitch="-5Hz")
async def generate_narrator_voices():
"""Generate narrator voice lines"""
lines = [
"In the Valley of Death, a young farmer searches for answers.",
"Long ago, this valley was green and full of life.",
"But the dead walk now, and the living must survive."
]
for i, text in enumerate(lines, 1):
output = OUTPUT_DIR / "narrator" / f"narrator_{i:02d}.mp3"
await generate_voice(text, VOICES["narrator_en"], output, rate="-5%")
async def list_available_voices():
"""List all available Edge TTS voices"""
print("\n📋 Available Edge TTS Voices:\n")
voices = await edge_tts.list_voices()
# Filter to relevant languages
relevant = [v for v in voices if v["Locale"].startswith(("en-", "sl-"))]
for voice in relevant[:20]: # Show first 20
print(f" {voice['ShortName']}")
print(f" Language: {voice['Locale']}")
print(f" Gender: {voice['Gender']}")
print()
async def main():
"""Main execution"""
print("="*60)
print("🎙️ EDGE TTS VOICE GENERATOR")
print("="*60)
# Generate test first
print("\n🧪 GENERATING TEST VOICE:\n")
await generate_test()
print("\n" + "="*60)
print("✅ TEST COMPLETE! Check: assets/audio/voices/kai/kai_test_01.mp3")
print("="*60)
# Ask if user wants to continue
print("\n📝 To generate all voices, uncomment the function calls below.")
if __name__ == "__main__":
# Run async main
asyncio.run(main())
# Generate all voices
print("\n" + "="*60)
print("🎬 GENERATING ALL CHARACTER VOICES...")
print("="*60)
asyncio.run(generate_kai_voices())
asyncio.run(generate_ana_voices())
asyncio.run(generate_narrator_voices())
print("\n" + "="*60)
print("✅ ALL VOICES GENERATED!")
print("="*60)