I have an HTML audio element with src
pointing to a valid URL, but the audio element is greyed out and disabled. Right next to the audio element, I have a link that goes to directly the src
URL, which correctly points to the mp3 file on S3.
I can't figure out why the audio player is in a disabled state. It's implemented in Svelte code below. Happening in Chrome and Safari browsers.
How can I remove the disabled state from this audio player?
<script>
import { onMount } from 'svelte';
import { slide } from 'svelte/transition';
import { BACKEND_URL } from '$lib/constants';
import { isRtlLanguage } from '$lib/utils';
import Ping from '$lib/components/loading/Ping.svelte';
export let text = 'hello';
export let language = 'English';
let isLoading = true;
let audioUrl;
onMount(async () => {
await handleSubmit();
});
async function handleSubmit() {
isLoading = true;
audioUrl = null;
const response = await fetch(BACKEND_URL + 'text-to-speech', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text, language })
});
const r = await response.json();
audioUrl = r.outputUri;
isLoading = false;
}
</script>
<div in:slide out:slide class="flex {isRtlLanguage(language) ? 'justify-end' : ''}">
{#if isLoading}
<div class="flex space-x-3">
<div class="pt-1">
<Ping />
</div>
<div class="text-sm text-gray">Generating voice response...</div>
</div>
{:else if audioUrl}
<div class="flex space-x-4">
<div class="rounded-full border border-lightgray">
<audio controls>
<source src={audioUrl} type="audio/mp3">
</audio>
</div>
<div class="pt-4">
<a href={audioUrl} target="_blank" class="hovertext">
<i class="bi bi-box-arrow-right"></i>
</a>
</div>
</div>
{/if}
</div>
The problem is fixed if I add a small delay between when the S3 audio file URL is generated and when I mount the audio player: setTimeout(() => {isLoading = false}, 2000);
.
This gives enough time for the audio URL to become accessible by the audio player.
<script>
import { onMount } from 'svelte';
import { slide } from 'svelte/transition';
import { BACKEND_URL } from '$lib/constants';
import { isRtlLanguage } from '$lib/utils';
import Ping from '$lib/components/loading/Ping.svelte';
export let text = 'hello';
export let language = 'English';
let isLoading = true;
let audioUrl;
onMount(() => {
handleSubmit();
});
async function handleSubmit() {
isLoading = true;
const response = await fetch(BACKEND_URL + 'text-to-speech', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text, language })
});
const r = await response.json();
audioUrl = r.outputUri;
// give short delay until audio is ready.
// this is to remedy a bug with the
// S3 source on the audio player.
setTimeout(() => {
isLoading = false;
}, 2000);
}
</script>
<div in:slide out:slide class="flex {isRtlLanguage(language) ? 'justify-end' : ''}">
{#if isLoading}
<div class="flex space-x-3">
<div class="pt-1">
<Ping />
</div>
<div class="text-sm text-gray">Generating voice response...</div>
</div>
{:else}
<div class="rounded-full border border-lightgray">
<audio controls>
<source src={audioUrl} type="audio/mp3" />
</audio>
</div>
{/if}
</div>