Spaces:
Runtime error
Runtime error
<script lang="ts"> | |
import { density, composing, style, temperature, notesImage, notesTokens, audioBlob } from '$lib/stores'; | |
import { styles } from './config.json'; | |
const updateMetadata = () => { | |
if ('mediaSession' in navigator) { | |
navigator.mediaSession.metadata = new MediaMetadata({ | |
title: `${styles[$style]} Composition`, | |
artist: 'AI Guru Composer', | |
album: 'Hugging Face', | |
artwork: [ | |
{ | |
src: 'static/hugging-face-headphones.png', | |
sizes: '512x512', | |
type: 'image/png', | |
}, | |
], | |
}); | |
} | |
}; | |
const createTask = async ({ | |
music_style, | |
density, | |
temperature, | |
}: { | |
music_style: string; | |
density: string; | |
temperature: string; | |
}) => { | |
const taskResponse = await fetch('task/create', { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
body: JSON.stringify({ | |
music_style, | |
density, | |
temperature, | |
}), | |
}); | |
if (!taskResponse.ok || !taskResponse.headers.get('content-type')?.includes('application/json')) { | |
throw new Error(`Unable to create composition: [${taskResponse.status}] ${await taskResponse.text()}`); | |
} | |
const task = await taskResponse.json(); | |
return task; | |
}; | |
const pollTask = async (task: Record<string, any>) => { | |
const taskResponse = await fetch(`task/poll?task_id=${task.task_id}`); | |
if (!taskResponse.ok || !taskResponse.headers.get('content-type')?.includes('application/json')) { | |
throw new Error(`Unable to create composition: [${taskResponse.status}] ${await taskResponse.text()}`); | |
} | |
return await taskResponse.json(); | |
}; | |
const longPollTask = async (task: Record<string, any>, interval = 1_000, max = 100): Promise<Record<string, any>> => { | |
task = await pollTask(task); | |
if (task.status === 'completed' || task.status === 'failed' || (max && task.poll_count > max)) { | |
return task; | |
} | |
await new Promise((resolve) => setTimeout(resolve, interval)); | |
return await longPollTask(task, interval, max); | |
}; | |
const compose = async () => { | |
$composing = true; | |
try { | |
const task = await createTask({ | |
music_style: $style, | |
density: $density, | |
temperature: $temperature, | |
}); | |
const completedTask = await longPollTask(task); | |
const { audio, image, tokens } = completedTask.output; | |
$audioBlob = audio; | |
$notesImage = image; | |
$notesTokens = tokens; | |
updateMetadata(); | |
} catch (err) { | |
console.error(err); | |
} finally { | |
$composing = false; | |
} | |
}; | |
</script> | |
<button disabled={$composing} on:click={compose}> | |
{#if $composing} | |
Composing... | |
{:else} | |
Compose <img src="static/wand.svg" alt="Magic wand" /> | |
{/if} | |
</button> | |
<style> | |
button { | |
display: block; | |
font-size: 1.2rem; | |
font-family: 'Lato', sans-serif; | |
font-weight: 700; | |
color: hsl(0 0% 97%); | |
background: transparent; | |
border: 3px solid hsl(0 0% 97%); | |
border-radius: 0.375rem; | |
padding: 0.5rem 1rem; | |
cursor: pointer; | |
margin: 1rem auto 2rem; | |
} | |
button[disabled] { | |
border-color: hsl(0 0% 50%); | |
color: hsl(0 0% 50%); | |
cursor: initial; | |
} | |
img { | |
height: 1.2rem; | |
aspect-ratio: 1 / 1; | |
vertical-align: bottom; | |
} | |
@media (min-width: 900px) { | |
button { | |
margin-top: 0; | |
} | |
} | |
</style> | |