Просмотр исходного кода

fix: LRC歌词时间戳为TTS停顿预留时间,解决歌词快于音频的问题

MyFramework User 3 месяцев назад
Родитель
Сommit
19e82763d8
1 измененных файлов с 20 добавлено и 3 удалено
  1. 20 3
      server/src/modules/tts/tts.service.ts

+ 20 - 3
server/src/modules/tts/tts.service.ts

@@ -843,9 +843,26 @@ export function generateLrc(text: string, duration: number, audioPath?: string):
     const totalChars = sentences.reduce((sum, s) => sum + countVisible(s), 0);
     if (totalChars === 0) return '';
 
-    // 核心:均匀语速 = 总时长 / 总字数
-    const speechRate = duration / totalChars; // 秒/字
-    ttsLogger.lrc(`语速: ${speechRate.toFixed(3)}s/字, 总字数=${totalChars}`);
+    // 计算句间停顿(TTS 引擎在句号、换行等位置天然有停顿)
+    // 句间停顿: 0.25s/句, 段落间停顿: 0.6s/段
+    let totalPause = 0;
+    for (let i = 0; i < sentences.length - 1; i++) {
+      const thisSentence = sentences[i].trim();
+      const nextSentence = sentences[i + 1].trim();
+      // 段落间:当前句以空行结尾,或下一句是标题
+      if (!thisSentence || !nextSentence || /^#{1,3}\s/.test(nextSentence)) {
+        totalPause += 0.6;
+      } else {
+        totalPause += 0.25;
+      }
+    }
+    // 末尾停顿
+    totalPause += 0.5;
+
+    // 有效朗读时长 = 总时长 - 停顿时间(至少保留 70% 给朗读)
+    const speechDuration = Math.max(duration * 0.7, duration - totalPause);
+    const speechRate = speechDuration / totalChars; // 秒/字
+    ttsLogger.lrc(`语速: ${speechRate.toFixed(3)}s/字, 总字数=${totalChars}, 停顿=${totalPause.toFixed(1)}s, 有效朗读=${speechDuration.toFixed(1)}s`);
 
     const lines: string[] = [];
     let currentTime = 0;