Commit 245f50d5 authored by Dazzle Wu's avatar Dazzle Wu

fix: 视频数字人位置、声音配置

parent 7c1f5846
<script setup lang="ts">
import { useDigitalCreationStore } from '@/store/modules/creation'
import { TimbreItem } from '@/store/types/creation'
import { computed, ref } from 'vue'
import { computed } from 'vue'
interface Props {
value?: TimbreItem
......@@ -11,19 +11,15 @@ interface Props {
interface Emits {
(e: 'click', value: TimbreItem): void
(e: 'toggle', value: boolean): void
(e: 'play', value: string): void
}
defineProps<Props>()
const emit = defineEmits<Emits>()
const digitalCreationStore = useDigitalCreationStore()
const digitalAudio = ref<HTMLAudioElement>()
const person = computed(() => digitalCreationStore.person)
function playAudio() {
digitalAudio.value?.play()
}
</script>
<template>
......@@ -39,7 +35,11 @@ function playAudio() {
<div class="flex-1 overflow-hidden">
<div class="mb-2 flex items-center gap-2">
<div class="max-w-32 truncate">{{ value?.name }}</div>
<CustomIcon class="cursor-pointer text-lg" icon="mingcute:volume-line" @click.stop.prevent="playAudio" />
<CustomIcon
class="cursor-pointer text-lg"
icon="mingcute:volume-line"
@click.stop.prevent="emit('play', value!.audioUrl)"
/>
</div>
<div class="flex gap-1">
<n-tag v-for="(style, index) in value?.style" :key="index" type="warning" size="tiny" round>{{ style }}</n-tag>
......@@ -49,6 +49,4 @@ function playAudio() {
<CustomIcon class="cursor-pointer text-lg" icon="ant-design:swap-outlined" @click="emit('toggle', true)" />
</div>
</div>
<audio ref="digitalAudio" :src="value?.audioUrl"></audio>
</template>
......@@ -2,9 +2,8 @@
import { fetchDigitalHumanTimbreList, fetchTimbreByExample } from '@/apis/digital-creation'
import { useAudioSettingStore } from '@/store/modules/audio-setting'
import { useDigitalCreationStore } from '@/store/modules/creation'
import { LangType, TimbreItem, VoiceType } from '@/store/types/creation'
import { computed, onMounted, ref, watch } from 'vue'
import { computed, nextTick, onMounted, ref, watch } from 'vue'
import DigitalAudioCard from './digital-audio-card.vue'
const audioSettingStore = useAudioSettingStore()
......@@ -36,8 +35,10 @@ const digitalTimbreValue = ref<TimbreItem>()
const digitalTimbreList = ref<TimbreItem[]>([])
const digitalTimbreFemaleList = ref<TimbreItem[]>([])
const digitalTimbreMaleList = ref<TimbreItem[]>([])
const showAll = ref(false)
const digitalAudio = ref<HTMLAudioElement>()
const audioSrc = ref('')
const searchName = ref('')
const showAll = ref(false)
const langType = computed({
get() {
......@@ -84,6 +85,7 @@ watch(
langType.value = LangType.MANDARIN
} else {
digitalTimbreValue.value = digitalTimbreList.value[0]
langType.value = LangType.CANTONESE
}
}
},
......@@ -93,13 +95,13 @@ watch(
() => langType.value,
(newVal) => {
if (newVal === LangType.CANTONESE) {
digitalCreationStore.setPerson('')
audioSettingStore.setVoiceType(VoiceType.CANTONESE_FEMALE)
} else {
if (digitalTimbreValue.value?.sex === '男') {
audioSettingStore.setVoiceType(VoiceType.MANDARIN_MALE)
} else {
audioSettingStore.setVoiceType(VoiceType.MANDARIN_FEMALE)
}
digitalCreationStore.setPerson(digitalTimbreValue.value?.timebreId || '')
audioSettingStore.setVoiceType(
digitalTimbreValue.value?.sex === '男' ? VoiceType.MANDARIN_MALE : VoiceType.MANDARIN_FEMALE,
)
}
},
)
......@@ -133,6 +135,14 @@ function handleClickAudioCard(timbreItem: TimbreItem) {
? audioSettingStore.setVoiceType(VoiceType.MANDARIN_MALE)
: audioSettingStore.setVoiceType(VoiceType.MANDARIN_FEMALE)
}
function playAudio(audioUrl: string) {
audioSrc.value && digitalAudio.value?.pause()
audioSrc.value = audioUrl
nextTick(() => {
digitalAudio.value?.play()
})
}
</script>
<template>
......@@ -153,6 +163,7 @@ function handleClickAudioCard(timbreItem: TimbreItem) {
:value="digitalTimbreValue"
show-toggle
@toggle="showAll = true"
@play="playAudio"
/>
<div class="mt-4 text-lg">聲音</div>
......@@ -198,8 +209,11 @@ function handleClickAudioCard(timbreItem: TimbreItem) {
:key="index"
:value="timbre"
@click="handleClickAudioCard"
@play="playAudio"
/>
</div>
</div>
<audio ref="digitalAudio" :src="audioSrc"></audio>
</div>
</template>
......@@ -43,18 +43,8 @@ const resizeObserver = new ResizeObserver((entries) => {
const isLandscape = computed(() => digitalCreationStore.width > digitalCreationStore.height)
const digitalHumanWidth = ref(0)
// const digitalHumanWidth = computed(
// () => (digitalCreationStore.w * previewContentWidth.value) / (isLandscape.value ? 1920 : 1080),
// )
const digitalHumanHeight = computed(
() => (digitalCreationStore.h * previewContentHeight.value) / (isLandscape.value ? 1080 : 1920),
)
const digitalHumanLeft = computed(
() =>
(digitalCreationStore.x * previewContentWidth.value) / (isLandscape.value ? 1920 : 1080) +
previewContentWidth.value / 2 -
digitalHumanWidth.value / 2,
() => (digitalCreationStore.x * previewContentWidth.value) / (isLandscape.value ? 1920 : 1080),
)
const digitalHumanTop = computed(
() => (digitalCreationStore.y * previewContentHeight.value) / (isLandscape.value ? 1080 : 1920),
......@@ -77,10 +67,6 @@ onUnmounted(() => {
previewContent.value && resizeObserver.unobserve(previewContent.value)
})
function getDigitalHumanWidth() {
digitalHumanWidth.value = digitalHumanImage.value?.width || 0
}
function connectWebSocket() {
websocket = new WebSocket(url)
websocket.onopen = () => {
......@@ -167,14 +153,11 @@ function controlAudio() {
v-if="digitalCreationStore.inputImageUrl"
ref="digitalHumanImage"
:src="digitalCreationStore.inputImageUrl"
class="absolute max-w-none object-cover"
class="absolute h-full max-w-none -translate-x-1/2 object-cover"
:style="{
// width: `${digitalHumanWidth}px`,
height: `${digitalHumanHeight}px`,
left: `${digitalHumanLeft}px`,
left: `calc(50% + ${digitalHumanLeft}px)`,
top: `${digitalHumanTop}px`,
}"
@load="getDigitalHumanWidth"
/>
</div>
</div>
......
......@@ -106,7 +106,7 @@ async function saveDraft(autoSave: boolean = true) {
const res = await saveDraftConfig<DraftConfig>(payload)
if (res.code === 0) {
autoSave ? (autoSaveSuccess.value = true) : window.$message.success('保存成功')
digitalCreationStore.updateDigitalCreation(res.data)
// digitalCreationStore.updateDigitalCreation(res.data)
const temp: DraftConfig = { ...res.data, modifiedTime: '' }
savedConfig.value = temp
}
......@@ -125,7 +125,7 @@ function confirmExport() {
window.$message.error('請輸入視頻名稱')
return false
}
if (!userCurrency.value) {
if (userCurrency.value < consumption.value) {
window.$message.error('餘額不足')
return false
}
......
......@@ -2,8 +2,9 @@
import { fetchDraftConfigById } from '@/apis/digital-creation'
import { fetchGetTaskConfig } from '@/apis/opus'
import { fetchDigitalHumanTemplateStatus } from '@/apis/template'
import { useAudioSettingStore } from '@/store/modules/audio-setting'
import { useDigitalCreationStore } from '@/store/modules/creation'
import { DraftConfig, ScreenType } from '@/store/types/creation'
import { DraftConfig, LangType, ScreenType, VoiceType } from '@/store/types/creation'
import { DigitalTemplate } from '@/store/types/template'
import { formatDateTime } from '@/utils/date-formatter'
import { onMounted } from 'vue'
......@@ -19,6 +20,7 @@ interface Props {
const props = defineProps<Props>()
const audioSettingStore = useAudioSettingStore()
const digitalCreationStore = useDigitalCreationStore()
onMounted(() => {
......@@ -77,6 +79,8 @@ async function getDigitalTemplate(id: string) {
pronunciationLanguage: digitalCreationStore.pronunciationLanguage,
}
digitalCreationStore.updateDigitalCreation(draftConfig)
audioSettingStore.setLanType(draftConfig.person ? LangType.MANDARIN : LangType.CANTONESE)
audioSettingStore.setVoiceType(draftConfig.person ? VoiceType.MANDARIN_FEMALE : VoiceType.CANTONESE_FEMALE)
}
}
......@@ -84,6 +88,8 @@ async function getDraft(id: string) {
const res = await fetchDraftConfigById<DraftConfig>(id)
if (res.code === 0) {
digitalCreationStore.updateDigitalCreation(res.data)
audioSettingStore.setLanType(res.data.person ? LangType.MANDARIN : LangType.CANTONESE)
audioSettingStore.setVoiceType(res.data.person ? VoiceType.MANDARIN_FEMALE : VoiceType.CANTONESE_FEMALE)
}
}
......@@ -124,6 +130,8 @@ async function getTaskConfig(id: string) {
pronunciationLanguage: res.data.pronunciationLanguage || digitalCreationStore.pronunciationLanguage,
}
digitalCreationStore.updateDigitalCreation(draftConfig)
audioSettingStore.setLanType(draftConfig.person ? LangType.MANDARIN : LangType.CANTONESE)
audioSettingStore.setVoiceType(draftConfig.person ? VoiceType.MANDARIN_FEMALE : VoiceType.CANTONESE_FEMALE)
}
}
</script>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment