|
|
@@ -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;
|