Files
novafarma/scripts/generate_audio_assets.py

268 lines
7.8 KiB
Python

#!/usr/bin/env python3
"""
AUDIO PRODUCTION AUTOMATION SCRIPT
Generates placeholder audio files and TTS voices for DolinaSmrti
Uses edge-tts for voice synthesis (FREE Microsoft Azure TTS)
"""
import os
import json
import asyncio
from pathlib import Path
# Check if edge-tts is installed
try:
import edge_tts
EDGE_TTS_AVAILABLE = True
except ImportError:
EDGE_TTS_AVAILABLE = False
print("⚠️ edge-tts not installed. Install with: pip install edge-tts")
# Audio output directory
AUDIO_DIR = Path(__file__).parent.parent / "assets" / "audio"
# Audio manifest
AUDIO_MANIFEST = {
"music": [
"main_theme.ogg",
"farm_ambient.ogg",
"combat_theme.ogg",
"raid_warning.ogg",
"town_theme.ogg",
"night_theme.ogg",
"victory_theme.ogg",
"ana_theme.ogg"
],
"ambience": [
"wind_soft.ogg",
"wind_strong.ogg",
"rain_light.ogg",
"rain_heavy.ogg",
"crickets.ogg",
"birds_chirping.ogg",
"fire_crackling.ogg",
"water_stream.ogg",
"zombie_moans_distant.ogg",
"town_bustle.ogg",
"workshop_ambient.ogg",
"forest_ambient.ogg"
],
"sfx": {
"farming": [
"dig.ogg",
"plant_seed.ogg",
"harvest.ogg",
"water_crop.ogg",
"tree_chop.ogg",
"stone_mine.ogg",
"scythe_swing.ogg",
"cow_moo.ogg"
],
"combat": [
"sword_slash.ogg",
"zombie_hit.ogg",
"zombie_death.ogg",
"player_hurt.ogg",
"raider_attack.ogg",
"shield_block.ogg",
"bow_release.ogg",
"explosion.ogg"
],
"building": [
"hammer_nail.ogg",
"door_open.ogg",
"door_close.ogg",
"chest_open.ogg",
"repair.ogg"
],
"misc": [
"footstep_grass.ogg",
"footstep_stone.ogg",
"coin_collect.ogg",
"level_up.ogg"
]
},
"ui": [
"button_click.ogg",
"button_hover.ogg",
"notification.ogg",
"quest_complete.ogg",
"error.ogg"
]
}
# NPC voice lines
NPC_VOICES = {
"kai": {
"voice": "sl-SI-PetraNeural", # Slovenian female (can use for young male)
"lines": [
"Živjo! Sem Kai.",
"Moramo najti Ano.",
"Zombiji prihajajo!",
"Hvala za pomoč.",
"To je nevarno..."
]
},
"ana": {
"voice": "sl-SI-RokNeural", # Slovenian male (soft)
"lines": [
"Kai... kje si?",
"Spomin mi uhaja...",
"Pomagaj mi, prosim.",
"Hvala ti."
]
},
"teacher": {
"voice": "sl-SI-PetraNeural",
"lines": [
"Dobrodošel v šoli!",
"Želiš se kaj naučiti?",
"Odlično delo!",
"Še ena lekcija?"
]
},
"mayor": {
"voice": "sl-SI-RokNeural",
"lines": [
"Dobrodošel, meščan!",
"Mesto potrebuje tvojo pomoč.",
"Odlično! Mesto cveti.",
"Hvala za vašo službo!"
]
}
}
async def generate_voice_line(text, voice, output_path):
"""Generate a single voice line using edge-tts"""
if not EDGE_TTS_AVAILABLE:
print(f"⚠️ Skipping {output_path.name} - edge-tts not available")
return False
try:
communicate = edge_tts.Communicate(text, voice)
await communicate.save(str(output_path))
print(f"✅ Generated: {output_path.name}")
return True
except Exception as e:
print(f"❌ Error generating {output_path.name}: {e}")
return False
async def generate_all_npc_voices():
"""Generate all NPC voice lines"""
voices_dir = AUDIO_DIR / "voices"
voices_dir.mkdir(parents=True, exist_ok=True)
total = 0
successful = 0
for npc_name, npc_data in NPC_VOICES.items():
npc_dir = voices_dir / npc_name
npc_dir.mkdir(exist_ok=True)
for i, line in enumerate(npc_data["lines"], 1):
output_file = npc_dir / f"{npc_name}_{i:02d}.mp3"
total += 1
if await generate_voice_line(line, npc_data["voice"], output_file):
successful += 1
print(f"\n🎤 Voice Generation: {successful}/{total} successful")
def create_placeholder_files():
"""Create placeholder text files for all audio"""
print("\n📝 Creating placeholder files...\n")
# Music
music_dir = AUDIO_DIR / "music"
music_dir.mkdir(parents=True, exist_ok=True)
for track in AUDIO_MANIFEST["music"]:
placeholder = music_dir / f"{track}.txt"
placeholder.write_text(f"PLACEHOLDER: {track}\nDuration: 2-3 minutes\nStyle: Dark folk/post-apocalyptic\nLoop: Yes")
print(f"📄 {track}.txt")
# Ambience
ambience_dir = AUDIO_DIR / "ambience"
ambience_dir.mkdir(parents=True, exist_ok=True)
for amb in AUDIO_MANIFEST["ambience"]:
placeholder = ambience_dir / f"{amb}.txt"
placeholder.write_text(f"PLACEHOLDER: {amb}\nDuration: 30-60 seconds\nLoop: Seamless\nSource: Freesound.org")
print(f"📄 {amb}.txt")
# SFX
for category, sounds in AUDIO_MANIFEST["sfx"].items():
sfx_dir = AUDIO_DIR / "sfx" / category
sfx_dir.mkdir(parents=True, exist_ok=True)
for sfx in sounds:
placeholder = sfx_dir / f"{sfx}.txt"
placeholder.write_text(f"PLACEHOLDER: {sfx}\nCategory: {category}\nDuration: 0.1-2 seconds\nFormat: OGG Vorbis")
print(f"📄 {sfx}.txt")
# UI
ui_dir = AUDIO_DIR / "ui"
ui_dir.mkdir(parents=True, exist_ok=True)
for ui_sound in AUDIO_MANIFEST["ui"]:
placeholder = ui_dir / f"{ui_sound}.txt"
placeholder.write_text(f"PLACEHOLDER: {ui_sound}\nDuration: 0.1-0.5 seconds\nFormat: OGG Vorbis\nCrisp, clean sound")
print(f"📄 {ui_sound}.txt")
print(f"\n✅ Created {61} placeholder files!")
def generate_audio_manifest_json():
"""Generate audio_manifest.json for loading"""
manifest_path = AUDIO_DIR / "audio_manifest.json"
manifest_data = {
"version": "1.0",
"total_files": 61,
"categories": {
"music": len(AUDIO_MANIFEST["music"]),
"ambience": len(AUDIO_MANIFEST["ambience"]),
"sfx": sum(len(sounds) for sounds in AUDIO_MANIFEST["sfx"].values()),
"ui": len(AUDIO_MANIFEST["ui"]),
"voices": sum(len(npc["lines"]) for npc in NPC_VOICES.values())
},
"files": AUDIO_MANIFEST
}
manifest_path.write_text(json.dumps(manifest_data, indent=2))
print(f"\n✅ Generated audio_manifest.json")
async def main():
"""Main execution"""
print("🎵 DolinaSmrti - Audio Production Automation")
print("=" * 50)
# Create directories
AUDIO_DIR.mkdir(parents=True, exist_ok=True)
# Step 1: Create placeholder files
create_placeholder_files()
# Step 2: Generate manifest
generate_audio_manifest_json()
# Step 3: Generate NPC voices (if edge-tts available)
if EDGE_TTS_AVAILABLE:
print("\n🎤 Generating NPC voice lines...")
await generate_all_npc_voices()
else:
print("\n⚠️ Install edge-tts to generate NPC voices:")
print(" pip install edge-tts")
print("\n" + "=" * 50)
print("✅ AUDIO PRODUCTION SETUP COMPLETE!")
print("\nNext steps:")
print("1. Install edge-tts: pip install edge-tts")
print("2. Run this script again to generate voices")
print("3. Source music/SFX from Freesound.org or AI music generators")
print("4. Convert all files to OGG Vorbis format")
if __name__ == "__main__":
asyncio.run(main())