import os import subprocess from moviepy.video.io.VideoFileClip import VideoFileClip from moviepy.audio.io.AudioFileClip import AudioFileClip from moviepy.audio.AudioClip import CompositeAudioClip from moviepy.config import change_settings # --- Robust FFmpeg Configuration --- BASE_DIR = os.path.dirname(os.path.abspath(__file__)) ff_local = os.path.join(BASE_DIR, "ffmpeg.exe") if os.path.exists(ff_local): change_settings({"FFMPEG_BINARY": ff_local}) from moviepy.audio.fx.volumex import volumex def finalize_video_pro(video_path, output_path, segments_info): """ Surgical Audio Replacement Engine: Keeps original interviewer voice, replaces candidate segments with Elite AI. """ video = VideoFileClip(video_path) original_audio = video.audio # 1. Create SRT & AI Audio Clips srt_content = "" ai_clips = [] # We will "duck" the original audio during AI segments # For simplicity in this demo, we'll use a CompositeAudioClip with the original as base for idx, (audio_path, start_time, text) in enumerate(segments_info): if os.path.exists(audio_path) and text.strip(): a_clip = AudioFileClip(audio_path).set_start(start_time) ai_clips.append(a_clip) # Format SRT def to_srt_time(seconds): hrs = int(seconds // 3600); mins = int((seconds % 3600) // 60); secs = int(seconds % 60) ms = int((seconds - int(seconds)) * 1000) return f"{hrs:02}:{mins:02}:{secs:02},{ms:03}" srt_content += f"{idx+1}\n{to_srt_time(start_time)} --> {to_srt_time(start_time + a_clip.duration)}\n{text}\n\n" with open("temp.srt", "w", encoding="utf-8") as f: f.write(srt_content) # 2. Master Audio Mix (Original + AI Overlays) # We lower original volume slightly using the direct FX function final_audio = CompositeAudioClip([volumex(original_audio, 0.3)] + ai_clips) temp_video = "temp_render.mp4" video.set_audio(final_audio).write_videofile(temp_video, codec="libx264", audio_codec="aac") # 3. Burn-in Subtitles ff_cmd = ff_local if os.path.exists(ff_local) else "ffmpeg" # Double-escaping for Windows FFmpeg path requirements srt_path = os.path.abspath("temp.srt").replace("\\", "/").replace(":", "\\:") subprocess.run([ ff_cmd, "-i", temp_video, "-vf", f"subtitles='{srt_path}':force_style='FontSize=26,PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,BorderStyle=1,Outline=2,Shadow=1,MarginV=35,Alignment=2'", "-c:a", "copy", output_path, "-y" ]) # Cleanup video.close() for c in ai_clips: c.close() if os.path.exists(temp_video): os.remove(temp_video) if os.path.exists("temp.srt"): os.remove("temp.srt")