|
14 | 14 |
|
15 | 15 | import Spinner from '$lib/components/common/Spinner.svelte'; |
16 | 16 | import SensitiveInput from '$lib/components/common/SensitiveInput.svelte'; |
| 17 | + import TTSVoiceInput from '$lib/components/workspace/Models/TTSVoiceInput.svelte'; |
17 | 18 |
|
18 | 19 | import { TTS_RESPONSE_SPLIT } from '$lib/types'; |
19 | 20 |
|
|
58 | 59 |
|
59 | 60 | let STT_WHISPER_MODEL_LOADING = false; |
60 | 61 |
|
| 62 | + type Voice = { |
| 63 | + id: string; |
| 64 | + name?: string; |
| 65 | + description?: string; |
| 66 | + meta?: { |
| 67 | + description?: string; |
| 68 | + }; |
| 69 | + }; |
| 70 | +
|
61 | 71 | // eslint-disable-next-line no-undef |
62 | 72 | let voices: SpeechSynthesisVoice[] = []; |
| 73 | + let providerVoices: Voice[] = []; |
63 | 74 | let models: Awaited<ReturnType<typeof _getModels>>['models'] = []; |
64 | 75 |
|
65 | 76 | const getModels = async () => { |
|
82 | 93 |
|
83 | 94 | const getVoices = async () => { |
84 | 95 | if (TTS_ENGINE === '') { |
| 96 | + providerVoices = []; |
| 97 | +
|
85 | 98 | const getVoicesLoop = setInterval(() => { |
86 | 99 | voices = speechSynthesis.getVoices(); |
87 | 100 |
|
|
92 | 105 | } |
93 | 106 | }, 100); |
94 | 107 | } else { |
| 108 | + voices = []; |
| 109 | +
|
95 | 110 | const res = await _getVoices(localStorage.token).catch((e) => { |
96 | 111 | toast.error(`${e}`); |
97 | 112 | }); |
98 | 113 |
|
99 | 114 | if (res) { |
100 | 115 | console.log(res); |
101 | | - voices = res.voices; |
102 | | - voices.sort((a, b) => a.name.localeCompare(b.name, $i18n.resolvedLanguage)); |
| 116 | + providerVoices = res.voices ?? []; |
| 117 | + providerVoices.sort((a, b) => |
| 118 | + (a.name ?? a.id).localeCompare(b.name ?? b.id, $i18n.resolvedLanguage) |
| 119 | + ); |
103 | 120 | } |
104 | 121 | } |
105 | 122 | }; |
|
679 | 696 | <div class=" mb-1.5 text-xs font-medium">{$i18n.t('TTS Voice')}</div> |
680 | 697 | <div class="flex w-full"> |
681 | 698 | <div class="flex-1"> |
682 | | - <input |
683 | | - list="voice-list" |
684 | | - class="w-full rounded-lg py-2 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden" |
| 699 | + <TTSVoiceInput |
685 | 700 | bind:value={TTS_VOICE} |
| 701 | + voices={providerVoices} |
686 | 702 | placeholder={$i18n.t('Select a voice')} |
| 703 | + className="w-full rounded-lg py-2 px-4 bg-gray-50 dark:text-gray-300 dark:bg-gray-850" |
687 | 704 | /> |
688 | | - |
689 | | - <datalist id="voice-list"> |
690 | | - {#each voices as voice} |
691 | | - <option value={voice.id}>{voice.name}</option> |
692 | | - {/each} |
693 | | - </datalist> |
694 | 705 | </div> |
695 | 706 | </div> |
696 | 707 | </div> |
|
736 | 747 | <div class=" mb-1.5 text-xs font-medium">{$i18n.t('TTS Voice')}</div> |
737 | 748 | <div class="flex w-full"> |
738 | 749 | <div class="flex-1"> |
739 | | - <input |
740 | | - list="voice-list" |
741 | | - class="w-full rounded-lg py-2 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden" |
| 750 | + <TTSVoiceInput |
742 | 751 | bind:value={TTS_VOICE} |
| 752 | + voices={providerVoices} |
743 | 753 | placeholder={$i18n.t('Select a voice')} |
| 754 | + className="w-full rounded-lg py-2 px-4 bg-gray-50 dark:text-gray-300 dark:bg-gray-850" |
744 | 755 | /> |
745 | | - |
746 | | - <datalist id="voice-list"> |
747 | | - {#each voices as voice} |
748 | | - <option value={voice.id}>{voice.name}</option> |
749 | | - {/each} |
750 | | - </datalist> |
751 | 756 | </div> |
752 | 757 | </div> |
753 | 758 | </div> |
|
777 | 782 | <div class=" mb-1.5 text-xs font-medium">{$i18n.t('TTS Voice')}</div> |
778 | 783 | <div class="flex w-full"> |
779 | 784 | <div class="flex-1"> |
780 | | - <input |
781 | | - list="voice-list" |
782 | | - class="w-full rounded-lg py-2 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden" |
| 785 | + <TTSVoiceInput |
783 | 786 | bind:value={TTS_VOICE} |
| 787 | + voices={providerVoices} |
784 | 788 | placeholder={$i18n.t('Select a voice')} |
| 789 | + className="w-full rounded-lg py-2 px-4 bg-gray-50 dark:text-gray-300 dark:bg-gray-850" |
785 | 790 | /> |
786 | | - |
787 | | - <datalist id="voice-list"> |
788 | | - {#each voices as voice} |
789 | | - <option value={voice.id}>{voice.name}</option> |
790 | | - {/each} |
791 | | - </datalist> |
792 | 791 | </div> |
793 | 792 | </div> |
794 | 793 | </div> |
|
820 | 819 | <div class=" mb-1.5 text-xs font-medium">{$i18n.t('TTS Voice')}</div> |
821 | 820 | <div class="flex w-full"> |
822 | 821 | <div class="flex-1"> |
823 | | - <input |
824 | | - list="voice-list" |
825 | | - class="w-full rounded-lg py-2 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden" |
| 822 | + <TTSVoiceInput |
826 | 823 | bind:value={TTS_VOICE} |
| 824 | + voices={providerVoices} |
827 | 825 | placeholder={$i18n.t('Select a voice')} |
| 826 | + className="w-full rounded-lg py-2 px-4 bg-gray-50 dark:text-gray-300 dark:bg-gray-850" |
828 | 827 | /> |
829 | | - |
830 | | - <datalist id="voice-list"> |
831 | | - {#each voices as voice} |
832 | | - <option value={voice.id}>{voice.name}</option> |
833 | | - {/each} |
834 | | - </datalist> |
835 | 828 | </div> |
836 | 829 | </div> |
837 | 830 | </div> |
|
0 commit comments