feat: 功能
This commit is contained in:
@@ -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('时长校验通过!')
|
||||
|
||||
Reference in New Issue
Block a user