const ffmpeg = require('fluent-ffmpeg');
const fs = require('fs');
const path = require('path');
const { promisify } = require('util');
const mkdir = promisify(fs.mkdir);
const exists = promisify(fs.exists);

class AudioService {
  /**
   * 根据字幕时间信息切割音频文件
   * @param {string} audioFilePath 音频文件路径
   * @param {Array} subtitles 字幕数组，每个字幕对象包含开始时间和结束时间
   * @param {string} outputDir 输出目录
   * @returns {Promise<Array>} 切割后的音频文件路径数组
   */
  async cutAudioBySubtitles(audioFilePath, subtitles, outputDir) {
    try {
      // 确保输出目录存在
      if (!(await exists(outputDir))) {
        await mkdir(outputDir, { recursive: true });
      }

      const audioFiles = [];
      
      // 为每个字幕切割音频
      for (let i = 0; i < subtitles.length; i++) {
        const subtitle = subtitles[i];
        const outputFilePath = path.join(outputDir, `segment_${i + 1}.mp3`);
        
        // 计算开始时间和持续时间（秒）
        const startTime = this._timeStringToSeconds(subtitle.start);
        const endTime = this._timeStringToSeconds(subtitle.end);
        const duration = endTime - startTime;
        
        // 使用ffmpeg切割音频
        await this._cutAudio(audioFilePath, outputFilePath, startTime, duration);
        
        audioFiles.push({
          path: outputFilePath,
          index: i,
          startTime: subtitle.start,
          endTime: subtitle.end,
          duration: duration
        });
      }
      
      return audioFiles;
    } catch (error) {
      console.error('切割音频文件时出错:', error);
      throw error;
    }
  }
  
  /**
   * 将时间字符串（如 "00:00:12,345"）转换为秒数
   * @param {string} timeString 时间字符串
   * @returns {number} 秒数
   */
  _timeStringToSeconds(timeString) {
    // 处理不同格式的时间字符串
    timeString = timeString.replace(',', '.');
    const parts = timeString.split(':');
    
    if (parts.length === 3) {
      // 格式: HH:MM:SS.ms
      const [hours, minutes, seconds] = parts;
      return (
        parseInt(hours) * 3600 + 
        parseInt(minutes) * 60 + 
        parseFloat(seconds)
      );
    } else if (parts.length === 2) {
      // 格式: MM:SS.ms
      const [minutes, seconds] = parts;
      return parseInt(minutes) * 60 + parseFloat(seconds);
    }
    
    // 默认返回
    return parseFloat(timeString);
  }
  
  /**
   * 使用ffmpeg切割音频
   * @param {string} inputPath 输入文件路径
   * @param {string} outputPath 输出文件路径
   * @param {number} startTime 开始时间（秒）
   * @param {number} duration 持续时间（秒）
   * @returns {Promise} 完成切割的Promise
   */
  _cutAudio(inputPath, outputPath, startTime, duration) {
    return new Promise((resolve, reject) => {
      ffmpeg(inputPath)
        .setStartTime(startTime)
        .setDuration(duration)
        .output(outputPath)
        .audioCodec('libmp3lame')
        .on('end', () => {
          console.log(`音频片段已创建: ${outputPath}`);
          resolve(outputPath);
        })
        .on('error', (err) => {
          console.error(`处理音频时出错: ${err.message}`);
          reject(err);
        })
        .run();
    });
  }
  
  /**
   * 获取音频文件的元数据（时长等）
   * @param {string} audioFilePath 音频文件路径
   * @returns {Promise<Object>} 音频元数据
   */
  getAudioMetadata(audioFilePath) {
    return new Promise((resolve, reject) => {
      ffmpeg.ffprobe(audioFilePath, (err, metadata) => {
        if (err) {
          console.error('获取音频元数据时出错:', err);
          reject(err);
          return;
        }
        
        resolve({
          duration: metadata.format.duration,
          format: metadata.format.format_name,
          size: metadata.format.size
        });
      });
    });
  }
  
  /**
   * 提取音频文件（从视频中）
   * @param {string} videoFilePath 视频文件路径
   * @param {string} outputFilePath 输出音频文件路径
   * @returns {Promise<string>} 输出音频文件路径
   */
  extractAudioFromVideo(videoFilePath, outputFilePath) {
    return new Promise((resolve, reject) => {
      ffmpeg(videoFilePath)
        .output(outputFilePath)
        .noVideo()
        .audioCodec('libmp3lame')
        .on('end', () => {
          console.log(`音频已从视频中提取: ${outputFilePath}`);
          resolve(outputFilePath);
        })
        .on('error', (err) => {
          console.error(`从视频中提取音频时出错: ${err.message}`);
          reject(err);
        })
        .run();
    });
  }
}

module.exports = new AudioService(); 