#!/usr/bin/env python3
"""
重新生成带空白音的静态视频并合并
确保所有静态视频都带有500ms空白音
"""
import os
import subprocess
import tempfile
import re

# 导入编码处理模块
from console_helper import (
    safe_print, print_header, print_step, print_info,
    print_success, print_fail, print_done
)


def get_audio_duration(audio_path):
    """获取音频时长"""
    args = [
        'ffprobe',
        '-v', 'quiet',
        '-print_format', 'json',
        '-show_format',
        audio_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 0


def create_silent_audio(duration, output_path, 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_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_audio_files(audio_files, output_path, ffmpeg_path="ffmpeg"):
    """使用filter_complex拼接多个音频文件"""
    inputs = []
    filters = []
    
    for i, audio_file in enumerate(audio_files):
        inputs.extend(['-i', audio_file])
        filters.append(f"[{i}:a]")
    
    filters.append(f"concat=n={len(audio_files)}:v=0:a=1[out]")
    
    args = [
        ffmpeg_path,
        '-y',
    ] + inputs + [
        '-filter_complex', ''.join(filters),
        '-map', '[out]',
        '-c:a', 'aac',
        '-ar', '44100',
        '-ac', '1',
        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 create_static_video(image_path, audio_path, output_path, silence_duration=0.5, ffmpeg_path="ffmpeg"):
    """使用图片和音频生成静态视频，音频前加空白音"""
    temp_dir = tempfile.gettempdir()
    
    original_duration = get_audio_duration(audio_path)
    if original_duration == 0:
        safe_print(f"      无法获取音频时长")
        return False
    
    # 创建静音音频
    silent_audio = os.path.join(temp_dir, f"silent_{os.path.basename(audio_path)}.aac")
    if not create_silent_audio(silence_duration, silent_audio):
        return False
    
    # 拼接静音音频和原始音频
    combined_audio = os.path.join(temp_dir, f"combined_{os.path.basename(audio_path)}.aac")
    if not concatenate_audio_files([silent_audio, audio_path], combined_audio):
        try:
            os.remove(silent_audio)
        except:
            pass
        return False
    
    total_duration = silence_duration + original_duration
    
    # 生成视频
    args = [
        ffmpeg_path,
        '-y',
        '-loop', '1',
        '-i', image_path,
        '-i', combined_audio,
        '-c:v', 'libx264',
        '-c:a', 'aac',
        '-ar', '44100',
        '-ac', '1',
        '-t', str(total_duration),
        '-pix_fmt', 'yuv420p',
        '-shortest',
        output_path
    ]
    
    try:
        subprocess.run(args, check=True, capture_output=True)
        try:
            os.remove(silent_audio)
            os.remove(combined_audio)
        except:
            pass
        return True
    except subprocess.CalledProcessError as e:
        safe_print(f"      生成视频失败: {e}")
        try:
            os.remove(silent_audio)
            os.remove(combined_audio)
        except:
            pass
        return False


def concatenate_videos(video_list, output_path, ffmpeg_path="ffmpeg"):
    """拼接多个视频"""
    list_file = 'concat_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',
        '-c:a', 'aac',
        '-ar', '44100',
        '-ac', '1',
        '-pix_fmt', 'yuv420p',
        output_path
    ]
    
    try:
        subprocess.run(args, check=True, capture_output=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 main():
    # 配置
    segments_dir = "all_segments"
    frames_with_subtitle_dir = "all_frames_with_subtitle"
    audio_dir = "tts_audio_all"
    static_videos_dir = "all_static_videos_with_silence"
    output_video = "final_video_with_silence.mp4"
    silence_duration = 0.5  # 500毫秒空白音
    
    print_header("重新处理带空白音的静态视频")
    safe_print("")
    
    # 检查目录
    if not os.path.exists(segments_dir):
        safe_print(f"错误: 片段目录 {segments_dir} 不存在")
        return
    
    if not os.path.exists(frames_with_subtitle_dir):
        safe_print(f"错误: 带字幕的帧目录 {frames_with_subtitle_dir} 不存在")
        return
    
    if not os.path.exists(audio_dir):
        safe_print(f"错误: 音频目录 {audio_dir} 不存在")
        return
    
    # 创建输出目录
    if not os.path.exists(static_videos_dir):
        os.makedirs(static_videos_dir)
    
    # 1. 生成带空白音的静态视频
    print_step(1, 2, "生成带空白音的静态视频...")
    static_video_files = []
    
    # 遍历所有带字幕的帧
    frame_files = sorted([f for f in os.listdir(frames_with_subtitle_dir) if f.endswith('.jpg')])
    
    for frame_file in frame_files:
        # 提取序号
        match = re.match(r'frame_(\d+)_with_subtitle\.jpg', frame_file)
        if match:
            line_number = int(match.group(1))
            
            image_path = os.path.join(frames_with_subtitle_dir, frame_file)
            audio_path = os.path.join(audio_dir, f"tts_line_{line_number}.wav")
            output_path = os.path.join(static_videos_dir, f"static_video_{line_number:03d}.mp4")
            
            if not os.path.exists(audio_path):
                safe_print(f"      警告: 音频文件 {audio_path} 不存在，跳过第{line_number}句")
                continue
            
            safe_print(f"      生成第{line_number}句静态视频...")
            
            if create_static_video(image_path, audio_path, output_path, silence_duration):
                static_video_files.append(output_path)
            else:
                safe_print(f"      生成第{line_number}句静态视频失败")
    
    print_info("成功生成", f"{len(static_video_files)}/{len(frame_files)} 个静态视频")
    safe_print("")
    
    # 2. 拼接视频
    print_step(2, 2, "拼接视频...")
    video_list = []
    
    # 遍历所有序号
    max_number = 68  # 已知最大序号
    for i in range(1, max_number + 1):
        # 原始片段
        segment = os.path.join(segments_dir, f"segment_{i:03d}.mp4")
        if os.path.exists(segment):
            video_list.append(segment)
        
        # 静态视频
        static_video = os.path.join(static_videos_dir, f"static_video_{i:03d}.mp4")
        if os.path.exists(static_video):
            video_list.append(static_video)
    
    # 检查第69段
    segment_69 = os.path.join(segments_dir, "segment_069.mp4")
    if os.path.exists(segment_69):
        video_list.append(segment_69)
    
    if not video_list:
        safe_print("错误: 没有找到任何视频文件")
        return
    
    print_info("总视频数", str(len(video_list)))
    safe_print("开始拼接...")
    
    if concatenate_videos(video_list, output_video):
        print_info("成功生成", output_video)
    else:
        safe_print("拼接视频失败")
        return
    
    print_done()


if __name__ == '__main__':
    main()
