I am trying to use my PlayHT API in order to add voice to my character. I am using the custom javascript section in advanced options in order to achieve this. I have a very rudimentary understanding of code so that combined with a bit of ChatGPT for help, I ended up with this:

async function getCustomPlayHTVoices() { const apiKey = “Removed for security”; // Your PlayHT API key const userId = “Removed for security”; // Your PlayHT User ID

try { const response = await fetch(“https://api.play.ht/api/v2/cloned-voices”, { headers: { “Authorization”: Bearer ${apiKey}, “X-User-ID”: userId } });

if (!response.ok) throw new Error("Failed to fetch PlayHT voices");

const voices = await response.json();
const customVoices = voices.filter(v => v.name.toLowerCase().includes("arlecchino"));

if (customVoices.length === 0) console.warn("Custom voice 'Arlecchino' not found.");

return customVoices;

} catch (error) { console.error(error); return []; } }

// Populate voice selection dropdown (async () => { const playHTVoices = await getCustomPlayHTVoices(); if (playHTVoices.length === 0) { document.body.innerHTML = “<p>Error fetching PlayHT voices. Check your API key or voice availability.</p>”; return; }

const voiceOptions = playHTVoices .map(v => <option value="${v.id}">${v.name}</option>) .join(“”);

document.body.innerHTML = <p>Please choose a voice:</p> <select id="voiceSelect">${voiceOptions}</select> <br> <button onclick="setVoice()">Submit</button> ;

window.chosenVoiceId = playHTVoices[0].id; // Default voice })();

function setVoice() { window.chosenVoiceId = document.getElementById(“voiceSelect”).value; oc.window.hide(); }

oc.window.show();

// Listen for streamed text and convert it to speech using PlayHT let sentence = “”; oc.thread.on(“StreamingMessage”, async function (data) { for await (let chunk of data.chunks) { sentence += chunk.text;

// Check for end of sentence OR limit to 200 characters to prevent buffering too much text
let endOfSentenceIndex = sentence.search(/[.!?]/);
if (endOfSentenceIndex !== -1 || sentence.length > 200) {
  let sentenceToSpeak = sentence.slice(0, endOfSentenceIndex + 1 || sentence.length);
  console.log("Speaking sentence:", sentenceToSpeak);
  await textToSpeech({ text: sentenceToSpeak, voiceId: window.chosenVoiceId });
  sentence = sentence.slice(endOfSentenceIndex + 1).trim(); // Reset for next sentence
}

} });

// Function to send text to PlayHT API and play the generated audio async function textToSpeech({ text, voiceId }) { const apiKey = “Removed for security”; // Your PlayHT API key const userId = “Removed for security”; // Your PlayHT User ID

try { const response = await fetch(“https://api.play.ht/api/v2/tts/stream”, { method: “POST”, headers: { “Authorization”: Bearer ${apiKey}, “X-User-ID”: userId, “Content-Type”: “application/json” }, body: JSON.stringify({ text: text, voice: voiceId, format: “mp3” }) });

if (!response.ok) throw new Error("Failed to fetch audio from PlayHT");

const result = await response.json();
console.log("PlayHT Response:", result);

if (!result.audioUrl) throw new Error("No audio URL returned from PlayHT");

return new Promise(resolve => {
  const audio = new Audio(result.audioUrl);
  audio.onended = resolve;
  audio.play();
});

} catch (error) { console.error(error); } }

I would also like to understand where I went wrong so please explain if you know the solution. Apologies as well, I can’t get the code to be in a single sheet in preview. I guess that tells me a lot about my ability to code.

    • ProfessorDoc@lemmy.worldOP
      link
      fedilink
      English
      arrow-up
      1
      ·
      18 hours ago

      Thank you for the help. One thing to note is window.chosenVoiceName = playHTVoices[0].id; I had to put it after the html body due to it not appearing if it was before, but otherwise this works perfectly. Thank you again.