74 lines
2.6 KiB
Python
74 lines
2.6 KiB
Python
import json
|
|
import sys
|
|
import os
|
|
from pathlib import Path
|
|
from dotenv import load_dotenv
|
|
|
|
# Load environment variables from .env file
|
|
load_dotenv()
|
|
|
|
# Add project root to sys.path to allow importing backend modules
|
|
project_root = Path(__file__).parent.parent
|
|
sys.path.append(str(project_root))
|
|
|
|
from backend.audio_generator import generate_audio_for_script
|
|
|
|
def rebuild_audio_from_props():
|
|
"""
|
|
Reads assets/1_processed/render_props.json, generates new audio files
|
|
for the narration text, and updates the durations and paths.
|
|
"""
|
|
props_path = project_root / "assets" / "1_processed" / "render_props.json"
|
|
|
|
if not props_path.exists():
|
|
print(f"❌ Error: {props_path} not found.")
|
|
return
|
|
|
|
print(f"📖 Reading script from {props_path}...")
|
|
with open(props_path, "r", encoding="utf-8") as f:
|
|
props = json.load(f)
|
|
|
|
# RE-INDEX segments first
|
|
print("🔢 Re-indexing script segments and fixing paths...")
|
|
for i, segment in enumerate(props["script"]):
|
|
new_id = i + 1
|
|
segment["id"] = new_id
|
|
|
|
# Determine if we should keep existing audio path
|
|
current_path = segment.get("audioPath", "")
|
|
is_original_clip = "dialogue_clip" in current_path
|
|
|
|
if segment.get("visualType") == "video":
|
|
if "audioPath" in segment:
|
|
del segment["audioPath"]
|
|
elif is_original_clip:
|
|
# Keep the dialogue_clip path as is
|
|
print(f" ⏭️ Segment {new_id}: Keeping original audio path {current_path}")
|
|
pass
|
|
else:
|
|
# Assign standard naming for AI generated segments
|
|
segment["audioPath"] = f"public/segment_{new_id:03d}.mp3"
|
|
|
|
script_data = {"segments": props["script"]}
|
|
|
|
# Generate new audio files (outputs to public/ folder)
|
|
print("🎙️ Generating new audio files...")
|
|
updated_script_data = generate_audio_for_script(script_data, voice="fable")
|
|
# voice options: "alloy", "echo", "fable", "onyx", "nova", "shimmer"
|
|
|
|
# Update the script in our props object
|
|
props["script"] = updated_script_data["segments"]
|
|
|
|
# Recalculate total duration if needed (Remotion uses segment durations)
|
|
total_duration = sum(seg.get("duration", 0) for seg in props["script"])
|
|
print(f"⏱️ New total duration: {total_duration:.2f} seconds")
|
|
|
|
# Save updated render_props.json
|
|
with open(props_path, "w", encoding="utf-8") as f:
|
|
json.dump(props, f, ensure_ascii=False, indent=2)
|
|
|
|
print(f"✅ Successfully updated {props_path} with new audio and durations.")
|
|
|
|
if __name__ == "__main__":
|
|
rebuild_audio_from_props()
|