{"version":3,"file":"subtitle-utils.cjs","sources":["../../../src/utils/subtitle-utils.js"],"sourcesContent":["/**\n * 字幕工具函数\n */\n\n/**\n * 计算混合中英文的语音时间\n * @param {string} text - 文本内容\n * @param {number} chineseSpeed - 中文速度（字符/分钟），默认 200\n * @param {number} englishSpeed - 英文速度（单词/分钟），默认 150\n * @returns {number} 总时间（秒）\n */\nexport function calculateSpeechTimeMixed(text, chineseSpeed = 200, englishSpeed = 150) {\n  if (!text || typeof text !== 'string') return 0;\n\n  // 统计中文字符数（Unicode中文范围）\n  const chineseChars = text.match(/[\\u4e00-\\u9fa5]/g) || [];\n  const chineseCount = chineseChars.length;\n\n  // 统计英文单词数（按空格分割，过滤空值）\n  const englishWords = text\n    .replace(/[\\u4e00-\\u9fa5]/g, ' ') // 移除中文以准确统计英文单词\n    .trim()\n    .split(/\\s+/)\n    .filter(word => word.length > 0);\n  const englishCount = englishWords.length;\n\n  // 计算两部分时间（秒）\n  const chineseTime = (chineseCount / chineseSpeed) * 60;\n  const englishTime = (englishCount / englishSpeed) * 60;\n\n  // 返回总时间（四舍五入）\n  return Math.round(chineseTime + englishTime);\n}\n\nconst SIGN = '_$_';\n\n/**\n * 检查是否正在分割英文单词\n */\nfunction isSplittingEnglishWord(text, position) {\n  if (position === 0 || position >= text.length) return false;\n  \n  const prevChar = text[position - 1];\n  const currChar = text[position];\n  \n  // 如果前后字符都是英文字母，说明正在分割单词\n  return /[a-zA-Z]/.test(prevChar) && /[a-zA-Z]/.test(currChar);\n}\n\n/**\n * 查找安全的分割点\n */\nfunction findSafeSplitPoint(text, start, proposedEnd, maxLength) {\n  let end = proposedEnd;\n  \n  // 方案1：向前查找空格或标点\n  for (let i = end - 1; i > start; i--) {\n    if (text[i] === ' ' || /[，。！？、,.;!?]/.test(text[i])) {\n      return i + 1; // 在空格或标点后分割\n    }\n  }\n  \n  // 方案2：向后查找空格或标点\n  for (let i = end; i < Math.min(text.length, end + 10); i++) {\n    if (text[i] === ' ' || /[，。！？、,.;!?]/.test(text[i])) {\n      return i + 1; // 在空格或标点后分割\n    }\n  }\n  \n  // 方案3：如果找不到合适位置，尽量完整包含单词\n  if (end < text.length) {\n    let wordEnd = end;\n    while (wordEnd < text.length && /[a-zA-Z]/.test(text[wordEnd])) {\n      wordEnd++;\n    }\n    \n    // 如果单词长度可控，尽量完整包含\n    if (wordEnd - start <= maxLength + 5) {\n      return wordEnd;\n    }\n  }\n  \n  // 最后手段：按原位置分割\n  return proposedEnd;\n}\n\n/**\n * 按标点符号和最大长度分割文本\n * @param {string} text - 文本内容\n * @param {number} maxLength - 每段最大字符数\n * @returns {Array<string>} 分割后的文本段落数组\n */\nfunction splitText(text, maxLength = 20) {\n  if (!text || typeof text !== 'string') return [];\n  \n  // 1. 去除多余的引号和换行符\n  text = text.replace(/[\"\"\"''\\n\\r]/g, '');\n  \n  // 2. 替换标点为 SIGN + 标点（标点后插入 SIGN）\n  const regexp = /([。？！,!;；，,])/g;\n  text = text.replace(regexp, `$1${SIGN}`); // 标点后加 SIGN\n  \n  // 3. 按 SIGN 分割，并过滤空字符串\n  let segments = text.split(SIGN).filter(seg => seg.trim());\n  \n  // 4. 处理长句子（超过 maxLength 的按字数分割），保护英文单词\n  segments = segments.flatMap(seg => {\n    if (seg.length <= maxLength) return seg;\n    \n    const chunks = [];\n    let start = 0;\n    \n    while (start < seg.length) {\n      let end = Math.min(start + maxLength, seg.length);\n      \n      // 避免在标点中间切断\n      if (end < seg.length && /[，。！？、,.;!?]/.test(seg[end])) {\n        end++;\n      }\n      // 避免分割英文单词\n      else if (end < seg.length && isSplittingEnglishWord(seg, end)) {\n        end = findSafeSplitPoint(seg, start, end, maxLength);\n      }\n      \n      chunks.push(seg.slice(start, end));\n      start = end;\n    }\n    \n    return chunks;\n  });\n  \n  return segments.filter(seg => seg.trim().length > 0);\n}\n\n/**\n * 同步文本段落时长与最小时长\n * @param {Array<string>} textSegments - 文本段落数组\n * @param {number} totalDuration - 总时长（秒）\n * @param {number} minDuration - 最小时长（秒），默认 0.2\n * @returns {Array<{text: string, duration: number}>} 带时长的段落数组\n */\nfunction syncDurationWithMinDuration(textSegments, totalDuration, minDuration = 0.2) {\n  if (!textSegments || textSegments.length === 0) return [];\n  \n  const totalChars = textSegments.join('').length;\n  if (totalChars === 0) return [];\n  \n  let remainingDuration = totalDuration;\n\n  // 先分配保底时长\n  const segments = textSegments.map(text => {\n    const duration = Math.max(\n      minDuration,\n      (text.length / totalChars) * totalDuration\n    );\n    remainingDuration -= duration;\n    return { text, duration };\n  });\n\n  // 如果剩余时间 > 0，按字数比例再分配\n  if (remainingDuration > 0) {\n    const extraPerChar = remainingDuration / totalChars;\n    segments.forEach(seg => {\n      seg.duration += seg.text.length * extraPerChar;\n    });\n  }\n\n  return segments;\n}\n\n/**\n * 计算文本容量\n * @param {number} screenWidth - 屏幕宽度（像素）\n * @param {number} fontSize - 字体大小（像素）\n * @param {string} text - 文本内容\n * @param {string} fontFamily - 字体族，默认 'PatuaOne'\n * @returns {Object} 包含最大字符数、平均字符宽度等信息\n */\nexport function calculateMixedTextCapacity(screenWidth, fontSize, text, fontFamily = 'PatuaOne') {\n  // 统计中英文比例\n  const chineseChars = text.match(/[\\u4e00-\\u9fa5]/g) || [];\n  const englishChars = text.match(/[a-zA-Z]/g) || [];\n  const otherChars = text.match(/[^\\u4e00-\\u9fa5a-zA-Z\\s]/g) || [];\n  \n  const totalChars = chineseChars.length + englishChars.length + otherChars.length;\n  if (totalChars === 0) {\n    return {\n      maxChars: 0,\n      avgCharWidth: fontSize,\n      chineseCount: 0,\n      englishCount: 0,\n      otherCount: 0,\n      chineseRatio: 0,\n      englishRatio: 0\n    };\n  }\n  \n  const chineseRatio = chineseChars.length / totalChars;\n  const englishRatio = englishChars.length / totalChars;\n  \n  // 不同字符的宽度系数\n  const chineseWidth = fontSize * 1.0;    // 中文字符宽度\n  const englishWidth = fontSize * 0.6;    // 英文字符宽度\n  const otherWidth = fontSize * 0.7;      // 其他字符宽度\n  \n  // 计算平均字符宽度\n  const avgCharWidth = (chineseWidth * chineseRatio) + \n                      (englishWidth * englishRatio) + \n                      (otherWidth * (1 - chineseRatio - englishRatio));\n  \n  const maxChars = Math.floor(screenWidth / avgCharWidth);\n  \n  return {\n    maxChars,\n    avgCharWidth,\n    chineseCount: chineseChars.length,\n    englishCount: englishChars.length,\n    otherCount: otherChars.length,\n    chineseRatio,\n    englishRatio\n  };\n}\n\n/**\n * 解析字幕文本，按标点符号和时长分割\n * @param {string} text - 文本内容\n * @param {number} duration - 总时长（秒），如果未指定则自动计算\n * @param {number} maxLength - 每段最大字符数，默认 20\n * @returns {Array<{text: string, duration: number}>} 带时长的段落数组\n */\nexport function parseSubtitles(text, duration, maxLength = 20) {\n  if (!text || typeof text !== 'string') return [];\n  \n  // 计算语音时间\n  const textListWithDuration = calculateSpeechTimeMixed(text);\n  \n  // 分割文本\n  const textList = splitText(text, maxLength);\n  \n  // 使用指定时长或计算出的时长\n  const finalDuration = duration || textListWithDuration;\n  \n  // 同步时长\n  return syncDurationWithMinDuration(textList, finalDuration);\n}\n\n"],"names":[],"mappings":"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"}