{"version":3,"file":"ffmpeg.cjs","sources":["../../../src/utils/ffmpeg.js"],"sourcesContent":["import execa from 'execa';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport fs from 'fs-extra';\r\nimport { nanoid } from 'nanoid';\r\nimport { readFileStreams } from './video-utils.js';\r\nimport { DEFAULT_FFMPEG_CONFIG } from '../types/constants.js';\r\n\r\n/**\r\n * FFmpeg 工具类\r\n */\r\nexport class FFmpegUtil {\r\n  constructor(config = {}) {\r\n    this.config = { ...DEFAULT_FFMPEG_CONFIG, ...config };\r\n  }\r\n\r\n  /**\r\n   * 检查 FFmpeg 是否可用\r\n   */\r\n  async checkFFmpeg() {\r\n    try {\r\n      const { stdout } = await execa('ffmpeg', ['-version']);\r\n      return stdout.includes('ffmpeg version');\r\n    } catch (error) {\r\n      throw new Error('FFmpeg is not installed or not in PATH. Please install FFmpeg first.');\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 将图片序列转换为视频\r\n   * @param {string} inputPattern - 输入图片序列模式（如：frame_%04d.png）\r\n   * @param {string} outputPath - 输出视频路径\r\n   * @param {Object} options - 选项\r\n   */\r\n  async imagesToVideo(inputPattern, outputPath, options = {}) {\r\n    await this.checkFFmpeg();\r\n\r\n    const {\r\n      fps = 30,\r\n      width,\r\n      height,\r\n      codec = this.config.codec,\r\n      preset = this.config.preset,\r\n      crf = this.config.crf,\r\n      pixelFormat = this.config.pixelFormat,\r\n    } = options;\r\n\r\n    const args = [\r\n      '-y', // 覆盖输出文件\r\n      '-hide_banner', // 隐藏版本信息横幅\r\n      '-loglevel', 'error', // 只显示错误信息\r\n      '-framerate', fps.toString(),\r\n      '-i', inputPattern,\r\n      '-c:v', codec,\r\n      '-preset', preset,\r\n      '-crf', crf.toString(),\r\n      '-pix_fmt', pixelFormat,\r\n      // 关键帧设置，解决播放延迟问题\r\n      '-g', '30', // 每30帧一个关键帧（每秒一个关键帧 @ 30fps）\r\n      '-keyint_min', '30', // 最小关键帧间隔\r\n      '-sc_threshold', '0', // 禁用场景切换检测，避免不规则关键帧\r\n    ];\r\n\r\n    if (width && height) {\r\n      args.push('-s', `${width}x${height}`);\r\n    }\r\n\r\n    // faststart：移动 moov atom 到文件开头，支持网页快速播放\r\n    args.push('-movflags', '+faststart');\r\n    args.push(outputPath);\r\n\r\n    try {\r\n      await execa('ffmpeg', args);\r\n      return outputPath;\r\n    } catch (error) {\r\n      throw new Error(`FFmpeg encoding failed: ${error.message}`);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 通过管道将图片数据直接写入 FFmpeg（不保存中间文件）\r\n   * @param {string} outputPath - 输出视频路径\r\n   * @param {Object} options - 选项\r\n   * @param {boolean} options.useRaw - 是否使用原始视频数据格式（默认 false，使用 PNG）\r\n   * @returns {Object} 返回 { process, writeFrame, addStream } 对象\r\n   *   - process: FFmpeg 进程\r\n   *   - writeFrame: 函数，用于写入一帧 buffer（PNG 或 raw）\r\n   *   - addStream: 函数，用于添加 Stream 输入（用于流式渲染）\r\n   *   - finish: Promise，等待编码完成\r\n   */\r\n  async imagesToVideoPipe(outputPath, options = {}) {\r\n    await this.checkFFmpeg();\r\n\r\n    const {\r\n      fps = 30,\r\n      width,\r\n      height,\r\n      codec = this.config.codec,\r\n      preset = this.config.preset,\r\n      crf = this.config.crf,\r\n      pixelFormat = this.config.pixelFormat,\r\n      useRaw = false, // 是否使用原始视频数据格式\r\n    } = options;\r\n\r\n    const args = [\r\n      '-y', // 覆盖输出文件\r\n      '-hide_banner', // 隐藏版本信息横幅\r\n      '-loglevel', 'error', // 只显示错误信息\r\n    ];\r\n\r\n    if (useRaw) {\r\n      // 使用原始视频数据格式（RGBA）\r\n      // 注意：node-canvas 的 toBuffer('raw') 返回 RGBA 格式\r\n      const size = `${width}x${height}`;\r\n      args.push(\r\n        '-f', 'rawvideo', // 原始视频格式\r\n        '-vcodec', 'rawvideo', // 原始视频编码\r\n        '-pixel_format', 'rgba', // RGBA 像素格式\r\n        '-video_size', size, // 视频尺寸\r\n        '-framerate', fps.toString(),\r\n        '-i', '-', // 从 stdin 读取\r\n        '-max_muxing_queue_size', '1024', // 增大缓冲区队列\r\n      );\r\n    } else {\r\n      // 使用 PNG 图片格式（向后兼容）\r\n      args.push(\r\n        '-f', 'image2pipe', // 从管道读取图片\r\n        '-vcodec', 'png', // 输入格式为 PNG\r\n        '-framerate', fps.toString(),\r\n        '-i', '-' // 从 stdin 读取\r\n      );\r\n    }\r\n\r\n    args.push(\r\n      '-c:v', codec,\r\n      '-preset', preset,\r\n      '-crf', crf.toString(),\r\n      '-pix_fmt', pixelFormat,\r\n      // 关键帧设置，解决播放延迟问题\r\n      '-g', '30', // 每30帧一个关键帧（每秒一个关键帧 @ 30fps）\r\n      '-keyint_min', '30', // 最小关键帧间隔\r\n      '-sc_threshold', '0', // 禁用场景切换检测\r\n    );\r\n\r\n    if (width && height && !useRaw) {\r\n      args.push('-s', `${width}x${height}`);\r\n    }\r\n\r\n    // faststart：移动 moov atom 到文件开头，支持网页快速播放\r\n    args.push('-movflags', '+faststart');\r\n    args.push(outputPath);\r\n\r\n    // 启动 FFmpeg 进程，stdin 作为管道\r\n    const ffmpegProcess = execa('ffmpeg', args, {\r\n      stdin: 'pipe',\r\n      stdout: 'pipe',\r\n      stderr: 'pipe',\r\n    });\r\n\r\n    // 在 CommonJS 编译环境中，execa 可能返回一个代理对象\r\n    // 需要等待 stdin 属性可用（最多等待 100ms）\r\n    if (!ffmpegProcess.stdin) {\r\n      let waited = 0;\r\n      const maxWait = 100; // 100ms\r\n      while (!ffmpegProcess.stdin && waited < maxWait) {\r\n        await new Promise(resolve => setTimeout(resolve, 10));\r\n        waited += 10;\r\n      }\r\n    }\r\n\r\n    // 检查 stdin 是否可用\r\n    if (!ffmpegProcess || !ffmpegProcess.stdin) {\r\n      throw new Error('FFmpeg process stdin is not available. execa may not support stdin pipe in this environment.');\r\n    }\r\n\r\n    // 监听进程错误（但不阻塞写入）\r\n    let processError = null;\r\n    let stderrOutput = '';\r\n    \r\n    // 监听 stderr 输出（用于调试）\r\n    if (ffmpegProcess.stderr) {\r\n      ffmpegProcess.stderr.on('data', (data) => {\r\n        const text = data.toString();\r\n        stderrOutput += text;\r\n        // 如果输出包含错误信息，记录它\r\n        if (text.includes('error') || text.includes('Error') || text.includes('failed')) {\r\n          console.warn(`[FFmpeg stderr] ${text.trim()}`);\r\n        }\r\n      });\r\n    }\r\n    \r\n    ffmpegProcess.catch((error) => {\r\n      processError = error;\r\n      if (stderrOutput) {\r\n        console.error(`[FFmpeg stderr 完整输出]:\\n${stderrOutput}`);\r\n      }\r\n    });\r\n\r\n    // 创建 Promise 来等待编码完成\r\n    let finishPromise = null;\r\n    let finishResolve = null;\r\n    let finishReject = null;\r\n\r\n    finishPromise = new Promise((resolve, reject) => {\r\n      finishResolve = resolve;\r\n      finishReject = reject;\r\n    });\r\n\r\n    // 监听进程完成\r\n    ffmpegProcess.then((result) => {\r\n      console.log('[FFmpeg] 进程正常退出');\r\n      if (finishResolve) finishResolve(outputPath);\r\n    }).catch((error) => {\r\n      console.error('[FFmpeg] 进程异常退出:', error.message);\r\n      if (stderrOutput) {\r\n        console.error(`[FFmpeg stderr 完整输出]:\\n${stderrOutput}`);\r\n      }\r\n      if (finishReject) finishReject(new Error(`FFmpeg encoding failed: ${error.message}`));\r\n    });\r\n\r\n    // 写入帧的函数\r\n    let framesWrittenCount = 0;\r\n    const writeFrame = async (buffer) => {\r\n      if (processError) {\r\n        throw new Error(`FFmpeg process error: ${processError.message}`);\r\n      }\r\n      if (!ffmpegProcess.stdin) {\r\n        throw new Error('FFmpeg stdin is not available');\r\n      }\r\n      if (ffmpegProcess.stdin.destroyed) {\r\n        throw new Error('FFmpeg stdin is closed');\r\n      }\r\n      \r\n      // 检查 buffer 是否有效\r\n      if (!buffer || !Buffer.isBuffer(buffer)) {\r\n        throw new Error(`Invalid buffer: expected Buffer, got ${typeof buffer}`);\r\n      }\r\n      if (buffer.length === 0) {\r\n        throw new Error('Buffer is empty');\r\n      }\r\n      \r\n      try {\r\n        await new Promise((resolve, reject) => {\r\n          // 再次检查是否已关闭\r\n          if (ffmpegProcess.stdin.destroyed) {\r\n            reject(new Error('FFmpeg stdin was closed during write'));\r\n            return;\r\n          }\r\n          \r\n          // 检查进程是否还在运行\r\n          if (processError) {\r\n            reject(new Error(`FFmpeg process error: ${processError.message}`));\r\n            return;\r\n          }\r\n          \r\n          const writeResult = ffmpegProcess.stdin.write(buffer, (error) => {\r\n            if (error) {\r\n              reject(new Error(`Failed to write frame to FFmpeg: ${error.message}`));\r\n            } else {\r\n              framesWrittenCount++;\r\n              resolve();\r\n            }\r\n          });\r\n          \r\n          // 如果 write 返回 false，说明缓冲区已满，等待 drain 事件\r\n          if (writeResult === false) {\r\n            ffmpegProcess.stdin.once('drain', () => {\r\n              framesWrittenCount++;\r\n              resolve();\r\n            });\r\n          }\r\n        });\r\n      } catch (error) {\r\n        // 如果错误信息已经包含详细信息，直接抛出\r\n        if (error.message.includes('FFmpeg') || error.message.includes('stdin')) {\r\n          throw error;\r\n        }\r\n        throw new Error(`Failed to write frame to FFmpeg (已写入 ${framesWrittenCount} 帧): ${error.message}`);\r\n      }\r\n    };\r\n\r\n    // 添加 Stream 输入（用于流式渲染）\r\n    const addStream = (stream) => {\r\n      if (processError) {\r\n        throw new Error(`FFmpeg process error: ${processError.message}`);\r\n      }\r\n      if (!ffmpegProcess.stdin) {\r\n        throw new Error('FFmpeg stdin is not available');\r\n      }\r\n      if (ffmpegProcess.stdin.destroyed) {\r\n        throw new Error('FFmpeg stdin is closed');\r\n      }\r\n      stream.pipe(ffmpegProcess.stdin);\r\n    };\r\n\r\n    // 结束写入的函数\r\n    const end = () => {\r\n      console.log(`[FFmpeg] 准备关闭 stdin 管道（已写入 ${framesWrittenCount} 帧）...`);\r\n      if (ffmpegProcess.stdin && !ffmpegProcess.stdin.destroyed) {\r\n        try {\r\n          ffmpegProcess.stdin.end();\r\n          console.log('[FFmpeg] stdin 管道已关闭');\r\n        } catch (error) {\r\n          console.error('[FFmpeg] 关闭 stdin 时出错:', error.message);\r\n        }\r\n      } else {\r\n        console.warn('[FFmpeg] stdin 已关闭或不存在');\r\n      }\r\n    };\r\n\r\n    // 强制终止 FFmpeg 进程（用于错误恢复）\r\n    const kill = () => {\r\n      console.log(`[FFmpeg] 终止进程（已写入 ${framesWrittenCount} 帧）`);\r\n      if (ffmpegProcess && !ffmpegProcess.killed) {\r\n        try {\r\n          ffmpegProcess.kill('SIGTERM');\r\n        } catch (_) {}\r\n      }\r\n    };\r\n\r\n    return {\r\n      process: ffmpegProcess,\r\n      writeFrame,\r\n      addStream,\r\n      end,\r\n      kill,\r\n      finish: finishPromise,\r\n    };\r\n  }\r\n\r\n  /**\r\n   * 添加音频到视频\r\n   * @param {string} videoPath - 视频路径\r\n   * @param {string} audioPath - 音频路径\r\n   * @param {string} outputPath - 输出路径\r\n   * @param {Object} options - 选项\r\n   */\r\n  async addAudioToVideo(videoPath, audioPath, outputPath, options = {}) {\r\n    await this.checkFFmpeg();\r\n\r\n    const {\r\n      audioCodec = this.config.audioCodec,\r\n      audioBitrate = this.config.audioBitrate,\r\n      audioStartTime = 0,\r\n      shortest = false,\r\n    } = options;\r\n\r\n    const args = [\r\n      '-y',\r\n      '-hide_banner', // 隐藏版本信息横幅\r\n      '-loglevel', 'error', // 只显示错误信息\r\n      '-i', videoPath,\r\n      '-i', audioPath,\r\n      '-c:v', 'copy', // 复制视频流，不重新编码\r\n      '-c:a', audioCodec,\r\n      '-b:a', audioBitrate,\r\n      '-map', '0:v:0',\r\n      '-map', '1:a:0',\r\n    ];\r\n\r\n    if (audioStartTime > 0) {\r\n      args.push('-ss', audioStartTime.toString());\r\n    }\r\n\r\n    if (shortest) {\r\n      args.push('-shortest');\r\n    }\r\n    args.push(outputPath);\r\n\r\n    try {\r\n      await execa('ffmpeg', args);\r\n      return outputPath;\r\n    } catch (error) {\r\n      throw new Error(`Failed to add audio to video: ${error.message}`);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 合并多个视频\r\n   * @param {string[]} videoPaths - 视频路径数组\r\n   * @param {string} outputPath - 输出路径\r\n   */\r\n  async concatVideos(videoPaths, outputPath, options = {}) {\r\n    await this.checkFFmpeg();\r\n\r\n    const {\r\n      fps = 30,\r\n      width,\r\n      height,\r\n      codec = this.config.codec || 'libx264',\r\n      preset = 'fast', // 使用 fast  preset 加速合并\r\n      crf = this.config.crf || 23,\r\n    } = options;\r\n\r\n    // 创建临时文件列表\r\n    const listFile = path.join(path.dirname(outputPath), 'concat_list.txt');\r\n    const listContent = videoPaths.map(p => `file '${path.resolve(p)}'`).join('\\n');\r\n    await fs.writeFile(listFile, listContent);\r\n\r\n    // 使用重新编码代替 copy，避免关键帧不对齐导致的播放问题\r\n    // 同时添加关键帧设置确保最终视频播放顺畅\r\n    const args = [\r\n      '-y',\r\n      '-hide_banner',\r\n      '-loglevel', 'error',\r\n      '-f', 'concat',\r\n      '-safe', '0',\r\n      '-i', listFile,\r\n      '-c:v', codec,\r\n      '-preset', preset,\r\n      '-crf', crf.toString(),\r\n      '-pix_fmt', 'yuv420p',\r\n      '-g', '30', // 关键帧间隔\r\n      '-keyint_min', '30',\r\n      '-sc_threshold', '0',\r\n      '-movflags', '+faststart', // 快速播放\r\n    ];\r\n\r\n    if (width && height) {\r\n      args.push('-s', `${width}x${height}`);\r\n    }\r\n\r\n    args.push(outputPath);\r\n\r\n    try {\r\n      await execa('ffmpeg', args);\r\n      await fs.remove(listFile); // 清理临时文件\r\n      return outputPath;\r\n    } catch (error) {\r\n      await fs.remove(listFile).catch(() => {});\r\n      throw new Error(`Failed to concat videos: ${error.message}`);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 获取视频信息\r\n   * @param {string} videoPath - 视频路径\r\n   */\r\n  async getVideoInfo(videoPath) {\r\n    await this.checkFFmpeg();\r\n\r\n    const args = [\r\n      '-i', videoPath,\r\n      '-hide_banner', // 隐藏版本信息横幅\r\n      '-loglevel', 'error', // 只显示错误信息\r\n    ];\r\n\r\n    try {\r\n      const { stderr } = await execa('ffmpeg', args, { reject: false });\r\n      // 解析 stderr 输出获取视频信息\r\n      const durationMatch = stderr.match(/Duration: (\\d{2}):(\\d{2}):(\\d{2}\\.\\d{2})/);\r\n      const sizeMatch = stderr.match(/(\\d+)x(\\d+)/);\r\n      const fpsMatch = stderr.match(/(\\d+(?:\\.\\d+)?) fps/);\r\n\r\n      return {\r\n        duration: durationMatch ? this.parseDuration(durationMatch) : 0,\r\n        width: sizeMatch ? parseInt(sizeMatch[1]) : 0,\r\n        height: sizeMatch ? parseInt(sizeMatch[2]) : 0,\r\n        fps: fpsMatch ? parseFloat(fpsMatch[1]) : 30,\r\n      };\r\n    } catch (error) {\r\n      throw new Error(`Failed to get video info: ${error.message}`);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 解析时长字符串\r\n   */\r\n  parseDuration(match) {\r\n    const hours = parseInt(match[1]);\r\n    const minutes = parseInt(match[2]);\r\n    const seconds = parseFloat(match[3]);\r\n    return hours * 3600 + minutes * 60 + seconds;\r\n  }\r\n\r\n  /**\r\n   * 合并多个音频文件\r\n   * @param {Array<Object>} audioConfigs - 音频配置数组 [{path, startTime, duration, volume, fadeIn, fadeOut, loop}, ...]\r\n   * @param {Object} options - 选项\r\n   * @returns {Promise<string>} 合并后的音频文件路径\r\n   */\r\n  async mergeAudios(audioConfigs, options = {}) {\r\n    await this.checkFFmpeg();\r\n\r\n    const {\r\n      outputDir = './output',\r\n      duration, // 总时长（秒）\r\n      audioMode = 'standard', // 混音模式：'standard' | 'fkvideo'\r\n      loudnessNormalization = true, // 是否对最终输出应用响度归一化\r\n      loudnessPreset = 'shortvideo', // 响度预设：'broadcast' | 'shortvideo' | 'podcast'\r\n    } = options;\r\n\r\n    if (!audioConfigs || audioConfigs.length === 0) {\r\n      return null;\r\n    }\r\n\r\n    // 单音频快路径 A：所有参数都是默认值\r\n    // 仍然走一次 loudnorm，避免原始音频响度不均\r\n    if (audioConfigs.length === 1) {\r\n      const audio = audioConfigs[0];\r\n      if (audio.fadeIn === 0 && audio.fadeOut === 0 && audio.volume === 1.0 && audio.startTime === 0) {\r\n        if (!loudnessNormalization) return audio.path;\r\n        return await this.normalizeLoudness(audio.path, { preset: loudnessPreset });\r\n      }\r\n    }\r\n\r\n    // 创建临时目录\r\n    const tempDir = path.join(outputDir, `temp_audio_${Date.now()}`);\r\n    await fs.ensureDir(tempDir);\r\n\r\n    try {\r\n      // 处理每个音频文件（应用音量、淡入淡出等效果）\r\n      const processedAudios = [];\r\n      for (let i = 0; i < audioConfigs.length; i++) {\r\n        const audio = audioConfigs[i];\r\n        if (!await fs.pathExists(audio.path)) {\r\n          console.warn(`音频文件不存在: ${audio.path}`);\r\n          continue;\r\n        }\r\n\r\n        const processedPath = path.join(tempDir, `processed_${i}.wav`);\r\n        const args = [\r\n          '-y',\r\n          '-hide_banner', // 隐藏版本信息横幅\r\n          '-loglevel', 'error', // 只显示错误信息\r\n          '-i', audio.path\r\n        ];\r\n\r\n        // 音频裁剪：从原始音频文件中裁剪指定时间段\r\n        // 支持 cutFrom/cutTo（新方式）和 audioStartTime/audioEndTime（旧方式）\r\n        const audioStartTime = audio.cutFrom !== undefined ? audio.cutFrom : (audio.audioStartTime !== undefined ? audio.audioStartTime : 0);\r\n        const audioEndTime = audio.cutTo !== undefined ? audio.cutTo : audio.audioEndTime;\r\n        \r\n        if (audioStartTime > 0) {\r\n          args.push('-ss', audioStartTime.toString());\r\n        }\r\n\r\n        // 计算裁剪后的音频时长\r\n        let trimDuration = audio.duration; // 默认使用 duration\r\n        if (audioEndTime !== undefined && audioStartTime !== undefined) {\r\n          // 如果指定了 audioEndTime，计算裁剪时长\r\n          trimDuration = audioEndTime - audioStartTime;\r\n        } else if (audioEndTime !== undefined) {\r\n          // 如果只指定了 audioEndTime，需要先获取音频总时长\r\n          // 这里简化处理，使用 duration 或 audioEndTime\r\n          trimDuration = audioEndTime - audioStartTime;\r\n        }\r\n\r\n        // 应用音量\r\n        const audioFilters = [];\r\n        if (audio.volume !== undefined && audio.volume !== 1.0) {\r\n          audioFilters.push(`volume=${audio.volume}`);\r\n        }\r\n\r\n        // 应用淡入淡出\r\n        if (audio.fadeIn > 0 || audio.fadeOut > 0) {\r\n          const fadeIn = audio.fadeIn || 0;\r\n          const fadeOut = audio.fadeOut || 0;\r\n          const audioDuration = trimDuration || audio.duration || 0;\r\n          \r\n          if (fadeIn > 0 && fadeOut > 0) {\r\n            audioFilters.push(`afade=t=in:st=0:d=${fadeIn},afade=t=out:st=${Math.max(0, audioDuration - fadeOut)}:d=${fadeOut}`);\r\n          } else if (fadeIn > 0) {\r\n            audioFilters.push(`afade=t=in:st=0:d=${fadeIn}`);\r\n          } else if (fadeOut > 0) {\r\n            audioFilters.push(`afade=t=out:st=${Math.max(0, audioDuration - fadeOut)}:d=${fadeOut}`);\r\n          }\r\n        }\r\n\r\n        if (audioFilters.length > 0) {\r\n          args.push('-af', audioFilters.join(','));\r\n        }\r\n\r\n        // 如果指定了裁剪时长，截取音频\r\n        if (trimDuration) {\r\n          args.push('-t', trimDuration.toString());\r\n        } else if (audio.audioEndTime !== undefined && audio.audioStartTime !== undefined) {\r\n          // 如果指定了 audioEndTime，计算并应用时长\r\n          const calculatedDuration = audio.audioEndTime - audio.audioStartTime;\r\n          if (calculatedDuration > 0) {\r\n            args.push('-t', calculatedDuration.toString());\r\n          }\r\n        }\r\n\r\n        args.push(processedPath);\r\n\r\n        try {\r\n          await execa('ffmpeg', args);\r\n          processedAudios.push({\r\n            path: processedPath,\r\n            startTime: audio.startTime || 0,\r\n            mixVolume: audio.volume !== undefined ? audio.volume : 1.0,\r\n          });\r\n        } catch (error) {\r\n          console.warn(`处理音频失败: ${audio.path}`, error.message);\r\n        }\r\n      }\r\n\r\n      if (processedAudios.length === 0) {\r\n        return null;\r\n      }\r\n\r\n      // 单音频快路径 B：处理后只有 1 个音频且没有延迟\r\n      // 处理后的文件只应用了 volume/afade，没做响度归一化\r\n      if (processedAudios.length === 1 && processedAudios[0].startTime === 0) {\r\n        if (!loudnessNormalization) return processedAudios[0].path;\r\n        return await this.normalizeLoudness(processedAudios[0].path, { preset: loudnessPreset });\r\n      }\r\n\r\n      // 创建音频混合脚本\r\n      const outputPath = path.join(tempDir, 'merged_audio.wav');\r\n      \r\n      // 使用 amix 或 amerge 混合音频\r\n      // 首先需要将所有音频对齐到正确的时间位置\r\n      const filterInputs = [];\r\n      const filterComplex = [];\r\n      \r\n      for (let i = 0; i < processedAudios.length; i++) {\r\n        const audio = processedAudios[i];\r\n        filterInputs.push(`-i`, audio.path);\r\n        \r\n        // 如果音频有延迟，需要添加延迟\r\n        if (audio.startTime > 0) {\r\n          filterComplex.push(`[${i}]adelay=${Math.round(audio.startTime * 1000)}|${Math.round(audio.startTime * 1000)}[a${i}]`);\r\n        } else {\r\n          filterComplex.push(`[${i}]acopy[a${i}]`);\r\n        }\r\n      }\r\n\r\n      // 混合所有音频\r\n      const mixInputs = processedAudios.map((_, i) => `[a${i}]`).join('');\r\n      // 选择目标响度参数\r\n      const target = {\r\n        broadcast:  { I: -23, LRA: 7,  TP: -2.0 },\r\n        shortvideo: { I: -16, LRA: 11, TP: -1.5 },\r\n        podcast:    { I: -19, LRA: 9,  TP: -2.0 },\r\n      }[loudnessPreset] || { I: -16, LRA: 11, TP: -1.5 };\r\n\r\n      if (audioMode === 'fkvideo') {\r\n        const weights = processedAudios.map(a => (a.mixVolume !== undefined ? a.mixVolume : 1)).join(' ');\r\n        filterComplex.push(`${mixInputs}amix=inputs=${processedAudios.length}:duration=longest:dropout_transition=0:normalize=0:weights=${weights}[out0]`);\r\n        // fkvideo 模式也补上响度归一化（可通过 loudnessNormalization=false 关闭）\r\n        if (loudnessNormalization) {\r\n          filterComplex.push(`[out0]loudnorm=I=${target.I}:LRA=${target.LRA}:TP=${target.TP}[out]`);\r\n        } else {\r\n          filterComplex.push(`[out0]acopy[out]`);\r\n        }\r\n      } else {\r\n        // 使用 normalize=0 保持输入素材的原始能量，不因输入数量被等分\r\n        filterComplex.push(`${mixInputs}amix=inputs=${processedAudios.length}:duration=longest:dropout_transition=0:normalize=0[out0]`);\r\n        // 默认仅应用响度规范（EBU R128）\r\n        if (loudnessNormalization) {\r\n          filterComplex.push(`[out0]loudnorm=I=${target.I}:LRA=${target.LRA}:TP=${target.TP}[out]`);\r\n        } else {\r\n          filterComplex.push(`[out0]acopy[out]`);\r\n        }\r\n      }\r\n\r\n      const args = [\r\n        '-y',\r\n        '-hide_banner', // 隐藏版本信息横幅\r\n        '-loglevel', 'error', // 只显示错误信息\r\n        ...filterInputs,\r\n        '-filter_complex', filterComplex.join(';'),\r\n        '-map', '[out]',\r\n        '-ac', '2', // 立体声\r\n        // 保留源采样率，避免 48kHz → 44.1kHz 重采样带来的高频损失和\"闷/慢\"感\r\n        outputPath,\r\n      ];\r\n\r\n      // 如果指定了总时长，限制输出时长\r\n      if (duration) {\r\n        args.splice(args.length - 1, 0, '-t', duration.toString());\r\n      }\r\n\r\n      try {\r\n        await execa('ffmpeg', args);\r\n        return outputPath;\r\n      } catch (error) {\r\n        console.warn('合并音频失败，尝试简单方式:', error.message);\r\n        if (processedAudios.length > 0) {\r\n          return processedAudios[0].path;\r\n        }\r\n        return null;\r\n      }\r\n    } catch (error) {\r\n      console.error('合并音频失败:', error);\r\n      return null;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * 对音频应用响度归一化（EBU R128 loudnorm）\r\n   * 默认目标适合短视频/自媒体；可选 preset: 'broadcast' (I=-23) | 'shortvideo' (I=-16) | 'podcast' (I=-19)\r\n   * @param {string} inputPath - 输入音频路径\r\n   * @param {Object} [options]\r\n   * @param {string} [options.outputPath] - 输出路径，不传则写到临时目录\r\n   * @param {string} [options.preset='shortvideo'] - 响度预设\r\n   * @param {boolean} [options.linear=false] - loudnorm 线性相位模式（true 会引入群延迟，听感\"闷/慢\"）\r\n   * @returns {Promise<string>} 处理后的音频路径\r\n   */\r\n  async normalizeLoudness(inputPath, options = {}) {\r\n    await this.checkFFmpeg();\r\n\r\n    const {\r\n      preset = 'shortvideo',\r\n      linear = false,  // 最小相位模式，无群延迟，听感更自然\r\n    } = options;\r\n    const target = {\r\n      broadcast:  { I: -23, LRA: 7,  TP: -2.0 },\r\n      shortvideo: { I: -16, LRA: 11, TP: -1.5 },\r\n      podcast:    { I: -19, LRA: 9,  TP: -2.0 },\r\n    }[preset] || { I: -16, LRA: 11, TP: -1.5 };\r\n\r\n    const outputPath = options.outputPath\r\n      || path.join(os.tmpdir(), `fknew-loudnorm-${nanoid()}.wav`);\r\n\r\n    // 探测源采样率，保持一致；不显式指定会让 WAV/pcm_s16le 默认输出 192kHz，\r\n    // 后续 AAC 编码又降到 96kHz，两次重采样是听感\"闷/慢\"的元凶\r\n    let sourceRate = 48000;\r\n    try {\r\n      const streams = await readFileStreams(inputPath);\r\n      const audioStream = streams.find(s => s.codec_type === 'audio');\r\n      if (audioStream && audioStream.sample_rate) {\r\n        sourceRate = parseInt(audioStream.sample_rate, 10) || 48000;\r\n      }\r\n    } catch (_) {}\r\n\r\n    const args = [\r\n      '-y',\r\n      '-hide_banner',\r\n      '-loglevel', 'error',\r\n      '-i', inputPath,\r\n      '-af', `loudnorm=I=${target.I}:LRA=${target.LRA}:TP=${target.TP}:linear=${linear ? 1 : 0}`,\r\n      '-ar', sourceRate.toString(),\r\n      outputPath,\r\n    ];\r\n\r\n    try {\r\n      await execa('ffmpeg', args);\r\n      return outputPath;\r\n    } catch (error) {\r\n      console.warn(`[FFmpeg] loudnorm 失败，降级使用原文件: ${error.message}`);\r\n      return inputPath;\r\n    }\r\n  }\r\n}\r\n\r\n"],"names":["DEFAULT_FFMPEG_CONFIG","nanoid","readFileStreams"],"mappings":"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"}