|
@@ -358,7 +358,7 @@
|
|
|
?.at(0) ?? undefined;
|
|
|
|
|
|
currentUtterance = new SpeechSynthesisUtterance(content);
|
|
|
- currentUtterance.rate = speechRate;
|
|
|
+ currentUtterance.rate = $settings.audio?.tts?.speedRate ?? 1;
|
|
|
|
|
|
if (voice) {
|
|
|
currentUtterance.voice = voice;
|
|
@@ -385,7 +385,7 @@
|
|
|
if (audioElement) {
|
|
|
audioElement.src = audio.src;
|
|
|
audioElement.muted = true;
|
|
|
- audioElement.playbackRate = speechRate;
|
|
|
+ audioElement.playbackRate = $settings.audio?.tts?.speedRate ?? 1;
|
|
|
|
|
|
audioElement
|
|
|
.play()
|
|
@@ -430,28 +430,6 @@
|
|
|
|
|
|
let audioAbortController = new AbortController();
|
|
|
|
|
|
- // Audio speed control
|
|
|
- let speechRate = 1;
|
|
|
- let showSpeedMenu = false;
|
|
|
-
|
|
|
- const speedOptions = [2, 1.75, 1.5, 1.25, 1, 0.75, 0.5];
|
|
|
-
|
|
|
- const setSpeedRate = (rate: number) => {
|
|
|
- speechRate = rate;
|
|
|
- showSpeedMenu = false;
|
|
|
- updateAudioSpeed();
|
|
|
- };
|
|
|
-
|
|
|
- const updateAudioSpeed = () => {
|
|
|
- if (currentUtterance) {
|
|
|
- currentUtterance.rate = speechRate;
|
|
|
- }
|
|
|
- const audioElement = document.getElementById('audioElement') as HTMLAudioElement;
|
|
|
- if (audioElement) {
|
|
|
- audioElement.playbackRate = speechRate;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
// Audio cache map where key is the content and value is the Audio object.
|
|
|
const audioCache = new Map();
|
|
|
const emojiCache = new Map();
|
|
@@ -940,41 +918,6 @@
|
|
|
</button>
|
|
|
</div>
|
|
|
|
|
|
- <div class="relative">
|
|
|
- <Dropdown bind:show={showSpeedMenu}>
|
|
|
- <button class="p-2 rounded-full bg-gray-50 dark:bg-gray-900">
|
|
|
- <svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
|
- <polygon points="8,5 8,19 19,12" fill="currentColor"/>
|
|
|
- <path d="M12 2A10 10 0 0 0 12 22" fill="none" stroke="currentColor" stroke-width="2" stroke-dasharray="2,2"/>
|
|
|
- <path d="M12 2A10 10 0 0 1 12 22" fill="none" stroke="currentColor" stroke-width="2"/>
|
|
|
- </svg>
|
|
|
- </button>
|
|
|
-
|
|
|
- <div slot="content">
|
|
|
- <DropdownMenu.Content
|
|
|
- class="w-full max-w-[180px] rounded-lg px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-[9999] bg-white dark:bg-gray-900 dark:text-white shadow-sm"
|
|
|
- sideOffset={6}
|
|
|
- side="top"
|
|
|
- align="start"
|
|
|
- transition={flyAndScale}
|
|
|
- >
|
|
|
- {#each speedOptions as speed}
|
|
|
- <DropdownMenu.Item
|
|
|
- class="flex gap-2 items-center px-3 py-2 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md {speechRate === speed ? 'bg-gray-200 dark:bg-gray-600' : ''}"
|
|
|
- on:click={() => setSpeedRate(speed)}
|
|
|
- >
|
|
|
- <div class="flex items-center">
|
|
|
- <div class="line-clamp-1">
|
|
|
- {speed}x
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </DropdownMenu.Item>
|
|
|
- {/each}
|
|
|
- </DropdownMenu.Content>
|
|
|
- </div>
|
|
|
- </Dropdown>
|
|
|
- </div>
|
|
|
-
|
|
|
<div>
|
|
|
<button
|
|
|
class=" p-3 rounded-full bg-gray-50 dark:bg-gray-900"
|