AI-video-lifeplan-demo/backend/regenerate_missing_audio.py

99 lines
3.2 KiB
Python

#!/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()