Commit a6f49c92 authored by Dazzle Wu's avatar Dazzle Wu

chore: 视频草稿参数调整

parent fab78130
import { AudioConfig, LanType, VoiceType } from '@/store/types/creation'
import { AudioConfig, LangType, VoiceType } from '@/store/types/creation'
import { defineStore } from 'pinia'
function defaultAudioSetting(): AudioConfig {
return {
lanType: LanType.CANTONESE,
langType: LangType.CANTONESE,
voiceType: VoiceType.CANTONESE_FEMALE,
}
}
......@@ -16,8 +16,8 @@ export const useAudioSettingStore = defineStore('audio-setting-store', {
state: (): AudioConfig => getLocalState(),
actions: {
setLanType(lanType: LanType) {
this.lanType = lanType
setLanType(langType: LangType) {
this.langType = langType
},
setVoiceType(voiceType: VoiceType) {
......
import { DraftConfig, DriveType, TaskType } from '@/store/types/creation'
import { DraftConfig, DriveType, LangType, TaskType } from '@/store/types/creation'
import { defineStore } from 'pinia'
function defaultDigitalCreation(): DraftConfig {
......@@ -37,6 +37,7 @@ function defaultDigitalCreation(): DraftConfig {
logoUrl: null,
bgmUrl: null,
materialUrl: null,
pronunciationLanguageL: LangType.CANTONESE,
}
}
......@@ -72,10 +73,22 @@ export const useDigitalCreationStore = defineStore('digital-creation-store', {
this.speed = speed
},
setVolume(volume: string) {
this.volume = volume
},
setPitch(pitch: string) {
this.pitch = pitch
},
setWidth(width: number) {
this.width = width
},
setHeight(height: number) {
this.height = height
},
setX(x: number) {
this.x = x
},
......
......@@ -15,9 +15,9 @@ export enum DriveType {
VOICE = 'VOICE',
}
export enum LanType {
CANTONESE,
MANDARIN,
export enum LangType {
CANTONESE = 'CANTONESE',
MANDARIN = 'MANDARIN',
}
export enum VoiceType {
......@@ -27,7 +27,7 @@ export enum VoiceType {
}
export interface AudioConfig {
lanType: LanType
langType: LangType
voiceType: VoiceType
}
......@@ -110,11 +110,12 @@ export interface TimbreItem {
iconUrl: string | null
}
export interface TextScript {
export interface AudioSetting {
codec: string
sampleRate: number
speed: number
volume: number
pitch?: number
voiceType: number
content: string
}
......@@ -154,6 +155,7 @@ export interface DraftConfig {
logoUrl: string | null
bgmUrl: string | null
materialUrl: string | null
pronunciationLanguageL: LangType
memberId?: number
modifiedTime?: string
}
......
......@@ -3,15 +3,15 @@ import { fetchDigitalHumanTimbreList, fetchTimbreByExample } from '@/apis/digita
import { useAudioSettingStore } from '@/store/modules/audio-setting'
import { useDigitalCreationStore } from '@/store/modules/creation'
import { LanType, TimbreItem, VoiceType } from '@/store/types/creation'
import { LangType, TimbreItem, VoiceType } from '@/store/types/creation'
import { computed, onMounted, ref, watch } from 'vue'
import DigitalAudioCard from './digital-audio-card.vue'
const audioSettingStore = useAudioSettingStore()
const digitalCreationStore = useDigitalCreationStore()
const lanList = ref([
{ key: LanType.CANTONESE, label: '粵語' },
{ key: LanType.MANDARIN, label: '普通話' },
{ key: LangType.CANTONESE, label: '粵語' },
{ key: LangType.MANDARIN, label: '普通話' },
])
const sexValue = ref(0)
const sexList = [
......@@ -25,9 +25,9 @@ const digitalTimbreMaleList = ref<TimbreItem[]>([])
const showAll = ref(false)
const searchName = ref('')
const lanType = computed({
const langType = computed({
get() {
return audioSettingStore.lanType
return audioSettingStore.langType
},
set(value) {
audioSettingStore.setLanType(value)
......@@ -43,6 +43,15 @@ const speed = computed({
},
})
const volume = computed({
get() {
return Number(digitalCreationStore.volume)
},
set(value) {
digitalCreationStore.setVolume(String(value))
},
})
const pitch = computed({
get() {
return Number(digitalCreationStore.pitch)
......@@ -58,7 +67,7 @@ watch(
if (len && !digitalTimbreValue.value) {
if (digitalCreationStore.person) {
digitalTimbreValue.value = digitalTimbreList.value.find((i) => i.timebreId === digitalCreationStore.person)
lanType.value = LanType.MANDARIN
langType.value = LangType.MANDARIN
} else {
digitalTimbreValue.value = digitalTimbreList.value[0]
}
......@@ -67,9 +76,9 @@ watch(
)
watch(
() => lanType.value,
() => langType.value,
(newVal) => {
if (newVal === LanType.CANTONESE) {
if (newVal === LangType.CANTONESE) {
audioSettingStore.setVoiceType(VoiceType.CANTONESE_FEMALE)
} else {
if (digitalTimbreValue.value?.sex === '男') {
......@@ -116,11 +125,11 @@ function handleClickAudioCard(timbreItem: TimbreItem) {
<div class="h-full overflow-y-auto px-4 py-2">
<div v-if="!showAll">
<div class="flex justify-end pb-3">
<HorizontalTabs v-model:value="lanType" :list="lanList" />
<HorizontalTabs v-model:value="langType" :list="lanList" />
</div>
<DigitalAudioCard
v-if="lanType === LanType.MANDARIN"
v-if="langType === LangType.MANDARIN"
:value="digitalTimbreValue"
show-toggle
@toggle="showAll = true"
......@@ -133,6 +142,11 @@ function handleClickAudioCard(timbreItem: TimbreItem) {
<div class="w-10">{{ speed }}</div>
</div>
<div class="mt-4 flex items-center gap-2">
<div class="w-12">音量:</div>
<n-slider v-model:value="volume" class="flex-1" :max="15" :min="0" :step="1" />
<div class="w-10">{{ volume }}</div>
</div>
<div v-if="langType === LangType.MANDARIN" class="mt-4 flex items-center gap-2">
<div class="w-12">語調:</div>
<n-slider v-model:value="pitch" class="flex-1" :max="15" :min="0" :step="1" />
<div class="w-10">{{ pitch }}</div>
......
<script setup lang="ts">
import { useAudioSettingStore } from '@/store/modules/audio-setting'
import { useDigitalCreationStore } from '@/store/modules/creation'
import { TextScript, VoiceType } from '@/store/types/creation'
import { AudioSetting, LangType, VoiceType } from '@/store/types/creation'
import { computed, onMounted, onUnmounted, ref } from 'vue'
let voiceType = VoiceType.CANTONESE_FEMALE
let contentData = ''
let websocket: WebSocket
const url = 'wss://ai-api-sit.gsstcloud.com/websocket/textToSpeechTC.ws'
......@@ -18,6 +16,15 @@ const previewContentWidth = ref(0)
const previewContentHeight = ref(0)
const previewContent = ref<HTMLElement>()
const digitalAudio = ref<HTMLAudioElement>()
const audioSetting = ref<AudioSetting>({
codec: 'mp3',
sampleRate: 16000,
content: '',
voiceType: VoiceType.CANTONESE_FEMALE,
speed: 5,
volume: 5,
pitch: 5,
})
const resizeObserver = new ResizeObserver((entries) => {
const { contentRect } = entries[0]
previewContentWidth.value = contentRect.width
......@@ -78,17 +85,12 @@ function disconnectWebSocket() {
}
function sendDataToWebSocket() {
voiceType = audioSettingStore.voiceType
contentData = digitalCreationStore.text
const payload: TextScript = {
codec: 'mp3',
sampleRate: 16000,
speed: Number(digitalCreationStore.speed),
volume: Number(digitalCreationStore.volume),
voiceType: voiceType,
content: contentData,
}
websocket.send(JSON.stringify(payload))
audioSetting.value.content = digitalCreationStore.text
audioSetting.value.voiceType = audioSettingStore.voiceType
audioSetting.value.speed = Number(digitalCreationStore.speed)
audioSetting.value.volume = Number(digitalCreationStore.volume)
audioSetting.value.pitch = Number(digitalCreationStore.pitch)
websocket.send(JSON.stringify(audioSetting.value))
}
function generatePreview() {
......@@ -101,11 +103,14 @@ function controlAudio() {
digitalAudio.value?.pause()
return
}
if (contentData !== digitalCreationStore.text) {
audioData.value = ''
return
}
if (voiceType !== audioSettingStore.voiceType) {
if (
audioSetting.value.content !== digitalCreationStore.text ||
audioSetting.value.voiceType !== audioSettingStore.voiceType ||
audioSetting.value.speed !== Number(digitalCreationStore.speed) ||
audioSetting.value.volume !== Number(digitalCreationStore.volume) ||
(audioSettingStore.langType === LangType.MANDARIN &&
audioSetting.value.pitch !== Number(digitalCreationStore.pitch))
) {
audioData.value = ''
return
}
......@@ -146,7 +151,7 @@ function controlAudio() {
:loading="isConnected"
:disabled="!digitalCreationStore.text"
@click="generatePreview"
>生成预览</n-button
>生成預覽</n-button
>
<CustomIcon
v-else
......
......@@ -3,13 +3,13 @@ import { createDigitalHumanVideoTask, saveDraftConfig } from '@/apis/digital-cre
import { fetchUniversalCurrency } from '@/apis/user'
import { useDigitalCreationStore } from '@/store/modules/creation'
import { BaseVideoTask, DraftConfig } from '@/store/types/creation'
import { onMounted, onUnmounted, ref } from 'vue'
import { onMounted, onUnmounted, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const digitalCreationStore = useDigitalCreationStore()
const editDraftName = ref(false)
const saveSuccess = ref(false)
const autoSaveSuccess = ref(false)
const showExportModal = ref(false)
const ratioValue = ref(720)
const ratioList = [
......@@ -22,6 +22,19 @@ const transparent = [
]
let timer: any
watch(
() => ratioValue.value,
(newVal) => {
if (newVal === 1080) {
digitalCreationStore.setWidth(1080)
digitalCreationStore.setHeight(1920)
} else {
digitalCreationStore.setWidth(720)
digitalCreationStore.setHeight(1280)
}
},
)
onMounted(() => {
timer = setInterval(() => {
saveDraft()
......@@ -34,15 +47,15 @@ onUnmounted(() => {
})
// 保存为草稿
async function saveDraft() {
async function saveDraft(autoSave: boolean = true) {
const payload: DraftConfig = {
...digitalCreationStore.$state,
draftName: digitalCreationStore.draftName,
}
const res = await saveDraftConfig<DraftConfig>(payload)
if (res.code === 0) {
autoSave ? (autoSaveSuccess.value = true) : window.$message.success('保存成功')
digitalCreationStore.updateDigitalCreation(res.data)
saveSuccess.value = true
}
}
......@@ -112,11 +125,11 @@ async function getUniversalCurrency() {
<div class="flex items-center">
<div class="flex items-center gap-4">
<div v-if="saveSuccess" class="flex items-center gap-2">
<div v-if="autoSaveSuccess" class="flex items-center gap-2">
<CustomIcon class="text-green" icon="ep:success-filled" />
<span>已自動保存</span>
</div>
<n-button class="!rounded-md" @click="saveDraft"> 保存爲草稿 </n-button>
<n-button class="!rounded-md" @click="saveDraft(false)"> 保存爲草稿 </n-button>
<n-button class="!rounded-md" type="info" @click="showExportModal = true"> 導出視頻 </n-button>
</div>
</div>
......
<script setup lang="ts">
import { fetchDigitalHumanTemplateStatus, fetchDraftConfigById } from '@/apis/digital-creation'
import { useDigitalCreationStore } from '@/store/modules/creation'
import { DigitalTemplate, DraftConfig } from '@/store/types/creation'
import { DigitalTemplate, DraftConfig, LangType } from '@/store/types/creation'
import { onMounted } from 'vue'
import { useRoute } from 'vue-router'
import HeaderBar from './header-bar.vue'
......@@ -40,8 +40,8 @@ async function getDigitalTemplate(id: number) {
inputAudioUrl: digitalTemplate.inputAudioUrl,
callbackUrl: digitalTemplate.callbackUrl,
figureId: digitalTemplate.figureId,
width: digitalTemplate.videoParams.width || 0,
height: digitalTemplate.videoParams.height || 0,
width: 720,
height: 1280,
transparent: digitalTemplate.videoParams.transparent ? 'Y' : 'N',
cameraId: digitalTemplate.dhParams.cameraId,
x: digitalTemplate.dhParams.position.x || 0,
......@@ -58,6 +58,7 @@ async function getDigitalTemplate(id: number) {
logoUrl: digitalTemplate.logoParams?.logoUrl || null,
bgmUrl: digitalTemplate.bgmParams?.bgmUrl || null,
materialUrl: digitalTemplate.materialUrl,
pronunciationLanguageL: LangType.CANTONESE,
}
digitalCreationStore.updateDigitalCreation(draftConfig)
}
......
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