Created
August 30, 2023 17:45
-
-
Save gsans/fefd2d620935626061856cd9e8def799 to your computer and use it in GitHub Desktop.
Angular Service to use latest ElevenLabs APIs for text-to-speech and streamed APIs for low latency
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@angular/core'; | |
import { HttpClient } from '@angular/common/http'; | |
import { environment } from 'src/environments/environment.development'; | |
// Usage: | |
// import { VoiceService } from './voice.service'; | |
// | |
// export class Component { | |
// constructor(private audio: AudioService) { } | |
// public playTextToSpeech(text:string) { | |
// this.audio.playTextToSpeech(text); | |
// } | |
// public playStreamAudio(text: string) { | |
// this.audio.playStreamAudio(text); | |
// } | |
// } | |
@Injectable() | |
export class VoiceService { | |
ELEVEN_LABS_VOICE_ID = environment.ELEVEN_LABS_VOICE_ID; | |
ELEVEN_LABS_API_KEY = environment.ELEVEN_LABS_API_KEY; | |
public audio: HTMLAudioElement; | |
constructor(private http: HttpClient) { | |
this.audio = new Audio(); | |
} | |
public setAudioSourceAndPlay(source: string): void { | |
this.audio.src = source; | |
this.audio.play(); | |
} | |
public setAudioAndPlay(data: ArrayBuffer): void { | |
const blob = new Blob([data], { type: 'audio/mpeg' }); | |
const url = URL.createObjectURL(blob); | |
this.audio.src = url; | |
console.log('Started playing: ' + Date.now()); | |
this.audio.play(); | |
console.log('Ended playing: ' + Date.now()); | |
} | |
public playTextToSpeech(text: string) { | |
this.getAudio(text); | |
} | |
private getAudio(text: string) { | |
const ttsURL = `https://api.elevenlabs.io/v1/text-to-speech/${this.ELEVEN_LABS_VOICE_ID}`; | |
const headers = { | |
accept: 'audio/mpeg', | |
'content-type': 'application/json', | |
'xi-api-key': this.ELEVEN_LABS_API_KEY, | |
}; | |
const request = { | |
text, | |
"model_id": "eleven_multilingual_v2", | |
"voice_settings": { //defaults specific to voiceId | |
"stability": 0.5, | |
"similarity_boost": 0.75, | |
"style": 0, | |
"use_speaker_boost": true | |
} | |
}; | |
console.log('Call made: ' + Date.now()); | |
this.http | |
.post(ttsURL, request, { headers, responseType: 'arraybuffer' }) | |
.subscribe({ | |
next: (response: ArrayBuffer) => { | |
this.playAudio(response); | |
}, | |
error: (error) => { | |
console.error('Error:', error); | |
} | |
}); | |
} | |
private playAudio(data: ArrayBuffer) { | |
this.setAudioAndPlay(data); | |
} | |
public async playStreamAudio(text: string) { | |
await this.getStreamAudio(text); | |
} | |
private async getStreamAudio(text: string) { | |
const streamingURL = `https://api.elevenlabs.io/v1/text-to-speech/${this.ELEVEN_LABS_VOICE_ID}/stream?optimize_streaming_latency=3`; | |
const headers = { | |
'content-type': 'application/json', | |
'xi-api-key': this.ELEVEN_LABS_API_KEY, | |
}; | |
console.log('Call made: ' + Date.now()); | |
const request = { | |
text, | |
"model_id": "eleven_multilingual_v2", | |
"voice_settings": { //defaults specific to voiceId | |
"stability": 0.5, | |
"similarity_boost": 0.75, | |
"style": 0, | |
"use_speaker_boost": true | |
} | |
}; | |
this.http | |
.post(streamingURL, request, { headers, responseType: 'arraybuffer' }) | |
.subscribe({ | |
next: (response: ArrayBuffer) => { | |
this.playAudioStream(response); | |
}, | |
error: (error) => { | |
console.error('Error:', error); | |
} | |
}); | |
} | |
private async playAudioStream(audioData: ArrayBuffer) { | |
const audioContext = new AudioContext(); | |
const audioBuffer = await audioContext.decodeAudioData(audioData); | |
const source = audioContext.createBufferSource(); | |
source.buffer = audioBuffer; | |
source.connect(audioContext.destination); | |
source.onended = () => { | |
console.log('Ended playing: ' + Date.now()); | |
}; | |
let startTime = audioContext.currentTime + 0.1; | |
console.log('Started playing: ' + startTime); | |
source.start(startTime); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment