From 63cbc101180469abcaca4d3093fdf413fbb3cd0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E9=B1=BC=E5=BC=80=E5=8F=91?= Date: Wed, 13 May 2026 17:31:12 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=BB=9F=E4=B8=80=E9=A2=84=E8=AE=A1?= =?UTF-8?q?=E6=96=87=E6=A1=88=EF=BC=8CTTS=E9=A2=84=E8=AE=A1=E7=A7=AF?= =?UTF-8?q?=E5=88=86=E6=81=A2=E5=A4=8D=C2=B11=E7=A7=AF=E5=88=86=E8=8C=83?= =?UTF-8?q?=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tauri-app/src/hooks/usePointsCheck.tsx | 4 ++-- .../src/pages/VideoCreation/VoiceSynthesis.tsx | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/tauri-app/src/hooks/usePointsCheck.tsx b/tauri-app/src/hooks/usePointsCheck.tsx index 4638ebc..d2317f4 100644 --- a/tauri-app/src/hooks/usePointsCheck.tsx +++ b/tauri-app/src/hooks/usePointsCheck.tsx @@ -47,7 +47,7 @@ export function usePointsCheck() { await fetchBalance(); const balance = usePointStore.getState().balance; if (balance < points) { - setModalDescription(`预估消耗 ${points} 积分,当前余额 ${balance} 积分`); + setModalDescription(`预计消耗 ${points} 积分,当前余额 ${balance} 积分`); setShowPointsModal(true); return false; } @@ -67,7 +67,7 @@ export function usePointsCheck() { (error: unknown, _bizName: string, _requiredPoints?: number): boolean => { const msg = error instanceof Error ? error.message : String(error); if (msg.includes('402') || msg.includes('积分不足')) { - setModalDescription(`预估消耗 ${_requiredPoints || '?'} 积分`); + setModalDescription(`预计消耗 ${_requiredPoints || '?'} 积分`); setShowPointsModal(true); return true; } diff --git a/tauri-app/src/pages/VideoCreation/VoiceSynthesis.tsx b/tauri-app/src/pages/VideoCreation/VoiceSynthesis.tsx index f010740..c88821e 100644 --- a/tauri-app/src/pages/VideoCreation/VoiceSynthesis.tsx +++ b/tauri-app/src/pages/VideoCreation/VoiceSynthesis.tsx @@ -79,7 +79,7 @@ export default function VoiceSynthesis() { // 加上镜头切换停顿(segment↔empty_shot: 0.5s,同类型: 0.3s),每 5 秒 1 积分,最低 1 积分 const estimatedTtsPoints = useMemo(() => { const validSegments = segments.filter(s => s.voiceover?.trim()); - if (validSegments.length === 0) return 0; + if (validSegments.length === 0) return { min: 0, max: 0 }; // 纯朗读时间 const totalChars = validSegments.reduce((sum, s) => sum + s.voiceover!.trim().length, 0); @@ -98,7 +98,11 @@ export default function VoiceSynthesis() { } const totalSeconds = speechSeconds + pauseSeconds; - return Math.max(1, Math.ceil(totalSeconds / 5)); + const base = Math.max(1, Math.ceil(totalSeconds / 5)); + // 范围:±1 积分,覆盖取整误差和语速波动 + const min = Math.max(1, base - 1); + const max = base + 1; + return { min, max }; }, [segments, speed]); const handlePlayPause = useCallback((voiceId: string, url: string | null, e: React.MouseEvent) => { @@ -299,7 +303,7 @@ export default function VoiceSynthesis() { if (!currentVoiceId) { toast.warning('请先选择音色'); setIsGenerating(false); return; } // 前置积分检查 - const ok = await checkBalance(estimatedTtsPoints, '配音合成'); + const ok = await checkBalance(estimatedTtsPoints.max, '配音合成'); if (!ok) return; const progress = useProgressStore.getState(); @@ -353,9 +357,9 @@ export default function VoiceSynthesis() { // 生成完成后自动执行打轴+截取 await handleAlignAndClip(qiniuUrl, meta.filePath); - progress.success('配音合成完成', result.consumedPoints || estimatedTtsPoints); + progress.success('配音合成完成', result.consumedPoints); } catch (err) { - if (handleError(err, '配音合成', estimatedTtsPoints)) { + if (handleError(err, '配音合成', estimatedTtsPoints.max)) { progress.hide(); return; } @@ -526,12 +530,12 @@ export default function VoiceSynthesis() {
{!hasGeneratedAudio ? ( ) : (