#!/usr/bin/env python3
"""
为所有4句字幕生成视频，然后合并成一个长视频
"""
import subprocess
import os
import tempfile

# 导入编码处理模块
from console_helper import (
    safe_print, print_header, print_step, print_info,
    print_success, print_fail, print_done
)

def get_video_duration(video_path):
    """获取视频时长（使用ffprobe）"""
    args = [
        'ffprobe',
        '-v', 'quiet',
        '-print_format', 'json',
        '-show_format',
        video_path
    ]
    
    try:
        result = subprocess.run(args, check=True, capture_output=True, text=True)
        import json
        data = json.loads(result.stdout)
        return float(data['format']['duration'])
    except Exception as e:
        safe_print(f"      获取时长失败: {e}")
        return None

def extract_last_frame(video_path, output_image, ffmpeg_path="ffmpeg"):
    """提取视频最后一帧"""
    # 先获取视频时长
    duration = get_video_duration(video_path)
    if duration is None:
        return False
    
    # 在视频结束前0.1秒提取一帧
    args = [
        ffmpeg_path,
        '-y',
        '-ss', str(max(0, duration - 0.1)),
        '-i', video_path,
        '-vframes', '1',
        '-q:v', '2',
        output_image
    ]
    
    try:
        subprocess.run(args, check=True, capture_output=True)
        return True
    except subprocess.CalledProcessError as e:
        safe_print(f"      提取最后一帧失败: {e}")
        return False

def read_subtitle_line(subtitle_path, line_number):
    """从字幕文件读取指定行的文本"""
    try:
        with open(subtitle_path, 'r', encoding='utf-8') as f:
            lines = f.readlines()
        
        # 查找指定行号的字幕
        current_line = 0
        for i, line in enumerate(lines):
            line = line.strip()
            if line.isdigit():
                current_line = int(line)
                if current_line == line_number:
                    # 找到字幕文本（跳过时间轴行）
                    for j in range(i+2, len(lines)):
                        subtitle_text = lines[j].strip()
                        if subtitle_text:
                            return subtitle_text
        return None
    except Exception as e:
        safe_print(f"      读取字幕失败: {e}")
        return None

def create_paused_video_with_subtitle(image_path, duration, subtitle_text, output_path, ffmpeg_path="ffmpeg"):
    """使用静态图片创建视频并添加字幕"""
    # 为字幕文本转义
    safe_subtitle = subtitle_text.replace('\\', '\\\\').replace("'", "\\'")
    
    # 创建带字幕的视频
    args = [
        ffmpeg_path,
        '-y',
        '-loop', '1',
        '-i', image_path,
        '-c:v', 'libx264',
        '-t', str(duration),
        '-pix_fmt', 'yuv420p',
        '-vf', f"fps=30,drawtext=text='{safe_subtitle}':fontsize=48:fontcolor=white:box=1:boxcolor=black@0.5:boxborderw=5:x=(w-text_w)/2:y=100",
        # 只输出视频流
        '-an',
        output_path
    ]
    
    try:
        subprocess.run(args, check=True, capture_output=True)
        return True
    except subprocess.CalledProcessError as e:
        safe_print(f"      创建带字幕的暂停视频失败: {e}")
        return False

def concatenate_videos(video_list, output_path, ffmpeg_path="ffmpeg"):
    """拼接多个视频（仅视频流）"""
    # 创建临时文件列表
    list_file = 'video_list.txt'
    with open(list_file, 'w', encoding='utf-8') as f:
        for video in video_list:
            escaped_path = video.replace('\\', '/')
            f.write(f"file '{escaped_path}'\n")
    
    args = [
        ffmpeg_path,
        '-y',
        '-f', 'concat',
        '-safe', '0',
        '-i', list_file,
        '-c:v', 'libx264',
        '-pix_fmt', 'yuv420p',
        # 只输出视频流
        '-an',
        output_path
    ]
    
    try:
        result = subprocess.run(args, check=True, capture_output=True, text=True)
        os.remove(list_file)
        return True
    except subprocess.CalledProcessError as e:
        safe_print(f"      拼接视频失败")
        if e.stderr:
            error_msg = e.stderr
            if "Permission denied" in error_msg:
                safe_print(f"      错误: 文件权限被拒绝，请更换输出文件名")
            else:
                safe_print(f"      错误信息: {error_msg[:300]}")
        try:
            os.remove(list_file)
        except:
            pass
        return False

