#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
=============================================================================
KIEU STORY AI CINEMA — PROLOGUE INTRO 2-SHOT PRODUCTION PIPELINE (FLOWKIT)
=============================================================================
Sản xuất 2 Shot Intro mở đầu phim theo Chuẩn Điện ảnh FlowKit & EBU R128:
- Shot 1 (ep01_intro_shot01, 10s): Dải lụa thanh xuân lướt qua mặt hồ sương sớm.
- Shot 2 (ep01_intro_shot02, 10s): Dải lụa xoáy khởi nguyên & Khai mở biểu trưng "Thập Ngũ Niên".
- Head-Tail Chaining: Frame 239 của Shot 1 kế thừa chính xác 100% làm Start Frame của Shot 2.
- Kiến trúc Âm thanh Điện ảnh Mới (Đồng điệu 100% với Prologue):
    * BỎ HOÀN TOÀN tiếng gảy đàn tì bà / pipa / guzheng giục giã, thừa thãi.
    * Stem 1 (Flowing Water): Tiếng nước chảy róc rách, bọt nước li ti, sóng vỗ lăn tăn, giọt nước rơi thanh khiết.
    * Stem 2 (Atmospheric Bed): Thảm âm thanh cổ phong ngân dài (D minor / F pentatonic strings pad & meditative drone),
      trầm lắng, sâu thẳm, cao trào trang nghiêm lúc hiện tựa đề và thoái trào êm ả về cuối để dẫn vào Prologue.
    * Stem 3 (Foley / Shimmer): Tiếng tà lụa mềm mại vút trong gió sớm và ánh bụi vàng lấp lánh (celestial sparkle).
    * Stem 4 (Mastering): Chuẩn hóa EBU R128 (-14.0 LUFS, -1.0 dBTP, Stereo 48kHz, AAC 192k).
