{"version":3,"file":"video-utils.cjs","sources":["../../../src/utils/video-utils.js"],"sourcesContent":["import { Transform } from \"stream\";\r\nimport execa from 'execa';\r\n\r\n/**\r\n * 视频处理工具函数\r\n */\r\n\r\n/**\r\n * 获取视频时长，并根据 cutFrom/cutTo 返回有效区间\r\n */\r\nexport async function getVideoDuration(filePath, options = {}) {\r\n  const { cutFrom = 0, cutTo } = options;\r\n\r\n  const { stdout } = await execa('ffprobe', [\r\n    '-v', 'error',\r\n    '-show_entries', 'format=duration',\r\n    '-of', 'default=noprint_wrappers=1:nokey=1',\r\n    filePath,\r\n  ]);\r\n\r\n  const rawDuration = parseFloat(stdout.trim());\r\n  if (!Number.isFinite(rawDuration)) {\r\n    return { rawDuration: 0, effectiveDuration: 0 };\r\n  }\r\n\r\n  const start = Math.max(0, cutFrom);\r\n  const end = cutTo !== undefined ? Math.min(cutTo, rawDuration) : rawDuration;\r\n  const effectiveDuration = Math.max(0, end - start);\r\n\r\n  return { rawDuration, effectiveDuration };\r\n}\r\n\r\n/**\r\n * 将原始视频流转换为单独的帧\r\n * @param {Object} options - 选项\r\n * @param {number} options.width - 帧宽度\r\n * @param {number} options.height - 帧高度\r\n * @param {number} options.channels - 通道数（通常为4，RGBA）\r\n * @returns {Transform} 转换流\r\n */\r\nexport function rawVideoToFrames({ width, height, channels, signal, ...options }) {\r\n  const frameByteSize = width * height * channels;\r\n  let buffer = new Uint8Array(frameByteSize);\r\n  let bytesRead = 0;\r\n  \r\n  return new Transform({\r\n    ...options,\r\n    writableObjectMode: false,\r\n    readableObjectMode: true,\r\n    // 设置较大的 highWaterMark 以避免缓冲区溢出\r\n    highWaterMark: Math.round(frameByteSize * 5), // 缓冲 10 帧\r\n    transform(chunk, _, callback) {\r\n      try {\r\n        let startAt = 0;\r\n        // 在块中查找帧\r\n        while (startAt < chunk.length) {\r\n          const endAt = Math.min(startAt + frameByteSize - bytesRead, chunk.length);\r\n          const bytesToRead = endAt - startAt;\r\n          buffer.set(chunk.slice(startAt, endAt), bytesRead);\r\n          bytesRead = (bytesRead + bytesToRead) % frameByteSize;\r\n          \r\n          if (bytesRead === 0) {\r\n            // 发出帧\r\n            const frame = Buffer.from(buffer);\r\n            this.push(frame);\r\n            // 重置数据缓冲区\r\n            buffer = new Uint8Array(frameByteSize);\r\n          }\r\n          // 移动到下一帧\r\n          startAt = endAt;\r\n        }\r\n        callback();\r\n      } catch (err) {\r\n        callback(err);\r\n      }\r\n    },\r\n    flush(callback) {\r\n      // 如果还有未完成的帧数据，尝试处理它\r\n      if (bytesRead > 0) {\r\n        // 如果数据量超过 90% 帧大小，补齐并发出（可能是最后一帧）\r\n        if (bytesRead >= frameByteSize * 0.9) {\r\n          // 用零补齐到完整帧大小\r\n          const paddedBuffer = new Uint8Array(frameByteSize);\r\n          paddedBuffer.set(buffer.subarray(0, bytesRead), 0);\r\n          const frame = Buffer.from(paddedBuffer);\r\n          this.push(frame);\r\n        } else {\r\n          // 数据量太少，可能是流提前结束，记录警告\r\n          console.warn(`[rawVideoToFrames] 流结束时还有 ${bytesRead}/${frameByteSize} 字节未完成，可能丢失最后一帧`);\r\n        }\r\n      }\r\n      callback();\r\n    },\r\n  });\r\n}\r\n\r\n/**\r\n * 计算视频缩放参数\r\n * @param {Object} options - 选项\r\n * @param {number} options.inputWidth - 输入宽度\r\n * @param {number} options.inputHeight - 输入高度\r\n * @param {number} options.requestedWidth - 请求宽度\r\n * @param {number} options.requestedHeight - 请求高度\r\n * @param {string} options.resizeMode - 调整模式\r\n * @returns {Object} 缩放参数\r\n */\r\nexport function calculateVideoScale({ inputWidth, inputHeight, requestedWidth, requestedHeight, resizeMode = 'contain' }) {\r\n  const inputAspectRatio = inputWidth / inputHeight;\r\n  const canvasAspectRatio = requestedWidth / requestedHeight;\r\n  \r\n  let targetWidth = requestedWidth;\r\n  let targetHeight = requestedHeight;\r\n  let scaleFilter;\r\n  \r\n  switch (resizeMode) {\r\n    case 'contain':\r\n    case 'contain-blur':\r\n      if (canvasAspectRatio > inputAspectRatio) {\r\n        targetHeight = requestedHeight;\r\n        targetWidth = Math.round(requestedHeight * inputAspectRatio);\r\n      } else {\r\n        targetWidth = requestedWidth;\r\n        targetHeight = Math.round(requestedWidth / inputAspectRatio);\r\n      }\r\n      scaleFilter = `scale=${targetWidth}:${targetHeight}`;\r\n      break;\r\n      \r\n    case 'cover':\r\n      let scaledWidth, scaledHeight;\r\n      if (canvasAspectRatio > inputAspectRatio) {\r\n        scaledWidth = requestedWidth;\r\n        scaledHeight = Math.round(requestedWidth / inputAspectRatio);\r\n      } else {\r\n        scaledHeight = requestedHeight;\r\n        scaledWidth = Math.round(requestedHeight * inputAspectRatio);\r\n      }\r\n      scaleFilter = `scale=${scaledWidth}:${scaledHeight},crop=${requestedWidth}:${requestedHeight}`;\r\n      break;\r\n      \r\n    case 'fill':\r\n    case 'stretch':\r\n      scaleFilter = `scale=${requestedWidth}:${requestedHeight}`;\r\n      break;\r\n      \r\n    case 'scale-down':\r\n      if (inputWidth > requestedWidth || inputHeight > requestedHeight) {\r\n        if (canvasAspectRatio > inputAspectRatio) {\r\n          targetHeight = requestedHeight;\r\n          targetWidth = Math.round(requestedHeight * inputAspectRatio);\r\n        } else {\r\n          targetWidth = requestedWidth;\r\n          targetHeight = Math.round(requestedWidth / inputAspectRatio);\r\n        }\r\n        scaleFilter = `scale=${targetWidth}:${targetHeight}`;\r\n      } else {\r\n        targetWidth = inputWidth;\r\n        targetHeight = inputHeight;\r\n        scaleFilter = `scale=${targetWidth}:${targetHeight}`;\r\n      }\r\n      break;\r\n      \r\n    default:\r\n      scaleFilter = `scale=${requestedWidth}:${requestedHeight}`;\r\n  }\r\n  \r\n  return {\r\n    targetWidth,\r\n    targetHeight,\r\n    scaleFilter\r\n  };\r\n}\r\n\r\n/**\r\n * 获取视频输入编解码器\r\n * @param {string} codecName - 编解码器名称\r\n * @returns {string|null} 输入编解码器\r\n */\r\nexport function getInputCodec(codecName) {\r\n  switch (codecName) {\r\n    case 'vp8':\r\n      return 'libvpx';\r\n    case 'vp9':\r\n      return 'libvpx-vp9';\r\n    default:\r\n      return null;\r\n  }\r\n}\r\n\r\n/**\r\n * 构建 FFmpeg 视频处理参数\r\n * @param {Object} options - 选项\r\n * @returns {Array} FFmpeg 参数数组\r\n */\r\nexport function buildVideoFFmpegArgs({\r\n  inputPath,\r\n  inputCodec,\r\n  cutFrom,\r\n  cutTo,\r\n  speedFactor = 1,\r\n  framerate,\r\n  scaleFilter,\r\n  outputFormat = 'rawvideo',\r\n  mute = true,\r\n  volume = 1\r\n}) {\r\n  // 计算实际提取时长\r\n  // cutTo 是绝对时间，cutFrom 也是绝对时间\r\n  // 所以提取时长 = cutTo - cutFrom（不考虑 speedFactor，因为 speedFactor 只影响播放速度，不影响提取时长）\r\n  const extractDuration = cutTo && cutFrom !== undefined \r\n    ? (cutTo - cutFrom) \r\n    : (cutTo || undefined);\r\n  \r\n  // FFmpeg 参数顺序很重要：\r\n  // 1. 输入定位：-ss 在 -i 之后（精度更高，确保帧数准确）\r\n  // 2. 输出时长：-t 在 -i 之后（限制输出时长）\r\n  // 3. 如果目标帧率与输入帧率相同，可以不使用 fps 滤镜（避免重新采样导致的帧数不准确）\r\n  // 4. 但对于 rawvideo 输出，必须使用 fps 滤镜或 -r 参数来确保帧率\r\n  \r\n  const args = [\r\n    '-nostdin',\r\n    '-hide_banner', // 隐藏版本信息横幅\r\n    '-loglevel', 'error', // 只显示错误信息\r\n    ...(inputCodec ? ['-vcodec', inputCodec] : []),\r\n    '-i', inputPath,\r\n    // 输入定位：-ss 在 -i 之后（精度更高，确保帧数准确）\r\n    ...(cutFrom ? ['-ss', cutFrom.toString()] : []),\r\n    // 输出时长：-t 在 -i 之后（限制输出时长）\r\n    ...(extractDuration ? ['-t', extractDuration.toString()] : []),\r\n    // 视频滤镜：先应用速度调整，再应用帧率和缩放\r\n    '-vf', `${speedFactor !== 1 ? `setpts=${1/speedFactor}*PTS,` : ''}fps=${framerate},${scaleFilter}`,\r\n    // 输出帧率：确保输出帧率准确\r\n    '-r', framerate.toString(),\r\n    '-map', 'v:0',\r\n    '-vcodec', 'rawvideo',\r\n    '-pix_fmt', 'rgba',\r\n    '-f', outputFormat,\r\n    '-'\r\n  ];\r\n  \r\n  return args;\r\n}\r\n\r\n/**\r\n * 读取文件流信息（使用 ffprobe）\r\n * @param {string} filePath - 文件路径\r\n * @returns {Promise<Array>} 流信息数组\r\n */\r\nexport async function readFileStreams(filePath) {\r\n  try {\r\n    const { stdout } = await execa('ffprobe', [\r\n      '-v', 'error',\r\n      '-show_streams',\r\n      '-of', 'json',\r\n      filePath\r\n    ]);\r\n    \r\n    const data = JSON.parse(stdout);\r\n    return data.streams || [];\r\n  } catch (error) {\r\n    throw new Error(`Failed to read file streams: ${error.message}`);\r\n  }\r\n}\r\n\r\n/**\r\n * 创建音频流处理器（从视频中提取音频）\r\n * @param {Object} config - 配置\r\n * @param {string} config.source - 视频文件路径\r\n * @param {number} config.cutFrom - 开始时间（秒）\r\n * @param {number} config.cutTo - 结束时间（秒）\r\n * @param {number} config.speedFactor - 播放速度倍数\r\n * @param {number} config.volume - 音量\r\n * @param {string} config.outputDir - 输出目录\r\n * @returns {Promise<Object|null>} 音频流处理器，如果没有音频流则返回 null\r\n */\r\nexport async function createAudioStream({\r\n  source,\r\n  cutFrom,\r\n  cutTo,\r\n  speedFactor = 1,\r\n  volume = 1,\r\n  outputDir = './output',\r\n  // 兼容旧参数但不再使用：响度归一化统一在 mergeAudios 单点处理，避免双重压缩导致闷/慢\r\n  loudnessNormalization = false,\r\n  loudnessPreset = 'shortvideo',\r\n}) {\r\n  // 首先检查输入文件是否有音频流\r\n  const streams = await readFileStreams(source);\r\n  const hasAudioStream = streams.some(s => s.codec_type === 'audio');\r\n  \r\n  // 如果没有音频流，返回 null\r\n  if (!hasAudioStream) {\r\n    return null;\r\n  }\r\n  \r\n  const fs = await import('fs-extra');\r\n  const path = await import('path');\r\n  const { nanoid } = await import('nanoid');\r\n  \r\n  // 确保输出目录存在\r\n  await fs.ensureDir(outputDir);\r\n  \r\n  // 生成临时音频文件路径\r\n  const tempAudioPath = path.join(outputDir, `temp-video-audio-${nanoid()}.flac`);\r\n  \r\n  // 仅做裁剪和音量调整，不在此处做响度归一化（统一在 mergeAudios 中处理）\r\n  // 这样可以避免\"双重 loudnorm\"导致的瞬态损失和听感闷/慢\r\n  // 不强制重采样，保留源采样率，避免重采样带来的高频损失\r\n  let filterComplex = volume !== 1 ? `[0:a]volume=${volume}[aout]` : '[0:a]acopy[aout]';\r\n  \r\n  // 计算实际裁剪时长\r\n  let duration = undefined;\r\n  if (cutFrom !== undefined && cutTo !== undefined) {\r\n    duration = (cutTo - cutFrom) / speedFactor;\r\n  } else if (cutTo !== undefined) {\r\n    duration = cutTo / speedFactor;\r\n  } else if (cutFrom !== undefined) {\r\n    // 如果只指定了开始时间，需要获取视频总时长\r\n    const videoStream = streams.find(s => s.codec_type === 'video');\r\n    if (videoStream && videoStream.duration) {\r\n      duration = (parseFloat(videoStream.duration) - cutFrom) / speedFactor;\r\n    }\r\n  }\r\n  \r\n  const args = [\r\n    '-nostdin',\r\n    '-hide_banner', // 隐藏版本信息横幅\r\n    '-loglevel', 'error', // 只显示错误信息\r\n    ...(cutFrom ? ['-ss', cutFrom.toString()] : []),\r\n    '-i', source,\r\n    ...(duration ? ['-t', duration.toString()] : []),\r\n    '-filter_complex', filterComplex,\r\n    '-map', '[aout]',\r\n    '-c:a', 'flac',\r\n    '-y', tempAudioPath\r\n  ];\r\n  \r\n  const controller = new AbortController();\r\n  \r\n  // 检测是否在 Worker 线程中\r\n  // Worker 线程中的 process.stderr 是 WritableWorkerStdio，不能直接传递给 execa\r\n  let isWorkerThread = false;\r\n  try {\r\n    // 方法1: 检查 WorkerGlobalScope\r\n    if (typeof WorkerGlobalScope !== 'undefined' && typeof self !== 'undefined' && self instanceof WorkerGlobalScope) {\r\n      isWorkerThread = true;\r\n    }\r\n    // 方法2: 检查 process.stderr 的类型\r\n    else if (process.stderr && typeof process.stderr === 'object') {\r\n      // Worker 线程中的 process.stderr 是 WritableWorkerStdio\r\n      const stderrType = process.stderr.constructor?.name || '';\r\n      if (stderrType === 'WritableWorkerStdio' || (process.stderr._writableState && !process.stderr.isTTY)) {\r\n        isWorkerThread = true;\r\n      }\r\n    }\r\n  } catch (e) {\r\n    // 如果检测失败，默认不在 Worker 线程中\r\n    isWorkerThread = false;\r\n  }\r\n  \r\n  const stderrOption = isWorkerThread ? 'pipe' : process.stderr;\r\n  \r\n  try {\r\n    const ps = execa('ffmpeg', args, {\r\n      encoding: 'buffer',\r\n      buffer: false,\r\n      stdin: 'ignore',\r\n      stdout: 'pipe',\r\n      stderr: stderrOption,\r\n      cancelSignal: controller.signal\r\n    });\r\n    \r\n    // 处理错误\r\n    ps.catch((err) => {\r\n      if (!err.isCanceled) {\r\n        console.error('视频音频提取失败:', err);\r\n      }\r\n    });\r\n    \r\n    // 等待音频处理完成\r\n    await ps;\r\n    \r\n    return {\r\n      path: tempAudioPath,\r\n      controller,\r\n      async close() {\r\n        if (!ps.exitCode) {\r\n          controller.abort();\r\n        }\r\n        // 清理临时文件\r\n        try {\r\n          await fs.unlink(tempAudioPath);\r\n        } catch (error) {\r\n          // 忽略文件删除错误\r\n        }\r\n      }\r\n    };\r\n  } catch (error) {\r\n    console.error('视频音频提取失败:', error);\r\n    return null;\r\n  }\r\n}\r\n\r\n"],"names":["Transform"],"mappings":"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"}