( params: Partial<PlayHtTtsParams> )
| 781 | } |
| 782 | |
| 783 | async function synthesizeWithPlayHT( |
| 784 | params: Partial<PlayHtTtsParams> |
| 785 | ): Promise<{ audioBuffer: Buffer; format: string; mimeType: string }> { |
| 786 | const { |
| 787 | text, |
| 788 | apiKey, |
| 789 | userId, |
| 790 | voice, |
| 791 | quality = 'standard', |
| 792 | outputFormat = 'mp3', |
| 793 | speed = 1.0, |
| 794 | temperature, |
| 795 | voiceGuidance, |
| 796 | textGuidance, |
| 797 | sampleRate, |
| 798 | } = params |
| 799 | |
| 800 | if (!text || !apiKey || !userId) { |
| 801 | throw new Error('text, apiKey, and userId are required for PlayHT') |
| 802 | } |
| 803 | |
| 804 | const requestBody: Record<string, unknown> = { |
| 805 | text, |
| 806 | quality, |
| 807 | output_format: outputFormat, |
| 808 | speed, |
| 809 | } |
| 810 | |
| 811 | if (voice) requestBody.voice = voice |
| 812 | if (temperature !== undefined) requestBody.temperature = temperature |
| 813 | if (voiceGuidance !== undefined) requestBody.voice_guidance = voiceGuidance |
| 814 | if (textGuidance !== undefined) requestBody.text_guidance = textGuidance |
| 815 | if (sampleRate) requestBody.sample_rate = sampleRate |
| 816 | |
| 817 | const response = await fetch('https://api.play.ht/api/v2/tts/stream', { |
| 818 | method: 'POST', |
| 819 | headers: { |
| 820 | AUTHORIZATION: apiKey, |
| 821 | 'X-USER-ID': userId, |
| 822 | 'Content-Type': 'application/json', |
| 823 | }, |
| 824 | body: JSON.stringify(requestBody), |
| 825 | }) |
| 826 | |
| 827 | if (!response.ok) { |
| 828 | const error = await readTtsErrorJson(response, 'PlayHT TTS error response') |
| 829 | const errorMessage = getTtsErrorMessage(error, response.statusText) |
| 830 | throw new Error(`PlayHT TTS API error: ${errorMessage}`) |
| 831 | } |
| 832 | |
| 833 | const audioBuffer = await readResponseToBufferWithLimit(response, { |
| 834 | maxBytes: MAX_TTS_AUDIO_BYTES, |
| 835 | label: 'PlayHT TTS audio response', |
| 836 | }) |
| 837 | |
| 838 | const format = outputFormat || 'mp3' |
| 839 | const mimeType = getMimeType(format) |
| 840 |
no test coverage detected