=============================================================================
"""

import os
import sys
import math
import wave
import struct
import random
import shutil
import subprocess
from pathlib import Path
import numpy as np

# Khởi tạo UTF-8 cho Windows Console
if sys.platform == "win32":
    try:
        sys.stdout.reconfigure(encoding="utf-8")
        sys.stderr.reconfigure(encoding="utf-8")
    except Exception:
        pass

BASE_DIR = Path("c:/Projects/KieuStory")
ASSETS_DIR = BASE_DIR / "04_Assets"
VIDEOS_DIR = ASSETS_DIR / "videos"
AUDIO_DIR = ASSETS_DIR / "audio"
KEYFRAMES_DIR = ASSETS_DIR / "keyframes"
CRITIC_DIR = ASSETS_DIR / "critic_queue"
EXPORTS_DIR = BASE_DIR / "06_Exports"

VIDEOS_DIR.mkdir(parents=True, exist_ok=True)
AUDIO_DIR.mkdir(parents=True, exist_ok=True)
CRITIC_DIR.mkdir(parents=True, exist_ok=True)
EXPORTS_DIR.mkdir(parents=True, exist_ok=True)

DEFAULT_FFMPEG_PATHS = [
    r"C:\Users\Admin\AppData\Local\Microsoft\WinGet\Packages\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\ffmpeg-9.0.2-full_build\bin\ffmpeg.exe",
    r"C:\Users\Admin\AppData\Local\Microsoft\WindowsApps\ffmpeg.exe",
    r"ffmpeg"
]

def get_ffmpeg():
    for p in DEFAULT_FFMPEG_PATHS:
        if os.path.exists(p) or p == "ffmpeg":
            try:
                res = subprocess.run([p, "-version"], capture_output=True, text=True)
                if res.returncode == 0:
                    return p
            except Exception:
                continue
    return "ffmpeg"


def generate_flowing_water_stream(output_path: str, duration_sec: float = 20.0, sample_rate: int = 48000) -> bool:
    """
    Tổng hợp Stem 1: Tiếng Nước Chảy & Sóng Hồ Róc Rách Tự Nhiên (20.0s, Stereo 48kHz).
    Mô phỏng chân thực:
    1. Hàng ngàn bọt nước vi mô (micro-bubbles resonance) tạo tiếng róc rách trong vắt.
    2. Gợn sóng lăn tăn và dao động vỗ bờ êm ái (water lapping swells, LFO 0.22Hz).
    3. Giọt nước thánh thót rơi khi cánh hoa đào/hoa lê chạm mặt nước.
    4. Gió sớm lướt nhẹ qua rặng liễu.
    """
    out_file = Path(output_path)
    out_file.parent.mkdir(parents=True, exist_ok=True)

    print(f"[*] Đang tổng hợp Stem 1: Flowing Water & Lake Stream ({duration_sec}s, {sample_rate}Hz Stereo)...")

    total_samples = int(duration_sec * sample_rate)
    t = np.linspace(0, duration_sec, total_samples, endpoint=False)

    np.random.seed(18610)
    random.seed(18610)

    # 1. Base water turbulence (Brownian noise)
    white = np.random.normal(0, 1, total_samples)
    brownian = np.cumsum(white)
    brownian = brownian - np.mean(brownian)
    brownian = brownian / np.max(np.abs(brownian))

    # 2. Sinh 4000 micro-bubble grains mô phỏng dòng nước róc rách trong vắt
    num_bubbles = 4200
    bubble_audio_l = np.zeros(total_samples)
    bubble_audio_r = np.zeros(total_samples)

    bubble_times = np.random.uniform(0.05, duration_sec - 0.1, num_bubbles)
    bubble_freqs = np.random.uniform(450, 2600, num_bubbles)
    bubble_durs = np.random.uniform(0.010, 0.035, num_bubbles)
    bubble_pans = np.random.uniform(0.15, 0.85, num_bubbles)
    bubble_amps = np.random.uniform(0.015, 0.060, num_bubbles)

    for i in range(num_bubbles):
        t_start = bubble_times[i]
        dur = bubble_durs[i]
        f0 = bubble_freqs[i]
        amp = bubble_amps[i]
        pan = bubble_pans[i]

        idx_start = int(t_start * sample_rate)
        n_samples = int(dur * sample_rate)
        if idx_start + n_samples >= total_samples:
            continue

        t_b = np.linspace(0, dur, n_samples, endpoint=False)
        # Tần số bọt nước tăng nhẹ khi bọt vỡ (Minnaert pitch rise)
        freq_curve = f0 * (1.0 + 0.18 * (t_b / dur))
        env = np.exp(-t_b * (55.0 / dur + 15.0))
        wave_b = amp * np.sin(2.0 * np.pi * freq_curve * t_b) * env

        bubble_audio_l[idx_start:idx_start+n_samples] += wave_b * (1.0 - pan)
        bubble_audio_r[idx_start:idx_start+n_samples] += wave_b * pan

    # 3. Điều biến nhịp thở sóng nước (Water ripple swells)
    swell_mod = 0.72 + 0.28 * np.sin(2.0 * np.pi * 0.20 * t + 0.5)
    water_l = (bubble_audio_l * 1.6 + brownian * 0.09) * swell_mod
    water_r = (bubble_audio_r * 1.6 + brownian * 0.09) * swell_mod

    # 4. Giọt nước thánh thót chạm mặt hồ (tại 2.4s, 5.8s, 9.2s, 13.5s, 17.6s)
    for t_drop in [2.4, 5.8, 9.2, 13.5, 17.6]:
        idx = int(t_drop * sample_rate)
        dur_d = 0.09
        n_d = int(dur_d * sample_rate)
        if idx + n_d < total_samples:
            t_d = np.linspace(0, dur_d, n_d, endpoint=False)
            f_drop = 1580.0
            wave_drop = 0.075 * np.sin(2.0 * np.pi * f_drop * (1.0 + 0.35 * (t_d / dur_d)) * t_d) * np.exp(-t_d * 42.0)
            water_l[idx:idx+n_d] += wave_drop * 0.65
            water_r[idx:idx+n_d] += wave_drop * 0.35

    # 5. Gió thoảng qua rặng liễu mềm mại
    pink_filter = np.random.normal(0, 0.03, total_samples)
    breeze_l = pink_filter * (0.6 + 0.4 * np.sin(2.0 * np.pi * 0.12 * t))
    breeze_r = pink_filter * (0.6 + 0.4 * np.cos(2.0 * np.pi * 0.12 * t))
    water_l += breeze_l
    water_r += breeze_r

    # Chuẩn hóa
    peak = max(np.max(np.abs(water_l)), np.max(np.abs(water_r)))
    if peak > 0:
        water_l = (water_l / peak) * 0.85
        water_r = (water_r / peak) * 0.85

    # Ghi file WAV 16-bit Stereo 48kHz
    with wave.open(str(out_file), "wb") as wf:
        wf.setnchannels(2)
        wf.setsampwidth(2)
        wf.setframerate(sample_rate)
        interleaved = np.empty((total_samples * 2,), dtype=np.int16)
        interleaved[0::2] = np.clip(water_l * 32767.0, -32768, 32767).astype(np.int16)
        interleaved[1::2] = np.clip(water_r * 32767.0, -32768, 32767).astype(np.int16)
        wf.writeframes(interleaved.tobytes())

    print(f"[✓] Đã tạo thành công Stem 1 Flowing Water: {out_file} ({out_file.stat().st_size} bytes)")
    return True


def generate_cinematic_atmospheric_bed(output_path: str, duration_sec: float = 20.0, sample_rate: int = 48000) -> bool:
    """
    Tổng hợp Stem 2: Thảm âm thanh cổ phong Á Đông hoài niệm & sâu lắng (20.0s, Stereo 48kHz).
    HOÀN TOÀN KHÔNG CÓ TIẾNG ĐÀN TÌ BÀ GẢY DÂY.
    - Cung điệu D minor / F pentatonic (D - F - G - A - C) thanh tịnh, hoài niệm, thuần chất điện ảnh.
    - Dàn dây / pad ambient ngân vang ấm áp, bồi đắp không gian kỳ ảo cho dải lụa bay.
    - Cấu trúc trường đoạn khớp hoàn hảo với Prologue:
      * 0s - 3s: Êm đềm mở ra từ tĩnh lặng, nhường chỗ cho tiếng nước chảy và tiếng gió.
      * 3s - 12s: Pad trầm bổng, thiền định đưa người xem vào không gian hồ liễu kinh kỳ.
      * 12s - 16s: Đỉnh điểm cao trào trang nghiêm lúc tựa đề 'Thập Ngũ Niên' bùng sáng hoàng kim.
      * 16s - 20s: Dịu dần về vùng thanh tịnh (smooth decrescendo), kết nối tự nhiên và liền mạch
        vào tiếng ngâm Kiều mộc mạc và âm cảnh hoàng hôn 1980s của Prologue.
    """
    out_file = Path(output_path)
    out_file.parent.mkdir(parents=True, exist_ok=True)

    print(f"[*] Đang tổng hợp Stem 2: Cinematic Atmospheric Bed ({duration_sec}s, {sample_rate}Hz Stereo)...")

    total_samples = int(duration_sec * sample_rate)
    t = np.linspace(0, duration_sec, total_samples, endpoint=False)

    np.random.seed(9999)

    # Các tần số ngũ cung cổ phong D-F-G-A-C:
    # D2=73.42, A2=110.00, D3=146.83, F3=174.61, G3=196.00, A3=220.00, C4=261.63, D4=293.66
    freqs = [73.42, 110.00, 146.83, 174.61, 196.00, 220.00, 261.63, 293.66]
    weights = [0.20, 0.17, 0.15, 0.13, 0.10, 0.10, 0.08, 0.07]

    pad_l = np.zeros(total_samples)
    pad_r = np.zeros(total_samples)

    # Đường bao cảm xúc điện ảnh (Cinematic Envelope)
    env = np.ones(total_samples)
    for i in range(total_samples):
        ti = t[i]
        if ti < 3.0:
            # Khởi đầu rất êm dịu, tăng dần từ 0
            env[i] = (ti / 3.0) ** 1.6 * 0.45
        elif ti < 11.5:
            # Bình nguyên êm ả, tôn vinh tiếng nước
            env[i] = 0.45 + 0.12 * math.sin((ti - 3.0) / 8.5 * math.pi * 0.5)
        elif ti < 14.5:
            # Dâng lên đỉnh điểm lúc chữ Thập Ngũ Niên bùng nổ hào quang
            p = (ti - 11.5) / 3.0
            env[i] = 0.57 + 0.43 * (math.sin(p * math.pi * 0.5) ** 2)
        elif ti < 16.8:
            # Ngân vang oai nghiêm
            p = (ti - 14.5) / 2.3
            env[i] = 1.0 - 0.25 * p
        else:
            # Hạ dần êm ái về 0.12 để dẫn dắt hoàn hảo vào Prologue
            p = (ti - 16.8) / 3.2
            env[i] = 0.75 * ((1.0 - p) ** 1.5) + 0.10

    # Hòa quyện các hòa âm ngũ cung với chorus và vibrato tự nhiên
    for f, w in zip(freqs, weights):
        detune = 0.0016
        vib = 0.0018 * np.sin(2.0 * np.pi * 4.0 * t)
        phase_l = np.random.uniform(0, 2 * np.pi)
        phase_r = np.random.uniform(0, 2 * np.pi)

        tone_l = np.sin(2.0 * np.pi * f * (1.0 - detune + vib) * t + phase_l)
        tone_r = np.sin(2.0 * np.pi * f * (1.0 + detune + vib) * t + phase_r)

        # Bổ sung harmonic thứ hai dịu nhẹ
        tone_l += 0.25 * np.sin(4.0 * np.pi * f * t + phase_l)
        tone_r += 0.25 * np.sin(4.0 * np.pi * f * t + phase_r)

        pad_l += w * tone_l
        pad_r += w * tone_r

    # Dải sub-bass ấm áp (D1 = 36.71 Hz)
    pad_l += 0.14 * np.sin(2.0 * np.pi * 36.71 * t)
    pad_r += 0.14 * np.sin(2.0 * np.pi * 36.71 * t)

    pad_l = pad_l * env
    pad_r = pad_r * env

    # Chuẩn hóa
    peak = max(np.max(np.abs(pad_l)), np.max(np.abs(pad_r)))
    if peak > 0:
        pad_l = (pad_l / peak) * 0.75
        pad_r = (pad_r / peak) * 0.75

    with wave.open(str(out_file), "wb") as wf:
        wf.setnchannels(2)
        wf.setsampwidth(2)
        wf.setframerate(sample_rate)
        interleaved = np.empty((total_samples * 2,), dtype=np.int16)
        interleaved[0::2] = np.clip(pad_l * 32767.0, -32768, 32767).astype(np.int16)
        interleaved[1::2] = np.clip(pad_r * 32767.0, -32768, 32767).astype(np.int16)
        wf.writeframes(interleaved.tobytes())

    print(f"[✓] Đã tạo thành công Stem 2 Atmospheric Bed: {out_file} ({out_file.stat().st_size} bytes)")
    return True


def create_enhanced_foley_track(
    raw_audio_path: str,
    output_foley_path: str,
    duration_sec: float = 20.0
) -> bool:
    """
    Stem 3: Foley lụa bay và hiệu ứng ánh sáng hoàng kim:
    - Tiếng lụa mềm mại vút nhẹ trong không gian.
    - Hiệu ứng bụi vàng ngân vang (celestial shimmer) tại 13.8s - 17.5s lúc tựa đề bùng sáng.
    """
    ffmpeg_exe = get_ffmpeg()
    out_file = Path(output_foley_path)
    out_file.parent.mkdir(parents=True, exist_ok=True)

    print(f"[*] Đang nâng cấp Stem 3 Foley & Celestial Shimmer...")

    filter_complex = (
        "[0:a]aformat=channel_layouts=stereo,aresample=48000,"
        "highpass=f=70,lowpass=f=11000,volume=1.2[foley_clean];"
        # Golden celestial chime shimmer synthesizer
        "aevalsrc='if(between(t, 13.8, 17.5), "
        "0.020*sin(2*PI*1760*t)*exp(-2.2*(t-13.8)) + "
        "0.016*sin(2*PI*2637*t)*exp(-1.8*(t-14.2)) + "
        "0.012*sin(2*PI*3520*t)*exp(-1.4*(t-14.6)) + "
        "0.009*sin(2*PI*4186*t)*exp(-1.0*(t-15.0)), 0)':s=48000:d=20[shimmer_synth];"
        "[shimmer_synth]aformat=channel_layouts=stereo,aphaser=in_gain=0.6:out_gain=0.8:delay=3.0:decay=0.4:speed=0.5:type=t[shimmer_fx];"
        "[foley_clean][shimmer_fx]amix=inputs=2:duration=first:dropout_transition=2[foley_out]"
    )

    cmd = [
        ffmpeg_exe, "-y",
        "-i", raw_audio_path,
        "-filter_complex", filter_complex,
        "-map", "[foley_out]",
        "-c:a", "pcm_s16le",
        "-t", str(duration_sec),
        str(out_file)
    ]
    res = subprocess.run(cmd, capture_output=True, text=True)
    if res.returncode == 0:
        print(f"[✓] Đã tạo thành công Stem 3 Foley Track: {out_file}")
        return True
    else:
        print(f"[!] Lỗi tạo Foley track: {res.stderr}")
        return False


def produce_cinema_intro_master():
    """
    Sản xuất toàn diện 2 Shot Intro và Master hoàn thiện với thiết kế âm thanh mới:
    1. Trích xuất Foley gốc.
    2. Tổng hợp Stem 1 (Tiếng Nước Chảy Róc Rách & Sóng Hồ).
    3. Tổng hợp Stem 2 (Nhạc Nền Cổ Phong Khớp Prologue - Zero Tỳ Bà).
    4. Tổng hợp Stem 3 (Foley Lụa & Celestial Shimmer).
    5. Hòa âm 3 Stems và chuẩn hóa EBU R128 (-14.0 LUFS).
    6. Tạo Shot 1 Master, Shot 2 Master và Intro Grand Master 20s.
    7. Ghép thử nối liền Intro + Prologue thành bản 60s để đối chứng độ ăn khớp.
    """
    ffmpeg_exe = get_ffmpeg()
    source_video = VIDEOS_DIR / "thap_ngu_nien_intro_complete_20s.mp4"
    if not source_video.exists():
        print(f"[!] Không tìm thấy file gốc: {source_video}")
        return False

    print("=" * 80)
    print("🎬 KIEU STORY AI CINEMA — PROLOGUE INTRO AUDIO RE-ENGINEERING")
    print("   Thiết kế: Tiếng Nước Chảy Tự Nhiên & Nhạc Nền Khớp Prologue (Zero Tỳ Bà)")
    print("=" * 80)

    # 1. Trích xuất Foley thô từ video
    raw_foley = CRITIC_DIR / "intro_raw_foley_20s.wav"
    subprocess.run([
        ffmpeg_exe, "-y",
        "-i", str(source_video),
        "-vn", "-c:a", "pcm_s16le",
        str(raw_foley)
    ], check=True)

    # 2. Tạo Stem 1 Flowing Water (Tiếng Nước Chảy & Sóng Hồ)
    water_path = AUDIO_DIR / "intro_flowing_water_20s.wav"
    generate_flowing_water_stream(str(water_path), duration_sec=20.0)

    # 3. Tạo Stem 2 Atmospheric Bed (Nhạc Nền Cổ Phong Khớp Prologue - Hoàn toàn không đàn tì bà)
    pad_path = AUDIO_DIR / "intro_atmospheric_bed_20s.wav"
    generate_cinematic_atmospheric_bed(str(pad_path), duration_sec=20.0)

    # 4. Tạo Stem 3 Foley Lụa & Shimmer
    foley_enhanced = AUDIO_DIR / "intro_foley_silk_and_title_shimmer_20s.wav"
    create_enhanced_foley_track(str(raw_foley), str(foley_enhanced), duration_sec=20.0)

    # 5. Phối âm 3 Stems & Chuẩn hóa EBU R128 (-14.0 LUFS)
    # Tỷ lệ: Tiếng Nước Chảy chủ đạo (vol 0.85) + Thảm Atmospheric (vol 0.38) + Foley Lụa (vol 0.65)
    print("\n🎛️ Đang hòa âm 3 Stems (Tiếng Nước, Nhạc Nền Khớp Prologue, Foley) và chuẩn hóa EBU R128 (-14.0 LUFS)...")
    master_audio_20s = CRITIC_DIR / "intro_master_audio_20s.wav"

    filter_mix = (
        "[0:a]volume=0.85[water_sub];"
        "[1:a]volume=0.38[pad_sub];"
        "[2:a]volume=0.65[fol_sub];"
        "[water_sub][pad_sub][fol_sub]amix=inputs=3:duration=first:dropout_transition=2[mix_raw];"
        "[mix_raw]loudnorm=I=-14.0:TP=-1.0:LRA=8.0:linear=true[mix_norm]"
    )
    subprocess.run([
        ffmpeg_exe, "-y",
        "-i", str(water_path),
        "-i", str(pad_path),
        "-i", str(foley_enhanced),
        "-filter_complex", filter_mix,
        "-map", "[mix_norm]",
        "-c:a", "pcm_s16le", "-ar", "48000",
        str(master_audio_20s)
    ], check=True)
    print(f"[✓] Đã tạo Master Audio 20s chuẩn EBU R128: {master_audio_20s}")

    # 6. Ghép Video & Audio Master cho Shot 1 (0-10s) và Shot 2 (10-20s)
    shot01_video_out = VIDEOS_DIR / "ep01_intro_shot01_10s_master.mp4"
    shot02_video_out = VIDEOS_DIR / "ep01_intro_shot02_10s_master.mp4"

    print("\n🎬 Đang ghép Video và Audio Master cho Shot 01 (10s)...")
    subprocess.run([
        ffmpeg_exe, "-y",
        "-ss", "0.0", "-t", "10.0", "-i", str(source_video),
        "-ss", "0.0", "-t", "10.0", "-i", str(master_audio_20s),
        "-map", "0:v:0", "-map", "1:a:0",
        "-c:v", "libx264", "-crf", "18", "-preset", "slow", "-pix_fmt", "yuv420p",
        "-c:a", "aac", "-b:a", "192k", "-ar", "48000",
        "-t", "10.0",
        str(shot01_video_out)
    ], check=True)
    print(f"[✓] Shot 01 Master: {shot01_video_out}")

    print("\n🎬 Đang ghép Video và Audio Master cho Shot 02 (10s)...")
    subprocess.run([
        ffmpeg_exe, "-y",
        "-ss", "10.0", "-t", "10.0", "-i", str(source_video),
        "-ss", "10.0", "-t", "10.0", "-i", str(master_audio_20s),
        "-map", "0:v:0", "-map", "1:a:0",
        "-c:v", "libx264", "-crf", "18", "-preset", "slow", "-pix_fmt", "yuv420p",
        "-c:a", "aac", "-b:a", "192k", "-ar", "48000",
        "-t", "10.0",
        str(shot02_video_out)
    ], check=True)
    print(f"[✓] Shot 02 Master: {shot02_video_out}")

    # 7. Ghép nối Master 20s Intro hoàn thiện
    intro_master_export = EXPORTS_DIR / "thap_ngu_nien_intro_master_20s.mp4"
    intro_master_assets = VIDEOS_DIR / "thap_ngu_nien_intro_complete_20s.mp4"

    print("\n🎬 Đang ghép nối liên tục 2 Shot thành Intro Grand Master (20s)...")
    subprocess.run([
        ffmpeg_exe, "-y",
        "-i", str(shot01_video_out),
        "-i", str(shot02_video_out),
        "-filter_complex", "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[v][a]",
        "-map", "[v]", "-map", "[a]",
        "-c:v", "libx264", "-crf", "18", "-preset", "slow", "-pix_fmt", "yuv420p",
        "-c:a", "aac", "-b:a", "192k", "-ar", "48000",
        str(intro_master_export)
    ], check=True)
    shutil.copy2(intro_master_export, intro_master_assets)
    print(f"[✓] Hoàn tất Intro Grand Master: {intro_master_export}")
    print(f"   Đồng bộ sang Assets: {intro_master_assets}")

    # 8. Đồng bộ Keyframes bảo toàn Head-Tail Chaining
    kf_shot01 = KEYFRAMES_DIR / "ep01_intro_shot01"
    kf_shot02 = KEYFRAMES_DIR / "ep01_intro_shot02"
    kf_shot01.mkdir(parents=True, exist_ok=True)
    kf_shot02.mkdir(parents=True, exist_ok=True)

    subprocess.run([
        ffmpeg_exe, "-y",
        "-ss", "0.0", "-i", str(shot01_video_out),
        "-vframes", "1", str(kf_shot01 / "start_frame_720p.png")
    ], check=True)
    subprocess.run([
        ffmpeg_exe, "-y",
        "-ss", "9.95", "-i", str(shot01_video_out),
        "-vframes", "1", str(kf_shot01 / "clean_frame_239.jpg")
    ], check=True)
    shutil.copy2(kf_shot01 / "clean_frame_239.jpg", kf_shot02 / "start_frame_720p.png")
    subprocess.run([
        ffmpeg_exe, "-y",
        "-ss", "9.95", "-i", str(shot02_video_out),
        "-vframes", "1", str(kf_shot02 / "clean_frame_239.jpg")
    ], check=True)

    # 9. Ghép nối đối chứng: Intro (20s) + Prologue (40s) = Liên Hoàn 60s
    prologue_master = EXPORTS_DIR / "prologue_master_40s.mp4"
    if prologue_master.exists():
        intro_prologue_60s = EXPORTS_DIR / "thap_ngu_nien_intro_prologue_continuous_60s.mp4"
        print(f"\n🎬 Đang ghép nối thử nghiệm: Intro (20s) + Prologue (40s) -> {intro_prologue_60s}...")
        subprocess.run([
            ffmpeg_exe, "-y",
            "-i", str(intro_master_export),
            "-i", str(prologue_master),
            "-filter_complex", "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[v][a]",
            "-map", "[v]", "-map", "[a]",
            "-c:v", "libx264", "-crf", "18", "-preset", "slow", "-pix_fmt", "yuv420p",
            "-c:a", "aac", "-b:a", "192k", "-ar", "48000",
            str(intro_prologue_60s)
        ], check=True)
        print(f"[✓] Đã tạo thành công bản liên hoàn 60s: {intro_prologue_60s}")

    print("\n" + "=" * 80)
    print("🎉 HOÀN TẤT TÁI THIẾT KẾ ÂM THANH INTRO: CHỈ NƯỚC CHẢY & KHỚP 100% PROLOGUE!")
    print("=" * 80)
    return True


if __name__ == "__main__":
    produce_cinema_intro_master()