def extract_audio(input_video, output_audio, ffmpeg_path="ffmpeg"):
    """提取音频流"""
    args = [
        ffmpeg_path,
        '-y',
        '-i', input_video,
        '-c:a', 'aac',
        '-ar', '44100',
        '-ac', '1',
        # 只输出音频流
        '-vn',
        output_audio
    ]
    
    try:
        subprocess.run(args, check=True, capture_output=True)
        return True
    except subprocess.CalledProcessError as e:
        safe_print(f"      提取音频失败: {e}")
        return False

def create_silent_audio(duration, output_audio, ffmpeg_path="ffmpeg"):
    """创建静音音频"""
    args = [
        ffmpeg_path,
        '-y',
        '-f', 'lavfi',
        '-i', 'anullsrc=r=44100:cl=mono',
        '-c:a', 'aac',
        '-ar', '44100',
        '-ac', '1',
        '-t', str(duration),
        output_audio
    ]
    
    try:
        subprocess.run(args, check=True, capture_output=True)
        return True
    except subprocess.CalledProcessError as e:
        safe_print(f"      创建静音音频失败: {e}")
        return False

def concatenate_audio(audio_list, output_audio, ffmpeg_path="ffmpeg"):
    """拼接多个音频"""
    # 创建临时文件列表
    list_file = 'audio_list.txt'
    with open(list_file, 'w', encoding='utf-8') as f:
        for audio in audio_list:
            escaped_path = audio.replace('\\', '/')
            f.write(f"file '{escaped_path}'\n")
    
    args = [
        ffmpeg_path,
        '-y',
        '-f', 'concat',
        '-safe', '0',
        '-i', list_file,
        '-c:a', 'aac',
        '-ar', '44100',
        '-ac', '1',
        output_audio
    ]
    
    try:
        result = subprocess.run(args, check=True, capture_output=True, text=True)
        os.remove(list_file)
        return True
    except subprocess.CalledProcessError as e:
        safe_print(f"      拼接音频失败: {e}")
        try:
            os.remove(list_file)
        except:
            pass
        return False

def merge_video_audio(video_path, audio_path, output_path, ffmpeg_path="ffmpeg"):
    """合并视频和音频"""
    args = [
        ffmpeg_path,
        '-y',
        '-i', video_path,
        '-i', audio_path,
        '-c:v', 'copy',
        '-c:a', 'aac',
        '-ar', '44100',
        '-ac', '1',
        '-shortest',
        output_path
    ]
    
    try:
        subprocess.run(args, check=True, capture_output=True)
        return True
    except subprocess.CalledProcessError as e:
        safe_print(f"      合并视频和音频失败: {e}")
        return False

