Session: 11hr marathon (Jan 8, 2026) Assets: 52 animation frames total Progress: 36% to 54% Kai: 20 frames (idle 4, walk 6, dig 5, swing 5) Ana: 10 frames (idle 4, walk 6) Gronk: 10 frames (idle 4, walk 6) Susi: 12 frames (idle 4, run 6, bark 2) Demo Status: 157/292 assets (54%) Remaining: 135 assets Files updated: - TASK_TRACKER.md - PRODUCTION_CHECKLIST.md - 64 new PNG assets - Susi reference updated
144 lines
4.5 KiB
Python
144 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Generate Quest Voiceover Audio
|
|
|
|
Generates TTS audio files for all quest dialogue using Edge TTS.
|
|
Supports Slovenian language with natural female voice (Petra).
|
|
|
|
Usage:
|
|
python generate_quest_voiceovers.py
|
|
|
|
Output:
|
|
assets/audio/quests/[quest_id]_start.mp3
|
|
assets/audio/quests/[quest_id]_progress.mp3
|
|
assets/audio/quests/[quest_id]_complete.mp3
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import asyncio
|
|
import edge_tts
|
|
|
|
# Quest dialogue from QuestDataLoader
|
|
QUEST_DIALOGUES = {
|
|
# Main Story Quests
|
|
"q001_kje_sem": {
|
|
"start": "...au glava... kje sm? Čak... kdo SM jaz sploh?!",
|
|
"complete": "Včeri sm bla tam, zdej pa tuki... MORŠ NEC NAJT!"
|
|
},
|
|
"q002_prvi_koraki": {
|
|
"start": "Hm... mam tools pa zemljo... Probam narit farmo?",
|
|
"progress": "Nice! Raste!",
|
|
"complete": "DAAAAJ! Prva plants! Kul!"
|
|
},
|
|
"q003_glas_v_glavi": {
|
|
"start": "...Kaj je to? Neki slišim... Dekle? Govori slovensko.. mam občutek da jo POZNAM?!",
|
|
"onVoice": "Kai, a me slišiš? Ne skrbi zame... najd se...",
|
|
"complete": "TA FOTKA! To je... ANA?! SESTRA! Moja SESTRA! ...pomnim se! ANA JE ŽIVA!"
|
|
},
|
|
|
|
# Collection Quests
|
|
"q010_80_crops": {
|
|
"start": "80 različnih crops? Challenge accepted!",
|
|
"progress": "Še {remaining} da konč!",
|
|
"complete": "DAAAAAJ 80/80! MASTER FARMER STATUS UNLOCKED!"
|
|
},
|
|
"q011_tree_planter": {
|
|
"start": "11 vrst dreves... začenjam z oak!",
|
|
"complete": "DONE! Ves forest je moj!"
|
|
},
|
|
"q020_creature_catalog": {
|
|
"start": "HOLY SHIT 99 creatures?! OK gremo!",
|
|
"progress": "{current}/99... keep going!",
|
|
"complete": "COMPLETE CREATURE CATALOG! SICK!"
|
|
},
|
|
|
|
# Social Quests
|
|
"q080_166_friends": {
|
|
"start": "166 ljudi? Noben me ne pozna... but I'll try!",
|
|
"progress": "{current} friends... getting there!",
|
|
"complete": "166/166! EVERYONE KNOWS ME NOW!"
|
|
},
|
|
|
|
# Building Quests
|
|
"q040_gothic_empire": {
|
|
"start": "6 buildings... let's gooo!",
|
|
"complete": "FARM EMPIRE COMPLETE!"
|
|
},
|
|
|
|
# Biome Quests
|
|
"q050_underwater_secrets": {
|
|
"start": "Voda! Water physics so sick! Dreads plavajo! 😂",
|
|
"complete": "Podvodni treasures found! DOPE!"
|
|
},
|
|
"q060_baba_yaga": {
|
|
"start": "Witch Forest... creepy af",
|
|
"onBoss": "BABA YAGA?! OH SHIT!",
|
|
"complete": "DEFEATED! Broomstick je moj! LETIM!"
|
|
},
|
|
"q070_jurassic_farm": {
|
|
"start": "DINOZAVRI?! WHAT?!",
|
|
"complete": "TAMED T-REX! BEST DAY EVER!"
|
|
}
|
|
}
|
|
|
|
# Voice settings
|
|
VOICE_SLOVENIAN_FEMALE = "sl-SI-PetraNeural" # Petra - Slovenian female voice
|
|
OUTPUT_DIR = "assets/audio/quests"
|
|
|
|
async def generate_voiceover(text, output_path, voice=VOICE_SLOVENIAN_FEMALE):
|
|
"""Generate single voiceover file"""
|
|
# Remove emojis and special characters for TTS
|
|
clean_text = text.replace('😂', '').replace('...', ' ').strip()
|
|
|
|
print(f"Generating: {output_path}")
|
|
print(f" Text: {clean_text[:50]}...")
|
|
|
|
communicate = edge_tts.Communicate(clean_text, voice)
|
|
await communicate.save(output_path)
|
|
|
|
print(f" ✅ Saved!")
|
|
|
|
async def generate_all_quest_voiceovers():
|
|
"""Generate all quest voiceovers"""
|
|
|
|
# Create output directory
|
|
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
|
|
|
total_files = 0
|
|
|
|
for quest_id, dialogues in QUEST_DIALOGUES.items():
|
|
print(f"\n🎙️ Quest: {quest_id}")
|
|
|
|
for event_type, text in dialogues.items():
|
|
# Skip progress dialogue with placeholders
|
|
if '{remaining}' in text or '{current}' in text:
|
|
print(f" ⏭️ Skipping {event_type} (has placeholder)")
|
|
continue
|
|
|
|
# Generate filename
|
|
filename = f"{quest_id}_{event_type}.mp3"
|
|
output_path = os.path.join(OUTPUT_DIR, filename)
|
|
|
|
# Generate voiceover
|
|
await generate_voiceover(text, output_path)
|
|
total_files += 1
|
|
|
|
print(f"\n✅ COMPLETE! Generated {total_files} voiceover files!")
|
|
print(f"📁 Location: {OUTPUT_DIR}/")
|
|
|
|
def main():
|
|
"""Main entry point"""
|
|
print("=" * 60)
|
|
print("QUEST VOICEOVER GENERATOR")
|
|
print("=" * 60)
|
|
print(f"Voice: {VOICE_SLOVENIAN_FEMALE}")
|
|
print(f"Output: {OUTPUT_DIR}/")
|
|
print("=" * 60)
|
|
|
|
# Run async generation
|
|
asyncio.run(generate_all_quest_voiceovers())
|
|
|
|
if __name__ == "__main__":
|
|
main()
|