// Eleven Labs API
const API_KEY = '<YOUR_API_KEY_HERE>'
const options = {method: 'GET', headers: {'xi-api-key': API_KEY}};
let elevenlabsVoices;
await fetch('https://api.elevenlabs.io/v1/voices', options)
.then(response => response.json())
.then(response => (console.log(response), elevenlabsVoices = [...response.voices]))
.catch(err => console.error(err));
console.log(elevenlabsVoices)
window.chosenVoiceName = elevenlabsVoices[0].voice_id;
document.body.innerHTML = `
<style>
body {
color: white;
font-family: system-ui, sans-serif;
}
</style>
Please choose a voice:
<br>
<select onchange="window.chosenVoiceName=this.value;">${elevenlabsVoices.map(n => `<option value="${n.voice_id}">${n.name} - ${n.labels ? `${n.labels.accent}, ${n.labels.description}, ${n.labels.age}, ${n.labels.gender}${n.labels['use case'] ? `, ${n.labels['use case']}` : ''}` : '' }</option>`).join("")}</select>
<br>
<button onclick="oc.window.hide();">submit</button>
<br><br>
(As you can see, this plugin is pretty rudimentary for now. Feel free to ask for more features on the Discord.)
`;
oc.window.show()
let sentence = "";
oc.thread.on("StreamingMessage", async function (data) {
for await (let chunk of data.chunks) {
sentence += chunk.text;
let endOfSentenceIndex = Math.max(sentence.indexOf("."), sentence.indexOf("!"), sentence.indexOf("?"));
if(endOfSentenceIndex !== -1) {
console.log("Speaking sentence:", sentence);
await textToSpeech({text:sentence.slice(0, endOfSentenceIndex+1), voiceName:window.chosenVoiceName});
sentence = sentence.slice(endOfSentenceIndex+1);
sentence = sentence.replace(/^[.!?\s]+/g, "");
}
}
});
function textToSpeech({text, voiceName}) {
return new Promise((resolve, reject) => {
const options = {
method: 'POST',
headers: {
'xi-api-key': API_KEY,
'Content-Type': 'application/json'
},
body: `{
"model_id":"eleven_multilingual_v1",
"text": "${text.trim().replaceAll('*','').replaceAll('"', '\\"')}",
"voice_settings":{"similarity_boost":0.5,"stability":0.5}
}`
};
let audio;
fetch(`https://api.elevenlabs.io/v1/text-to-speech/${voiceName}`, options)
.then(response => response.blob())
.then(blob => {
const url = URL.createObjectURL(blob);
audio = new Audio(url)
audio.onended = function() {
resolve()
}
audio.play()
}).catch(err => (console.error(err), reject()))
});
}