// Cloned by Niall Ryan on 24 Nov 2023 from World "Calling APIs" by Niall Ryan // Please leave this clone trail here.// Cloned by Niall Ryan on 22 Nov 2023 from World "Chat with GPT model" by Starter user // Please leave this clone trail here.// Sample prompt for a song
let prompt ="";
let key ="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";// METHOD FOR CALLING AI APIs
async function fetchData(apiUrl, data){// MH edit
console.log ("fetchData: "+ apiUrl );
console.log ( data );const response = await fetch(apiUrl,{
headers:{Authorization:`Bearer ${key}`},
method:"POST",
body: JSON.stringify(data),});if(!response.ok){thrownewError(`HTTP Error! status: ${response.status}`);}return response;}// Function handles the query to the image generating AI API
async function queryImage(data){// Add a 'loader' to the image container whilst awaiting the API
let loader = document.createElement('div');
loader.className ='loader';
document.getElementById('image').appendChild(loader);try{const response = await fetchData("https://api-inference.huggingface.co/models/runwayml/stable-diffusion-v1-5", data);const imageBlob = await response.blob();
updateUI('image', imageBlob,true);}catch(error){
handleError('image', error.message);}}// General function for querying sound API (small & medium sized models)
async function querySound(data, apiUrl, containerId){// Add a 'loader' to the image container whilst awaiting the API
let loader = document.createElement('div');
loader.className ='loader';
document.getElementById(containerId).appendChild(loader);try{const response = await fetchData(apiUrl, data);if(response.headers.get("content-type")==="audio/flac"){const audioBlob = await response.blob();
updateUI(containerId, audioBlob,false);}else{const result = await response.json();return result;}}catch(error){
handleError(containerId, error.message);}}// Function updates the UI with new content or error messagesfunction updateUI(containerId, content, isImage){const container = document.getElementById(containerId);
container.innerHTML ='';// Clear previous content or loadersif(isImage){const image = document.createElement('img');
image.src = URL.createObjectURL(content);
container.appendChild(image);}else{const audio =newAudio(URL.createObjectURL(content));
audio.controls =true;
container.appendChild(audio);
audio.addEventListener('canplaythrough',()=> audio.play());}}function clearUI(){
document.getElementById('image').innerHTML ='';
document.getElementById('audioSmall').innerHTML ='';
document.getElementById('audioMedium').innerHTML ='';}// Error handler for UI updatesfunction handleError(containerId, status){const container = document.getElementById(containerId);
container.innerHTML ='';// Clear loadersconst errorElement = document.createElement('p');
errorElement.className ='errorText';
errorElement.textContent =`ERROR: ${containerId} returned ${status}`;
container.appendChild(errorElement);
console.error(`HTTP Error! status: ${status}`);}// Function that handles the user's custom prompt input
async function handleUserInput(){// Clear any existing inference results
clearUI()// Get the user promptconst userInput = document.getElementById('userPrompt').value;const prompt = userInput;// Use the user input as the new prompt// Update the displayed prompt
document.getElementById('prompt').innerHTML =`<b>Prompt:</b> ${prompt}`;// Execute the API calls with the new promptconst imagePromise = queryImage({ inputs:`Album cover art for a song described as "${prompt}"`});const soundSmallPromise = querySound({ inputs: prompt },"https://api-inference.huggingface.co/models/facebook/musicgen-small",'audioSmall');const soundMediumPromise = querySound({ inputs: prompt },"https://api-inference.huggingface.co/models/facebook/musicgen-medium",'audioMedium');// Execute all the API calls at once
await Promise.all([imagePromise, soundSmallPromise, soundMediumPromise]);}// The actual document HTML
document.write(`<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AI SongGenerator</title><link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet"/><style>
body {
font-family:'Roboto', sans-serif;
text-align: center;
margin:0;
color:#fff;}.background {
width:100%;
height:100%;
position: fixed;
top:0;
left:0;
background-color:#333;}.container {
background-color:#282828;
border-radius:10px;
box-shadow:04px8px rgba(4,170,109,0.2);
margin:auto;
padding:20px;
max-width:800px;
margin-top:40px;}
img, audio {
max-width:100%;
border-radius:5px;
margin-top:20px;}.input-field {
width:80%;
padding:12px20px;
margin:8px0;
display:inline-block;
border:3px solid #04AA6D;
border-radius:6px;
box-sizing: border-box;
background-color:#f0f0f0;
color:#333;
font-size:16px;
transition: border 0.3s;}.input-field:focus {
border-color:#026D4D;
outline: none;}.input-field::placeholder {
color:#7a7a7a;}.input-field:hover {
border-color:#013D2D;}.generate-button {
padding:10px20px;
border-radius:5px;
border: none;
background-color:#04AA6D;
color:#D6EEE2;
color: white;
font-size:16px;
cursor: pointer;
transition: background-color 0.3s ease;}.generate-button:hover {
background-color:#D6EEE2;
color:#04AA6D;}.loader {
border:5px solid #D6EEE2;
border-top:5px solid #04AA6D;
border-radius:50%;
width:50px;
height:50px;
animation: spin 2s linear infinite;
margin:20pxauto;}@keyframes spin {0%{ transform: rotate(0deg);}100%{ transform: rotate(360deg);}}.errorText {
color:#e74c3c;
padding:10px;
font-weight:900;}.prompt-display {
background-color:#333;
border-left:5px solid #35634C;
padding:10px;
margin:20px0;
display: block;
text-align: left;}.prompt-display b {
color:#D6EEE2
}.title {
color:#04AA6D;
margin-bottom:5px;
margin:0020px0;}
footer {
position: fixed;
left:0;
bottom:0;
width:100%;
background-color:#282828;
padding:10px0;}.footer-content {
display: flex;
justify-content: center;
align-items: center;}.green-bar {
color:00ff00;
font-weight:900;
margin:010px020px;}</style></head><body><div class="background"><div class="container"><h1 class="title">AI SongGenerator</h1><input type="text" id="userPrompt"class="input-field" placeholder="Describe your fictional song..." value="${prompt}"><button onclick="handleUserInput()"class="generate-button">Generate</button><span class="prompt-display" id="prompt"><b>Prompt:</b> ${prompt}</span><div id="image"></div><div id="audioSmall"class="pad"></div><div id="audioMedium"class="pad"></div></div></div><footer><div class="footer-content"><span class="green-bar">|</span>AudioAPIs are unreliable due to their popularity.<span class="green-bar">|</span>AudioAPIs take ~30s to perform inference and return info.</div></footer></body></html>`);