import os
from moviepy.editor import VideoFileClip
from openai import OpenAI
import sys
import subprocess

# 添加raw目录到路径，以便导入subtitles模块
raw_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'raw')
if raw_path not in sys.path:
    sys.path.insert(0, raw_path)

# 导入subtitles.py中的函数（只需要转录功能，压缩在提取时已完成）
from subtitles import transcribe_audio_with_whisper

class AudioProcessor:
    """音频处理器：提取音频、使用Whisper API生成字幕"""
    
    def __init__(self):
        # 配置Whisper API（基于 Ifasr.py 的新版实现）
        self.api_base = os.environ.get('WHISPER_API_BASE', 'https://jeniya.cn/v1')
        self.api_key = os.environ.get('WHISPER_API_KEY', 'sk-5w2FNpdHmV4xoi07RAe2lWiqXGgvRWCbmCk9o8T39hZBhJIc')
        
        # 不再需要全局配置，每次调用时创建新客户端
        print(f"   ✅ Whisper API 配置完成")
        print(f"   🌐 API 地址: {self.api_base}")
    
    
    def extract_audio(self, video_path, process_id):
        """从视频中提取音频并使用Whisper生成字幕（使用subtitles.py中的函数）"""
        try:
            results = {
                'audio_path': None,
                'duration': 0,
                'transcription': None,
                'subtitle_file': None
            }
            
            output_dir = os.path.join('processed', 'audio', process_id)
            os.makedirs(output_dir, exist_ok=True)
            
            print("   🎵 从视频中提取音频...")
            
            # 使用独立命名：process_id + 音频
            audio_filename = f"{process_id}_audio.mp3"
            audio_path = os.path.join(output_dir, audio_filename)
            
            # 先获取视频时长（快速读取）
            try:
                video = VideoFileClip(video_path)
                duration = video.duration
                video.close()
            except Exception as e:
                print(f"   ⚠️  无法读取视频时长: {str(e)}")
                duration = 0
            
            print(f"   💾 提取并压缩音频到: {audio_filename}")
            print(f"   🚀 使用 FFmpeg 直接提取（极速模式）...")
            
            # 规范化路径（Windows 兼容）
            video_path_abs = os.path.abspath(video_path)
            audio_path_abs = os.path.abspath(audio_path)
            
            # 使用 FFmpeg 直接提取音频（比 moviepy 快 10-20 倍）
            # 使用更鲁棒的参数避免编码器错误
            ffmpeg_cmd = [
                'ffmpeg',
                '-i', video_path_abs,      # 输入文件（绝对路径）
                '-vn',                      # 不处理视频流
                '-map', '0:a:0',            # 选择第一个音频流
                '-c:a', 'libmp3lame',       # 使用 LAME MP3 编码器
                '-ar', '16000',             # 16kHz采样率（语音识别标准）
                '-ac', '1',                 # 单声道（减少50%文件大小）
                '-b:a', '32k',              # 32k 比特率（更稳定，避免 LAME 断言错误）
                '-q:a', '9',                # 最低质量（优先文件大小）
                '-compression_level', '0',  # 快速压缩
                '-y',                       # 覆盖已存在文件
                audio_path_abs              # 输出文件（绝对路径）
            ]
            
            try:
                # 执行 FFmpeg 命令（捕获错误信息用于调试）
                result = subprocess.run(
                    ffmpeg_cmd,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    check=True,
                    creationflags=subprocess.CREATE_NO_WINDOW if os.name == 'nt' else 0  # Windows 下隐藏窗口
                )
                
                # 显示文件大小
                file_size = os.path.getsize(audio_path) / (1024 * 1024)  # MB
                print(f"   ✅ 音频提取完成: {file_size:.2f} MB, 时长: {duration:.2f}秒")
                print(f"   ⚡ FFmpeg 极速提取，速度提升 10-20 倍！")
                
                results['audio_path'] = f'/processed/audio/{process_id}/{audio_filename}'
                results['duration'] = duration
                
                # 检查文件大小（API限制约为5MB）
                if file_size > 5:
                    print(f"   ⚠️  警告: 音频文件较大 ({file_size:.2f} MB)，可能超过API限制")
                    print(f"   💡 建议: 使用更短的视频（建议 < 15分钟）")
                    
            except FileNotFoundError:
                print(f"   ❌ 错误: 找不到 FFmpeg，请确保 FFmpeg 已安装并添加到 PATH")
                print(f"   💡 正在尝试使用 moviepy 备用方案（较慢）...")
                
                # 备用方案：使用 moviepy（慢但兼容）
                video = VideoFileClip(video_path)
                audio = video.audio
                
                if audio is not None:
                    audio.write_audiofile(
                        audio_path, 
                        bitrate="12k",
                        verbose=False, 
                        logger=None
                    )
                    audio.close()
                    
                    file_size = os.path.getsize(audio_path) / (1024 * 1024)
                    print(f"   ✅ 音频提取完成: {file_size:.2f} MB")
                    
                    results['audio_path'] = f'/processed/audio/{process_id}/{audio_filename}'
                    results['duration'] = duration
                
                video.close()
                
            except subprocess.CalledProcessError as e:
                print(f"   ❌ FFmpeg 执行失败（退出代码: {e.returncode}）")
                
                # 显示详细的 FFmpeg 错误信息
                if e.stderr:
                    error_output = e.stderr.decode('utf-8', errors='ignore').strip()
                    if error_output:
                        print(f"   📄 FFmpeg 错误详情:")
                        # 显示最后几行错误信息（通常最有用）
                        error_lines = error_output.split('\n')
                        for line in error_lines[-10:]:  # 显示最后10行
                            if line.strip():
                                print(f"      {line}")
                
                print(f"   💡 尝试解决方案:")
                print(f"      1. 检查视频文件是否完整且未损坏")
                print(f"      2. 使用 moviepy 备用方案（较慢但兼容性好）")
                
                # 使用 moviepy 备用方案
                print(f"   🔄 正在使用 moviepy 备用方案...")
                try:
                    video = VideoFileClip(video_path)
                    audio = video.audio
                    
                    if audio is not None:
                        audio.write_audiofile(
                            audio_path, 
                            bitrate="12k",
                            verbose=False, 
                            logger=None
                        )
                        audio.close()
                        
                        file_size = os.path.getsize(audio_path) / (1024 * 1024)
                        print(f"   ✅ 音频提取完成（moviepy）: {file_size:.2f} MB")
                        
                        results['audio_path'] = f'/processed/audio/{process_id}/{audio_filename}'
                        results['duration'] = duration
                    
                    video.close()
                except Exception as moviepy_error:
                    print(f"   ❌ moviepy 也失败了: {str(moviepy_error)}")
                    raise
            
            print(f"   📝 开始使用Whisper API生成字幕...")
            
            # 使用subtitles.py中的函数生成字幕
            transcription_result = self._transcribe_with_whisper_from_subtitles(audio_path, output_dir, process_id)
            
            if transcription_result:
                results['transcription'] = transcription_result['segments']
                results['subtitle_file'] = transcription_result['subtitle_file']
                print(f"   ✅ 字幕生成完成：{len(results['transcription'])} 个片段")
            else:
                print("   ⚠️  Whisper转录失败")
            
            return results
            
        except Exception as e:
            print(f"   ❌ 音频提取错误: {str(e)}")
            import traceback
            traceback.print_exc()
            return {
                'audio_path': None,
                'duration': 0,
                'transcription': None,
                'error': str(e)
            }
    
    def _transcribe_with_whisper_from_subtitles(self, audio_path, output_dir, process_id):
        """使用subtitles.py中的函数转录音频（已经是超低比特率+单声道+低采样率）"""
        try:
            # 检查音频文件大小
            audio_size = os.path.getsize(audio_path) / (1024 * 1024)  # MB
            
            # API 缓冲区限制通常在 5MB 左右
            MAX_FILE_SIZE_MB = 5.0
            
            # 如果文件仍然太大，说明视频时长过长
            if audio_size > MAX_FILE_SIZE_MB:
                print(f"   ❌ 文件过大 ({audio_size:.2f} MB)，超过API限制 ({MAX_FILE_SIZE_MB} MB)")
                print(f"   💡 解决方案:")
                print(f"      1. 使用更短的视频（建议 < 15分钟）")
                print(f"      2. 或者分段上传视频")
                print(f"      3. 或者切换到支持更大文件的API提供商")
                return None
            
            print(f"   📞 调用Whisper API（文件大小: {audio_size:.2f} MB）...")
            
            try:
                # 使用subtitles.py中的transcribe_audio_with_whisper函数
                # 传递API提供商参数（可动态修改）
                transcript = transcribe_audio_with_whisper(
                    audio_path,
                    api_base=self.api_base,
                    api_key=self.api_key
                )
                
                if not transcript:
                    print("   ❌ Whisper API调用失败")
                    return None
                    
            except Exception as e:
                error_msg = str(e)
                if "413" in error_msg or "Request Entity Too Large" in error_msg or "buffer full" in error_msg:
                    print(f"   ❌ 文件太大！API返回错误")
                    print(f"   📊 当前文件: {audio_size:.2f} MB")
                    print(f"   💡 解决方案:")
                    print(f"      1. 使用更短的视频（建议 < 15分钟）")
                    print(f"      2. 或者分段上传视频")
                    print(f"      3. 或者切换到支持更大文件的API提供商")
                    return None
                else:
                    print(f"   ❌ Whisper API错误: {error_msg}")
                    return None
            
            # 保存字幕文件 - 使用独立命名
            subtitle_filename = f"{process_id}_whisper_subtitles.txt"
            subtitle_file = os.path.join(output_dir, subtitle_filename)
            
            segments = []
            
            print(f"   💾 保存字幕文件: {subtitle_filename}")
            with open(subtitle_file, 'w', encoding='utf-8') as f:
                
                if hasattr(transcript, 'segments') and transcript.segments:
                    for segment in transcript.segments:
                        # 新版 API 返回的是 Pydantic 对象，直接访问属性
                        start_time = segment.start if hasattr(segment, 'start') else 0
                        end_time = segment.end if hasattr(segment, 'end') else 0
                        text = segment.text.strip() if hasattr(segment, 'text') else ''
                        
                        # 转换为分钟:秒格式
                        start_min = int(start_time // 60)
                        start_sec = int(start_time % 60)
                        end_min = int(end_time // 60)
                        end_sec = int(end_time % 60)
                        
                        time_range = f"{start_min:02d}:{start_sec:02d}-{end_min:02d}:{end_sec:02d}"
                        f.write(f'"{time_range}": "{text}"\n')
                        
                        segments.append({
                            'start_time': start_time,
                            'end_time': end_time,
                            'text': text
                        })
                else:
                    f.write("未获取到时间戳分段信息\n")
            
            print(f"   ✅ 字幕文件保存成功")
            
            return {
                'segments': segments,
                'subtitle_file': subtitle_file,
                'full_text': transcript.text
            }
            
        except Exception as e:
            print(f"   ❌ Whisper转录错误: {str(e)}")
            import traceback
            traceback.print_exc()
            return None


