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> | |