From 88a2c349f461ac6064353f365170502f93c6968c Mon Sep 17 00:00:00 2001 From: liucheng Date: Sat, 25 Jul 2026 14:55:23 +0800 Subject: [PATCH] =?UTF-8?q?fix(tts):=20=E6=9C=8D=E5=8A=A1=E7=AB=AF=20tts?= =?UTF-8?q?=5Fcache=20=E5=8E=BB=E9=87=8D,=E9=98=B2=E4=BC=A0=20null=20?= =?UTF-8?q?=E5=BC=BA=E5=88=B6=E9=87=8D=E5=90=88=E6=88=90=E5=88=B7=20TTS=20?= =?UTF-8?q?=E8=B4=A6=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 合成前先查 tts_cache 集合,命中则直接 getTempFileURL,不重复合成 - 合成后写 tts_cache,相同参数组合只合成一次 - 集合不存在时 catch 走原合成路径不崩(需在云开发控制台建 tts_cache 集合启用去重) Co-Authored-By: Claude --- cloudfunctions/tts/index.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/cloudfunctions/tts/index.js b/cloudfunctions/tts/index.js index 0cbe409..dc70be2 100644 --- a/cloudfunctions/tts/index.js +++ b/cloudfunctions/tts/index.js @@ -80,12 +80,23 @@ exports.main = async (event) => { // If the client passed a cached fileID, try to get a fresh temp URL // from it — this is the fast path (no synthesis, no upload). - if (fileID) { + const db = cloud.database() + const cacheKey = `${promptKey}-${voiceType || 'default'}-v${volume != null ? volume : 0}-s${speed != null ? speed : 0}` + + // 解析 fileID:优先 client 传入,否则查服务端 tts_cache,防 client 传 null 强制重合成(刷 TTS 账单) + let resolvedFileID = fileID || null + if (!resolvedFileID) { try { - const urlRes = await cloud.getTempFileURL({ fileList: [fileID] }) + const r = await db.collection('tts_cache').doc(cacheKey).get() + if (r.data && r.data.length && r.data[0].fileID) resolvedFileID = r.data[0].fileID + } catch (e) {} // 集合/文档不存在,走合成 + } + if (resolvedFileID) { + try { + const urlRes = await cloud.getTempFileURL({ fileList: [resolvedFileID] }) const url = urlRes.fileList[0].tempFileURL if (url) { - return { success: true, audioUrl: url, fileID, text, cached: true } + return { success: true, audioUrl: url, fileID: resolvedFileID, text, cached: true } } } catch (e) { // fileID stale or file deleted — fall through to re-synthesize @@ -101,6 +112,8 @@ exports.main = async (event) => { if (!url) { return { success: false, error: 'getTempFileURL returned empty URL', text } } + // 写服务端 tts_cache,下次相同参数直接命中,不重复合成 + try { await db.collection('tts_cache').doc(cacheKey).set({ data: { fileID: newFileID, updatedAt: db.serverDate() } }) } catch (e) {} return { success: true, audioUrl: url, fileID: newFileID, text, cached: false } } catch (e) { return { success: false, error: e.message, text }