def process_segment(segment_number, input_video, subtitle_path, output_video, extra_duration=0.5):
    """处理单个片段"""
    temp_dir = tempfile.gettempdir()
    
    # 临时文件
    last_frame_image = os.path.join(temp_dir, f"last_frame_{segment_number}.png")
    paused_video = os.path.join(temp_dir, f"paused_video_{segment_number}.mp4")
    concatenated_video = os.path.join(temp_dir, f"concatenated_video_{segment_number}.mp4")
    original_audio = os.path.join(temp_dir, f"original_audio_{segment_number}.aac")
    silent_audio = os.path.join(temp_dir, f"silent_audio_{segment_number}.aac")
    concatenated_audio = os.path.join(temp_dir, f"concatenated_audio_{segment_number}.aac")
    
    safe_print(f"\n[处理片段 {segment_number}]")
    
    # 1. 获取原始视频时长
    duration = get_video_duration(input_video)
    if duration is None:
        return False
    print_info("原始时长", f"{duration:.3f}秒")
    
    # 计算静止视频时长
    paused_duration = duration + extra_duration
    print_info("静止视频时长", f"{paused_duration:.3f}秒")
    
    # 2. 读取字幕
    subtitle_text = read_subtitle_line(subtitle_path, line_number=segment_number)
    if subtitle_text is None:
        return False
    print_info("字幕文本", subtitle_text)
    
    # 3. 提取最后一帧
    if not extract_last_frame(input_video, last_frame_image):
        return False
    
    # 4. 创建带字幕的静止画面视频
    if not create_paused_video_with_subtitle(last_frame_image, paused_duration, subtitle_text, paused_video):
        return False
    
    # 5. 拼接视频流
    if not concatenate_videos([input_video, paused_video], concatenated_video):
        return False
    
    # 6. 处理音频
    if not extract_audio(input_video, original_audio):
        return False
    
    if not create_silent_audio(paused_duration, silent_audio):
        return False
    
    if not concatenate_audio([original_audio, silent_audio], concatenated_audio):
        return False
    
    # 7. 合并视频和音频
    if not merge_video_audio(concatenated_video, concatenated_audio, output_video):
        return False
    
    # 清理临时文件
    try:
        files_to_remove = [
            last_frame_image, paused_video, concatenated_video,
            original_audio, silent_audio, concatenated_audio
        ]
        for f in files_to_remove:
            if os.path.exists(f):
                os.remove(f)
    except:
        pass
    
    # 验证结果
    final_duration = get_video_duration(output_video)
    print_info("最终时长", f"{final_duration:.3f}秒")
    
    return True

def main():
    # 配置
    input_videos = [
        "segment_01.mp4",
        "segment_02.mp4", 
        "segment_03.mp4",
        "segment_04.mp4"
    ]
    subtitle_path = "subtitles.srt"
    output_videos = [
        "segment_01_with_subtitle.mp4",
        "segment_02_with_subtitle.mp4",
        "segment_03_with_subtitle.mp4",
        "segment_04_with_subtitle.mp4"
    ]
    final_output = "final_combined_video.mp4"
    
    print_header("处理所有片段并合并")
    
    # 处理每个片段
    processed_videos = []
    for i, (input_video, output_video) in enumerate(zip(input_videos, output_videos), 1):
        print_step(i, 5, f"处理片段 {i}...")
        if process_segment(i, input_video, subtitle_path, output_video):
            processed_videos.append(output_video)
            print_info("状态", "成功")
        else:
            print_info("状态", "失败")
            return
    
    # 合并所有片段
    print_step(5, 5, "合并所有片段...")
    if not concatenate_videos(processed_videos, "temp_combined_video.mp4"):
        safe_print("合并视频失败")
        return
    
    # 处理合并后的音频
    temp_dir = tempfile.gettempdir()
    audio_files = []
    for output_video in processed_videos:
        audio_file = os.path.join(temp_dir, f"temp_audio_{output_video}.aac")
        if extract_audio(output_video, audio_file):
            audio_files.append(audio_file)
        else:
            safe_print("提取音频失败")
            return
    
    combined_audio = os.path.join(temp_dir, "combined_audio.aac")
    if not concatenate_audio(audio_files, combined_audio):
        safe_print("拼接音频失败")
        return
    
    # 合并最终视频和音频
    if not merge_video_audio("temp_combined_video.mp4", combined_audio, final_output):
        safe_print("合并最终视频失败")
        return
    
    # 清理临时文件
    try:
        os.remove("temp_combined_video.mp4")
        for audio_file in audio_files:
            if os.path.exists(audio_file):
                os.remove(audio_file)
        if os.path.exists(combined_audio):
            os.remove(combined_audio)
    except:
        pass
    
    # 验证最终结果
    final_duration = get_video_duration(final_output)
    print_info("最终视频时长", f"{final_duration:.3f}秒")
    
    print_done()

if __name__ == '__main__':
    main()
