From 3762c6b142419f5912572aee8426df3c0b578a16 Mon Sep 17 00:00:00 2001 From: ElmTran Date: Mon, 30 Sep 2024 15:10:20 +0800 Subject: [PATCH] feat: support tiktok api --- README.md | 8 +- package.json | 2 +- src-tauri/Cargo.lock | 3 +- src-tauri/Cargo.toml | 3 +- src-tauri/src/cmd.rs | 3 +- src-tauri/src/services/tts/mod.rs | 1 + src-tauri/src/services/tts/tiktok.rs | 44 +++ src-tauri/tauri.conf.json | 2 +- src/locales/langs/en-US.json | 52 ++- src/locales/langs/zh-CN.json | 67 +++- src/utils/constants.ts | 413 ++++++++++++++------ src/views/TTSView/components/AzureForm.vue | 30 +- src/views/TTSView/components/FormButton.vue | 2 +- src/views/TTSView/components/TikTokForm.vue | 101 +++++ src/views/TTSView/index.vue | 6 +- 15 files changed, 601 insertions(+), 136 deletions(-) create mode 100644 src-tauri/src/services/tts/tiktok.rs create mode 100644 src/views/TTSView/components/TikTokForm.vue diff --git a/README.md b/README.md index 0fc7c14..7332797 100644 --- a/README.md +++ b/README.md @@ -29,13 +29,16 @@ You can download the latest version from the [release page](https://github.com/E - [x] Selection Speech Shortcut +- [x] TikTok API + +- [ ] Support Speech Synthesis Markup Language (SSML) + ## License Distributed under the MIT License. See `LICENSE` for more information. [![License][license-shield]][license-url] - ## Contact Mengqing - [@Telegram](https://t.me/mzfbwu/) - [@Email](mailto:c897611977@gmail.com) @@ -58,9 +61,8 @@ Mengqing - [@Telegram](https://t.me/mzfbwu/) - [@Email](mailto:c897611977@gmail. - [Azure Cognitiveservices Speech](https://learn.microsoft.com/en-us/azure/ai-services/speech-service/get-started-text-to-speech?tabs=windows%2Cterminal&pivots=programming-language-rest#synthesize-to-a-file) - [license-shield]: https://img.shields.io/github/license/ElmTran/praises -[license-url]: https://github.com/ElmTran/praises/blob/master/LICENSE \ No newline at end of file +[license-url]: https://github.com/ElmTran/praises/blob/master/LICENSE diff --git a/package.json b/package.json index 00fffd5..f0ddc89 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "praises", "private": true, - "version": "0.0.5", + "version": "0.0.6", "type": "module", "lint-staged": { "*.{js,ts,tsx,vue}": [ diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 65d1104..582ea5b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3360,8 +3360,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "praises" -version = "0.0.5" +version = "0.0.6" dependencies = [ + "base64 0.22.1", "dirs", "env_logger", "futures-util", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ce27c63..bfb38af 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "praises" -version = "0.0.5" +version = "0.0.6" description = "Praises is a text-to-speech tool that can help you read text easily." authors = ["ElmTran"] edition = "2021" @@ -48,6 +48,7 @@ url = "2.5.2" regex = "1.10.5" strum_macros = "0.26.4" strum = "0.26.3" +base64 = "0.22.1" [features] # This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!! diff --git a/src-tauri/src/cmd.rs b/src-tauri/src/cmd.rs index 1c41581..1eb42c6 100644 --- a/src-tauri/src/cmd.rs +++ b/src-tauri/src/cmd.rs @@ -1,6 +1,6 @@ // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command use crate::app::HANDLE; -use crate::services::tts::{ azure, windows, msedge }; +use crate::services::tts::{ azure, windows, msedge, tiktok }; use crate::config; use crate::hotkeys; use tauri::Manager; @@ -39,6 +39,7 @@ pub async fn convert( tts.receive().await } "azure" => { azure::request(text, speaker, language, style, role, rate, pitch).await } + "tiktok" => { tiktok::request(text, speaker).await } _ => Err("Invalid service".to_string()), } } diff --git a/src-tauri/src/services/tts/mod.rs b/src-tauri/src/services/tts/mod.rs index 43e0e30..d5f31ba 100644 --- a/src-tauri/src/services/tts/mod.rs +++ b/src-tauri/src/services/tts/mod.rs @@ -1,3 +1,4 @@ pub mod windows; pub mod azure; pub mod msedge; +pub mod tiktok; diff --git a/src-tauri/src/services/tts/tiktok.rs b/src-tauri/src/services/tts/tiktok.rs new file mode 100644 index 0000000..25d94b0 --- /dev/null +++ b/src-tauri/src/services/tts/tiktok.rs @@ -0,0 +1,44 @@ +use reqwest::Client; +use serde_json::json; +use std::error::Error; +use base64::Engine; + +static ENDPOINT: &str = "https://tiktok-tts.weilnet.workers.dev/api/generation"; + +pub struct TikTokTTS { + text: String, + voice: String, +} + +impl TikTokTTS { + pub fn new(text: String, voice: String) -> Self { + Self { text, voice } + } + + pub async fn send(&self) -> Result, Box> { + let client = Client::new(); + let res = client + .post(ENDPOINT) + .header("Content-Type", "application/json") + .json( + &json!({ + "text": self.text, + "voice": self.voice, + }) + ) + .send().await?; + let res = res.error_for_status()?; + let data = res.json::().await?; + if !data["success"].as_bool().unwrap_or(false) || !data.get("data").is_some() { + return Err(format!("TikTok API error: {:?}", data).into()); + } + let audio_base64 = data["data"].as_str().ok_or("Invalid audio data")?; + let audio = base64::prelude::BASE64_STANDARD.decode(audio_base64)?; + Ok(audio) + } +} + +pub async fn request(text: &str, voice: &str) -> Result, String> { + let tts = TikTokTTS::new(text.to_string(), voice.to_string()); + tts.send().await.map_err(|e| e.to_string()) +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ee8d70e..b3f5338 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -7,7 +7,7 @@ }, "package": { "productName": "praises", - "version": "0.0.5" + "version": "0.0.6" }, "tauri": { "allowlist": { diff --git a/src/locales/langs/en-US.json b/src/locales/langs/en-US.json index 1d73482..32d7212 100644 --- a/src/locales/langs/en-US.json +++ b/src/locales/langs/en-US.json @@ -1,6 +1,6 @@ { "tts": { - "form": { + "azure": { "language": "Language", "speaker": "Speaker", "style": "Style", @@ -76,6 +76,56 @@ "role": "Please select role", "template": "Please select template" } + }, + "tiktok": { + "language": "Language", + "voice": "Voice", + "options": { + "language": { + "en_us": "English (US)", + "en_uk": "English (UK)", + "en_au": "English (Australia)", + "fr": "French", + "de": "German", + "es": "Spanish", + "es_mx": "Spanish (Mexico)", + "br": "Portuguese (Brazil)", + "id": "Indonesian", + "jp": "Japanese", + "kr": "Korean", + "characters": "Characters", + "singing": "Singing" + }, + "voice": { + "female": "Female", + "male1": "Male 1", + "male2": "Male 2", + "male3": "Male 3", + "male4": "Male 4", + "male": "Male", + "female1": "Female 1", + "female2": "Female 2", + "female3": "Female 3", + "ghostface": "Ghostface", + "chewbacca": "Chewbacca", + "c3po": "C-3PO", + "stitch": "Stitch", + "stormtrooper": "Stormtrooper", + "rocket": "Rocket", + "alto": "Alto", + "tenor": "Tenor", + "sunshineSoon": "Sunshine Soon", + "warmyBreeze": "Warmy Breeze", + "glorious": "Glorious", + "itGoesUp": "It Goes Up", + "chipmunk": "Chipmunk", + "dramatic": "Dramatic" + } + }, + "placeholder": { + "language": "Please select language", + "voice": "Please select voice" + } } }, "setting": { diff --git a/src/locales/langs/zh-CN.json b/src/locales/langs/zh-CN.json index e8d4da8..7b19b1b 100644 --- a/src/locales/langs/zh-CN.json +++ b/src/locales/langs/zh-CN.json @@ -1,6 +1,6 @@ { "tts": { - "form": { + "azure": { "language": "语言", "speaker": "语音", "style": "风格", @@ -13,7 +13,20 @@ "language": { "en": "英语", "zh": "中文", - "ja": "日语" + "ja": "日语", + "en_us": "英语(美国)", + "en_uk": "英语(英国)", + "en_au": "英语(澳大利亚)", + "fr": "法语", + "de": "德语", + "es": "西班牙语", + "es_mx": "西班牙语(墨西哥)", + "br": "葡萄牙语(巴西)", + "id": "印度尼西亚语", + "jp": "日语", + "kr": "韩语", + "characters": "角色语音", + "singing": "歌唱" }, "speaker": { "aria": "Aria", @@ -76,6 +89,56 @@ "role": "请选择角色", "template": "请选择模板" } + }, + "tiktok": { + "language": "语言", + "voice": "语音", + "options": { + "language": { + "en_us": "英语(美国)", + "en_uk": "英语(英国)", + "en_au": "英语(澳大利亚)", + "fr": "法语", + "de": "德语", + "es": "西班牙语", + "es_mx": "西班牙语(墨西哥)", + "br": "葡萄牙语(巴西)", + "id": "印度尼西亚语", + "jp": "日语", + "kr": "韩语", + "characters": "角色语音", + "singing": "歌唱" + }, + "voice": { + "female": "女性", + "male1": "男性1", + "male2": "男性2", + "male3": "男性3", + "male4": "男性4", + "male": "男性", + "female1": "女性1", + "female2": "女性2", + "female3": "女性3", + "ghostface": "鬼脸", + "chewbacca": "丘巴卡", + "c3po": "C-3PO", + "stitch": "史迪奇", + "stormtrooper": "冲锋队员", + "rocket": "火箭浣熊", + "alto": "女中音", + "tenor": "男高音", + "sunshineSoon": "阳光很快", + "warmyBreeze": "温暖微风", + "glorious": "光辉灿烂", + "itGoesUp": "音调上升", + "chipmunk": "花栗鼠", + "dramatic": "戏剧性的" + } + }, + "placeholder": { + "language": "请选择语言", + "voice": "请选择语音" + } } }, "setting": { diff --git a/src/utils/constants.ts b/src/utils/constants.ts index e0a222e..e233413 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -16,106 +16,115 @@ type LanguageOption = { export const languageOptions: ComputedRef = computed(() => [ { value: "en-US", - label: $t("tts.form.options.language.en"), + label: $t("tts.azure.options.language.en"), speakers: [ { value: "en-US-AriaNeural", - label: $t("tts.form.options.speaker.aria"), + label: $t("tts.azure.options.speaker.aria"), styles: [ - { value: "chat", label: $t("tts.form.options.style.chat") }, - { value: "angry", label: $t("tts.form.options.style.angry") }, - { value: "cheerful", label: $t("tts.form.options.style.cheerful") }, + { value: "chat", label: $t("tts.azure.options.style.chat") }, + { value: "angry", label: $t("tts.azure.options.style.angry") }, + { value: "cheerful", label: $t("tts.azure.options.style.cheerful") }, { value: "customerservice", - label: $t("tts.form.options.style.customerservice"), + label: $t("tts.azure.options.style.customerservice"), }, { value: "empathetic", - label: $t("tts.form.options.style.empathetic"), + label: $t("tts.azure.options.style.empathetic"), }, - { value: "excited", label: $t("tts.form.options.style.excited") }, - { value: "friendly", label: $t("tts.form.options.style.friendly") }, - { value: "hopeful", label: $t("tts.form.options.style.hopeful") }, + { value: "excited", label: $t("tts.azure.options.style.excited") }, + { value: "friendly", label: $t("tts.azure.options.style.friendly") }, + { value: "hopeful", label: $t("tts.azure.options.style.hopeful") }, { value: "narration - professional", - label: $t("tts.form.options.style.narrationProfessional"), + label: $t("tts.azure.options.style.narrationProfessional"), }, { value: "newscast - casual", - label: $t("tts.form.options.style.newscastCasual"), + label: $t("tts.azure.options.style.newscastCasual"), }, { value: "newscast - formal", - label: $t("tts.form.options.style.newscastFormal"), + label: $t("tts.azure.options.style.newscastFormal"), + }, + { value: "sad", label: $t("tts.azure.options.style.sad") }, + { value: "shouting", label: $t("tts.azure.options.style.shouting") }, + { + value: "terrified", + label: $t("tts.azure.options.style.terrified"), }, - { value: "sad", label: $t("tts.form.options.style.sad") }, - { value: "shouting", label: $t("tts.form.options.style.shouting") }, - { value: "terrified", label: $t("tts.form.options.style.terrified") }, { value: "unfriendly", - label: $t("tts.form.options.style.unfriendly"), + label: $t("tts.azure.options.style.unfriendly"), }, { value: "whispering", - label: $t("tts.form.options.style.whispering"), + label: $t("tts.azure.options.style.whispering"), }, ], }, { value: "en-US-DavisNeural", - label: $t("tts.form.options.speaker.davis"), + label: $t("tts.azure.options.speaker.davis"), styles: [ - { value: "chat", label: $t("tts.form.options.style.chat") }, - { value: "angry", label: $t("tts.form.options.style.angry") }, - { value: "cheerful", label: $t("tts.form.options.style.cheerful") }, - { value: "excited", label: $t("tts.form.options.style.excited") }, - { value: "friendly", label: $t("tts.form.options.style.friendly") }, - { value: "hopeful", label: $t("tts.form.options.style.hopeful") }, - { value: "sad", label: $t("tts.form.options.style.sad") }, - { value: "shouting", label: $t("tts.form.options.style.shouting") }, - { value: "terrified", label: $t("tts.form.options.style.terrified") }, + { value: "chat", label: $t("tts.azure.options.style.chat") }, + { value: "angry", label: $t("tts.azure.options.style.angry") }, + { value: "cheerful", label: $t("tts.azure.options.style.cheerful") }, + { value: "excited", label: $t("tts.azure.options.style.excited") }, + { value: "friendly", label: $t("tts.azure.options.style.friendly") }, + { value: "hopeful", label: $t("tts.azure.options.style.hopeful") }, + { value: "sad", label: $t("tts.azure.options.style.sad") }, + { value: "shouting", label: $t("tts.azure.options.style.shouting") }, + { + value: "terrified", + label: $t("tts.azure.options.style.terrified"), + }, { value: "unfriendly", - label: $t("tts.form.options.style.unfriendly"), + label: $t("tts.azure.options.style.unfriendly"), }, { value: "whispering", - label: $t("tts.form.options.style.whispering"), + label: $t("tts.azure.options.style.whispering"), }, ], }, { value: "en-US-GuyNeural", - label: $t("tts.form.options.speaker.guy"), + label: $t("tts.azure.options.speaker.guy"), styles: [ - { value: "chat", label: $t("tts.form.options.style.chat") }, - { value: "angry", label: $t("tts.form.options.style.angry") }, - { value: "cheerful", label: $t("tts.form.options.style.cheerful") }, - { value: "excited", label: $t("tts.form.options.style.excited") }, - { value: "friendly", label: $t("tts.form.options.style.friendly") }, - { value: "hopeful", label: $t("tts.form.options.style.hopeful") }, + { value: "chat", label: $t("tts.azure.options.style.chat") }, + { value: "angry", label: $t("tts.azure.options.style.angry") }, + { value: "cheerful", label: $t("tts.azure.options.style.cheerful") }, + { value: "excited", label: $t("tts.azure.options.style.excited") }, + { value: "friendly", label: $t("tts.azure.options.style.friendly") }, + { value: "hopeful", label: $t("tts.azure.options.style.hopeful") }, { value: "narration - professional", - label: $t("tts.form.options.style.narrationProfessional"), + label: $t("tts.azure.options.style.narrationProfessional"), }, { value: "newscast - casual", - label: $t("tts.form.options.style.newscastCasual"), + label: $t("tts.azure.options.style.newscastCasual"), }, { value: "newscast - formal", - label: $t("tts.form.options.style.newscastFormal"), + label: $t("tts.azure.options.style.newscastFormal"), + }, + { value: "sad", label: $t("tts.azure.options.style.sad") }, + { value: "shouting", label: $t("tts.azure.options.style.shouting") }, + { + value: "terrified", + label: $t("tts.azure.options.style.terrified"), }, - { value: "sad", label: $t("tts.form.options.style.sad") }, - { value: "shouting", label: $t("tts.form.options.style.shouting") }, - { value: "terrified", label: $t("tts.form.options.style.terrified") }, { value: "unfriendly", - label: $t("tts.form.options.style.unfriendly"), + label: $t("tts.azure.options.style.unfriendly"), }, { value: "whispering", - label: $t("tts.form.options.style.whispering"), + label: $t("tts.azure.options.style.whispering"), }, ], }, @@ -123,148 +132,154 @@ export const languageOptions: ComputedRef = computed(() => [ }, { value: "zh-CN", - label: $t("tts.form.options.language.zh"), + label: $t("tts.azure.options.language.zh"), speakers: [ { value: "zh-CN-XiaoxiaoNeural", - label: $t("tts.form.options.speaker.xiaoxiao"), + label: $t("tts.azure.options.speaker.xiaoxiao"), styles: [ { value: "affectionate", - label: $t("tts.form.options.style.affectionate"), + label: $t("tts.azure.options.style.affectionate"), + }, + { value: "angry", label: $t("tts.azure.options.style.angry") }, + { + value: "assistant", + label: $t("tts.azure.options.style.assistant"), }, - { value: "angry", label: $t("tts.form.options.style.angry") }, - { value: "assistant", label: $t("tts.form.options.style.assistant") }, - { value: "calm", label: $t("tts.form.options.style.calm") }, - { value: "chat", label: $t("tts.form.options.style.chat") }, + { value: "calm", label: $t("tts.azure.options.style.calm") }, + { value: "chat", label: $t("tts.azure.options.style.chat") }, { value: "chat - casual", - label: $t("tts.form.options.style.chatCasual"), + label: $t("tts.azure.options.style.chatCasual"), }, - { value: "cheerful", label: $t("tts.form.options.style.cheerful") }, + { value: "cheerful", label: $t("tts.azure.options.style.cheerful") }, { value: "customerservice", - label: $t("tts.form.options.style.customerservice"), + label: $t("tts.azure.options.style.customerservice"), }, { value: "disgruntled", - label: $t("tts.form.options.style.disgruntled"), + label: $t("tts.azure.options.style.disgruntled"), }, - { value: "fearful", label: $t("tts.form.options.style.fearful") }, - { value: "friendly", label: $t("tts.form.options.style.friendly") }, - { value: "gentle", label: $t("tts.form.options.style.gentle") }, - { value: "lyrical", label: $t("tts.form.options.style.lyrical") }, - { value: "newscast", label: $t("tts.form.options.style.newscast") }, + { value: "fearful", label: $t("tts.azure.options.style.fearful") }, + { value: "friendly", label: $t("tts.azure.options.style.friendly") }, + { value: "gentle", label: $t("tts.azure.options.style.gentle") }, + { value: "lyrical", label: $t("tts.azure.options.style.lyrical") }, + { value: "newscast", label: $t("tts.azure.options.style.newscast") }, { value: "poetry - reading", - label: $t("tts.form.options.style.poetryReading"), + label: $t("tts.azure.options.style.poetryReading"), }, - { value: "sad", label: $t("tts.form.options.style.sad") }, - { value: "serious", label: $t("tts.form.options.style.serious") }, - { value: "sorry", label: $t("tts.form.options.style.sorry") }, - { value: "whisper", label: $t("tts.form.options.style.whisper") }, + { value: "sad", label: $t("tts.azure.options.style.sad") }, + { value: "serious", label: $t("tts.azure.options.style.serious") }, + { value: "sorry", label: $t("tts.azure.options.style.sorry") }, + { value: "whisper", label: $t("tts.azure.options.style.whisper") }, ], }, { value: "zh-CN-XiaomoNeural", - label: $t("tts.form.options.speaker.xiaomo"), + label: $t("tts.azure.options.speaker.xiaomo"), styles: [ { value: "affectionate", - label: $t("tts.form.options.style.affectionate"), + label: $t("tts.azure.options.style.affectionate"), + }, + { value: "angry", label: $t("tts.azure.options.style.angry") }, + { value: "calm", label: $t("tts.azure.options.style.calm") }, + { value: "cheerful", label: $t("tts.azure.options.style.cheerful") }, + { + value: "depressed", + label: $t("tts.azure.options.style.depressed"), }, - { value: "angry", label: $t("tts.form.options.style.angry") }, - { value: "calm", label: $t("tts.form.options.style.calm") }, - { value: "cheerful", label: $t("tts.form.options.style.cheerful") }, - { value: "depressed", label: $t("tts.form.options.style.depressed") }, { value: "disgruntled", - label: $t("tts.form.options.style.disgruntled"), + label: $t("tts.azure.options.style.disgruntled"), }, { value: "embarrassed", - label: $t("tts.form.options.style.embarrassed"), + label: $t("tts.azure.options.style.embarrassed"), }, - { value: "envious", label: $t("tts.form.options.style.envious") }, - { value: "fearful", label: $t("tts.form.options.style.fearful") }, - { value: "gentle", label: $t("tts.form.options.style.gentle") }, - { value: "sad", label: $t("tts.form.options.style.sad") }, - { value: "serious", label: $t("tts.form.options.style.serious") }, + { value: "envious", label: $t("tts.azure.options.style.envious") }, + { value: "fearful", label: $t("tts.azure.options.style.fearful") }, + { value: "gentle", label: $t("tts.azure.options.style.gentle") }, + { value: "sad", label: $t("tts.azure.options.style.sad") }, + { value: "serious", label: $t("tts.azure.options.style.serious") }, ], roles: [ - { value: "Boy", label: $t("tts.form.options.role.boy") }, - { value: "Girl", label: $t("tts.form.options.role.girl") }, + { value: "Boy", label: $t("tts.azure.options.role.boy") }, + { value: "Girl", label: $t("tts.azure.options.role.girl") }, { value: "OlderAdultFemale", - label: $t("tts.form.options.role.olderAdultFemale"), + label: $t("tts.azure.options.role.olderAdultFemale"), }, { value: "OlderAdultMale", - label: $t("tts.form.options.role.olderAdultMale"), + label: $t("tts.azure.options.role.olderAdultMale"), }, { value: "SeniorFemale", - label: $t("tts.form.options.role.seniorFemale"), + label: $t("tts.azure.options.role.seniorFemale"), }, { value: "SeniorMale", - label: $t("tts.form.options.role.seniorMale"), + label: $t("tts.azure.options.role.seniorMale"), }, { value: "YoungAdultFemale", - label: $t("tts.form.options.role.youngAdultFemale"), + label: $t("tts.azure.options.role.youngAdultFemale"), }, { value: "YoungAdultMale", - label: $t("tts.form.options.role.youngAdultMale"), + label: $t("tts.azure.options.role.youngAdultMale"), }, ], }, { value: "zh-CN-YunyeNeural", - label: $t("tts.form.options.speaker.yunye"), + label: $t("tts.azure.options.speaker.yunye"), styles: [ - { value: "angry", label: $t("tts.form.options.style.angry") }, - { value: "calm", label: $t("tts.form.options.style.calm") }, - { value: "cheerful", label: $t("tts.form.options.style.cheerful") }, + { value: "angry", label: $t("tts.azure.options.style.angry") }, + { value: "calm", label: $t("tts.azure.options.style.calm") }, + { value: "cheerful", label: $t("tts.azure.options.style.cheerful") }, { value: "disgruntled", - label: $t("tts.form.options.style.disgruntled"), + label: $t("tts.azure.options.style.disgruntled"), }, { value: "embarrassed", - label: $t("tts.form.options.style.embarrassed"), + label: $t("tts.azure.options.style.embarrassed"), }, - { value: "fearful", label: $t("tts.form.options.style.fearful") }, - { value: "sad", label: $t("tts.form.options.style.sad") }, - { value: "serious", label: $t("tts.form.options.style.serious") }, + { value: "fearful", label: $t("tts.azure.options.style.fearful") }, + { value: "sad", label: $t("tts.azure.options.style.sad") }, + { value: "serious", label: $t("tts.azure.options.style.serious") }, ], roles: [ - { value: "Boy", label: $t("tts.form.options.role.boy") }, - { value: "Girl", label: $t("tts.form.options.role.girl") }, + { value: "Boy", label: $t("tts.azure.options.role.boy") }, + { value: "Girl", label: $t("tts.azure.options.role.girl") }, { value: "OlderAdultFemale", - label: $t("tts.form.options.role.olderAdultFemale"), + label: $t("tts.azure.options.role.olderAdultFemale"), }, { value: "OlderAdultMale", - label: $t("tts.form.options.role.olderAdultMale"), + label: $t("tts.azure.options.role.olderAdultMale"), }, { value: "SeniorFemale", - label: $t("tts.form.options.role.seniorFemale"), + label: $t("tts.azure.options.role.seniorFemale"), }, { value: "SeniorMale", - label: $t("tts.form.options.role.seniorMale"), + label: $t("tts.azure.options.role.seniorMale"), }, { value: "YoungAdultFemale", - label: $t("tts.form.options.role.youngAdultFemale"), + label: $t("tts.azure.options.role.youngAdultFemale"), }, { value: "YoungAdultMale", - label: $t("tts.form.options.role.youngAdultMale"), + label: $t("tts.azure.options.role.youngAdultMale"), }, ], }, @@ -272,20 +287,200 @@ export const languageOptions: ComputedRef = computed(() => [ }, { value: "ja-JP", - label: $t("tts.form.options.language.ja"), + label: $t("tts.azure.options.language.ja"), speakers: [ { value: "ja-JP-NanamiNeural", - label: $t("tts.form.options.speaker.nanami"), + label: $t("tts.azure.options.speaker.nanami"), styles: [ - { value: "chat", label: $t("tts.form.options.style.chat") }, - { value: "cheerful", label: $t("tts.form.options.style.cheerful") }, + { value: "chat", label: $t("tts.azure.options.style.chat") }, + { value: "cheerful", label: $t("tts.azure.options.style.cheerful") }, { value: "customerservice", - label: $t("tts.form.options.style.customerservice"), + label: $t("tts.azure.options.style.customerservice"), }, ], }, ], }, ]); + +type TiktokLanguageOption = { + value: string; + label: string; + speakers: { value: string; label: string }[]; +}; + +export const tiktokLanguageOptions: ComputedRef = + computed(() => [ + { + value: "en_us", + label: $t("tts.tiktok.options.language.en_us"), + speakers: [ + { value: "en_us_001", label: $t("tts.tiktok.options.voice.female") }, + { value: "en_us_006", label: $t("tts.tiktok.options.voice.male1") }, + { value: "en_us_007", label: $t("tts.tiktok.options.voice.male2") }, + { value: "en_us_009", label: $t("tts.tiktok.options.voice.male3") }, + { value: "en_us_010", label: $t("tts.tiktok.options.voice.male4") }, + ], + }, + { + value: "en_uk", + label: $t("tts.tiktok.options.language.en_uk"), + speakers: [ + { value: "en_uk_001", label: $t("tts.tiktok.options.voice.male1") }, + { value: "en_uk_003", label: $t("tts.tiktok.options.voice.male2") }, + ], + }, + { + value: "en_au", + label: $t("tts.tiktok.options.language.en_au"), + speakers: [ + { value: "en_au_001", label: $t("tts.tiktok.options.voice.female") }, + { value: "en_au_002", label: $t("tts.tiktok.options.voice.male") }, + ], + }, + { + value: "fr", + label: $t("tts.tiktok.options.language.fr"), + speakers: [ + { value: "fr_001", label: $t("tts.tiktok.options.voice.male1") }, + { value: "fr_002", label: $t("tts.tiktok.options.voice.male2") }, + ], + }, + { + value: "de", + label: $t("tts.tiktok.options.language.de"), + speakers: [ + { value: "de_001", label: $t("tts.tiktok.options.voice.female") }, + { value: "de_002", label: $t("tts.tiktok.options.voice.male") }, + ], + }, + { + value: "es", + label: $t("tts.tiktok.options.language.es"), + speakers: [ + { value: "es_002", label: $t("tts.tiktok.options.voice.male") }, + ], + }, + { + value: "es_mx", + label: $t("tts.tiktok.options.language.es_mx"), + speakers: [ + { value: "es_mx_002", label: $t("tts.tiktok.options.voice.male1") }, + { value: "es_male_m3", label: $t("tts.tiktok.options.voice.male2") }, + { + value: "es_female_f6", + label: $t("tts.tiktok.options.voice.female1"), + }, + { + value: "es_female_fp1", + label: $t("tts.tiktok.options.voice.female2"), + }, + { + value: "es_mx_female_supermom", + label: $t("tts.tiktok.options.voice.female3"), + }, + ], + }, + { + value: "br", + label: $t("tts.tiktok.options.language.br"), + speakers: [ + { value: "br_003", label: $t("tts.tiktok.options.voice.female2") }, + { value: "br_004", label: $t("tts.tiktok.options.voice.female3") }, + { value: "br_005", label: $t("tts.tiktok.options.voice.male") }, + ], + }, + { + value: "id", + label: $t("tts.tiktok.options.language.id"), + speakers: [ + { value: "id_001", label: $t("tts.tiktok.options.voice.female") }, + ], + }, + { + value: "jp", + label: $t("tts.tiktok.options.language.jp"), + speakers: [ + { value: "jp_001", label: $t("tts.tiktok.options.voice.female1") }, + { value: "jp_003", label: $t("tts.tiktok.options.voice.female2") }, + { value: "jp_005", label: $t("tts.tiktok.options.voice.female3") }, + { value: "jp_006", label: $t("tts.tiktok.options.voice.male") }, + ], + }, + { + value: "kr", + label: $t("tts.tiktok.options.language.kr"), + speakers: [ + { value: "kr_002", label: $t("tts.tiktok.options.voice.male1") }, + { value: "kr_004", label: $t("tts.tiktok.options.voice.male2") }, + { value: "kr_003", label: $t("tts.tiktok.options.voice.female") }, + ], + }, + { + value: "characters", + label: $t("tts.tiktok.options.language.characters"), + speakers: [ + { + value: "en_us_ghostface", + label: $t("tts.tiktok.options.voice.ghostface"), + }, + { + value: "en_us_chewbacca", + label: $t("tts.tiktok.options.voice.chewbacca"), + }, + { value: "en_us_c3po", label: $t("tts.tiktok.options.voice.c3po") }, + { + value: "en_us_stitch", + label: $t("tts.tiktok.options.voice.stitch"), + }, + { + value: "en_us_stormtrooper", + label: $t("tts.tiktok.options.voice.stormtrooper"), + }, + { + value: "en_us_rocket", + label: $t("tts.tiktok.options.voice.rocket"), + }, + ], + }, + { + value: "singing", + label: $t("tts.tiktok.options.language.singing"), + speakers: [ + { + value: "en_female_f08_salut_damour", + label: $t("tts.tiktok.options.voice.alto"), + }, + { + value: "en_male_m03_lobby", + label: $t("tts.tiktok.options.voice.tenor"), + }, + { + value: "en_male_m03_sunshine_soon", + label: $t("tts.tiktok.options.voice.sunshineSoon"), + }, + { + value: "en_female_f08_warmy_breeze", + label: $t("tts.tiktok.options.voice.warmyBreeze"), + }, + { + value: "en_female_ht_f08_glorious", + label: $t("tts.tiktok.options.voice.glorious"), + }, + { + value: "en_male_sing_funny_it_goes_up", + label: $t("tts.tiktok.options.voice.itGoesUp"), + }, + { + value: "en_male_m2_xhxs_m03_silly", + label: $t("tts.tiktok.options.voice.chipmunk"), + }, + { + value: "en_female_ht_f08_wonderful_world", + label: $t("tts.tiktok.options.voice.dramatic"), + }, + ], + }, + ]); diff --git a/src/views/TTSView/components/AzureForm.vue b/src/views/TTSView/components/AzureForm.vue index 15b967c..46e19f2 100644 --- a/src/views/TTSView/components/AzureForm.vue +++ b/src/views/TTSView/components/AzureForm.vue @@ -19,7 +19,11 @@ const { state } = storeToRefs(ttsStore); const { ttsTemplate } = storeToRefs(settingStore); const useSpeakerOptions = (value: string) => { - const language = languageOptions.value.find((item) => item.value === value); + let language = languageOptions.value.find((item) => item.value === value); + if (!language) { + language = languageOptions.value[0]; + state.value.language = language.value; + } speakerOptions.value = language?.speakers || []; state.value.speaker = speakerOptions.value[0].value; useStyleAndRoleOptions(state.value.speaker); @@ -59,13 +63,13 @@ useSpeakerOptions(state.value.language); @@ -80,13 +84,13 @@ useSpeakerOptions(state.value.language); -

{{ $t("tts.form.save") }}

+

{{ $t("tts.azure.save") }}

diff --git a/src/views/TTSView/components/FormButton.vue b/src/views/TTSView/components/FormButton.vue index 8cfb435..e4aade0 100644 --- a/src/views/TTSView/components/FormButton.vue +++ b/src/views/TTSView/components/FormButton.vue @@ -11,7 +11,7 @@ const convert = () => { diff --git a/src/views/TTSView/components/TikTokForm.vue b/src/views/TTSView/components/TikTokForm.vue new file mode 100644 index 0000000..34dd703 --- /dev/null +++ b/src/views/TTSView/components/TikTokForm.vue @@ -0,0 +1,101 @@ + + + diff --git a/src/views/TTSView/index.vue b/src/views/TTSView/index.vue index a415f73..013f8e4 100644 --- a/src/views/TTSView/index.vue +++ b/src/views/TTSView/index.vue @@ -1,6 +1,7 @@