feat: 功能

This commit is contained in:
2025-12-28 13:49:45 +08:00
parent 36195ea55a
commit bbf8093ca3
25 changed files with 1046 additions and 1970 deletions

View File

@@ -9,20 +9,16 @@ import type {
UseVoiceGeneration,
AudioState,
VoiceMeta,
IdentifyState,
AudioData,
} from '../types/identify-face'
// @ts-ignore
import { VoiceService } from '@/api/voice'
/**
* 语音生成 Hook
* @param identifyState 人脸识别状态(来自父 Hook
* @param faceDuration 人脸出现时长(毫秒)
* 独立管理所有状态,不依赖外部状态
*/
export function useVoiceGeneration(
identifyState: IdentifyState,
faceDuration: number
): UseVoiceGeneration {
export function useVoiceGeneration(): UseVoiceGeneration {
// ==================== 响应式状态 ====================
const ttsText = ref<string>('')
@@ -43,17 +39,16 @@ export function useVoiceGeneration(
const canGenerateAudio = computed(() => {
const hasText = ttsText.value.trim()
const hasVoice = selectedVoiceMeta.value
const hasVideo = identifyState.identified
const hasVideo = true // 语音生成不依赖视频状态
return !!(hasText && hasVoice && hasVideo && !audioState.value.generating)
})
/**
* 建议的最大字符数
* 建议的最大字符数(需要从外部传入)
*/
const suggestedMaxChars = computed(() => {
const durationSec = faceDuration / 1000
const adjustedRate = speechRate.value || 1.0
return Math.floor(durationSec * 3.5 * adjustedRate)
// 默认为 4000需要从外部设置
return 4000
})
// ==================== 核心方法 ====================
@@ -156,31 +151,33 @@ export function useVoiceGeneration(
}
/**
* 验证音频与人脸区间的重合时长
* 验证音频与人脸区间的重合时长(外部调用时传入校验参数)
*/
const validateAudioDuration = (): boolean => {
if (!identifyState.identified || faceDuration <= 0) {
const validateAudioDuration = (
faceStartTime: number = 0,
faceEndTime: number = 0,
minOverlapMs: number = 2000
): boolean => {
if (faceStartTime <= 0 || faceEndTime <= 0) {
audioState.value.validationPassed = false
return false
}
const faceStart = identifyState.faceStartTime
const faceEnd = identifyState.faceEndTime
const faceDurationMs = faceEnd - faceStart
const faceDurationMs = faceEndTime - faceStartTime
const audioDuration = audioState.value.durationMs
const overlapStart = faceStart
const overlapEnd = Math.min(faceEnd, faceStart + audioDuration)
const overlapStart = faceStartTime
const overlapEnd = Math.min(faceEndTime, faceStartTime + audioDuration)
const overlapDuration = Math.max(0, overlapEnd - overlapStart)
const isValid = overlapDuration >= 2000
const isValid = overlapDuration >= minOverlapMs
audioState.value.validationPassed = isValid
if (!isValid) {
const overlapSec = (overlapDuration / 1000).toFixed(1)
message.warning(
`音频时长(${(audioDuration/1000).toFixed(1)}秒)与人脸区间(${(faceDurationMs/1000).toFixed(1)}秒)不匹配,重合部分仅${overlapSec}秒,至少需要2`
`音频时长(${(audioDuration/1000).toFixed(1)}秒)与人脸区间(${(faceDurationMs/1000).toFixed(1)}秒)不匹配,重合部分仅${overlapSec}秒,至少需要${(minOverlapMs/1000)}`
)
} else {
message.success('时长校验通过!')