#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Regenerate missing audio files for PPT intro video Only regenerates audio for segments that failed previously """ import os import json import sys from pathlib import Path from dotenv import load_dotenv load_dotenv() def regenerate_missing_audio(): """Regenerate audio for segments that are missing audioPath""" project_root = Path(__file__).parent.parent # Load the render props props_path = project_root / "assets/1_processed/render_props_ppt_intro_final.json" with open(props_path, encoding="utf-8") as f: props_data = json.load(f) segments = props_data["script"] # Find segments without audioPath missing_segments = [] for seg in segments: if "audioPath" not in seg or not seg["audioPath"]: missing_segments.append(seg) if not missing_segments: print("āœ“ All segments already have audio files!") return print(f"šŸ” Found {len(missing_segments)} segments without audio") # Import audio generator sys.path.insert(0, str(project_root)) from backend.audio_generator import AudioGenerator from backend.video_processor.utils import get_video_duration audio_gen = AudioGenerator() output_dir = project_root / "public" / "ppt_intro_final_audio" output_dir.mkdir(parents=True, exist_ok=True) # Regenerate audio print("\nšŸŽ™ļø Generating missing audio files...") for i, seg in enumerate(missing_segments, 1): text = seg["text"] audio_filename = f"narration_{seg['id']}.mp3" audio_path = output_dir / audio_filename print(f"\n[{i}/{len(missing_segments)}] {seg['id']}") print(f" Text: {text[:60]}...") print(f" Generating audio...") try: response = audio_gen.client.audio.speech.create( model="tts-1", voice="nova", input=text ) response.stream_to_file(str(audio_path)) actual_duration = get_video_duration(str(audio_path)) seg["duration"] = actual_duration seg["audioPath"] = f"public/ppt_intro_final_audio/{audio_filename}" print(f" āœ“ Generated: {actual_duration:.2f}s") except Exception as e: print(f" āš ļø Failed: {e}") seg["duration"] = seg.get("estimatedDuration", 10) continue # Update duration in props props_data["meta"]["duration"] = sum(s.get("duration", 0) for s in segments) # Save updated props with open(props_path, "w", encoding="utf-8") as f: json.dump(props_data, f, ensure_ascii=False, indent=2) print(f"\nāœ… Regeneration complete!") print(f" Total duration: {props_data['meta']['duration']:.1f}s") print(f"\nšŸ“¹ Ready to render:") print(f" npx remotion render MainVideo assets/2_output/ppt_intro_final_video.mp4 \\") print(f" --props=\"assets/1_processed/render_props_ppt_intro_final.json\" --concurrency=1") if __name__ == "__main__": try: regenerate_missing_audio() except Exception as e: print(f"\nāŒ Error: {e}") import traceback traceback.print_exc()