2
0
Files
bot/packages/forge/blocks/elevenlabs/actions/convertTextToSpeech.ts
Baptiste Arnaud d96f384e02 ♻️ Migrate from got to ky (#1416)
Closes #1415
2024-04-05 09:01:16 +02:00

117 lines
3.3 KiB
TypeScript

import { createAction, option } from '@typebot.io/forge'
import { auth } from '../auth'
import { baseUrl } from '../constants'
import { ModelsResponse, VoicesResponse } from '../type'
import got, { HTTPError } from 'ky'
import { uploadFileToBucket } from '@typebot.io/lib/s3/uploadFileToBucket'
import { createId } from '@typebot.io/lib/createId'
export const convertTextToSpeech = createAction({
name: 'Convert text to speech',
auth,
options: option.object({
text: option.string.layout({
label: 'Text',
inputType: 'textarea',
placeholder: 'Enter the text to convert to speech',
}),
voiceId: option.string.layout({
fetcher: 'fetchVoices',
label: 'Voice',
placeholder: 'Select a voice',
}),
modelId: option.string.layout({
fetcher: 'fetchModels',
label: 'Model',
placeholder: 'Select a model',
defaultValue: 'eleven_monolingual_v1',
}),
saveUrlInVariableId: option.string.layout({
label: 'Save audio URL in variable',
placeholder: 'Select a variable',
inputType: 'variableDropdown',
}),
}),
getSetVariableIds: ({ saveUrlInVariableId }) =>
saveUrlInVariableId ? [saveUrlInVariableId] : [],
fetchers: [
{
id: 'fetchVoices',
fetch: async ({ credentials }) => {
const response = await got
.get(baseUrl + '/v1/voices', {
headers: {
'xi-api-key': credentials.apiKey,
},
})
.json<VoicesResponse>()
return response.voices.map((voice) => ({
value: voice.voice_id,
label: voice.name,
}))
},
dependencies: [],
},
{
id: 'fetchModels',
fetch: async ({ credentials }) => {
const response = await got
.get(baseUrl + '/v1/models', {
headers: {
'xi-api-key': credentials.apiKey,
},
})
.json<ModelsResponse>()
return response
.filter((model) => model.can_do_text_to_speech)
.map((model) => ({
value: model.model_id,
label: model.name,
}))
},
dependencies: [],
},
],
run: {
server: async ({ credentials, options, variables, logs }) => {
if (!options.voiceId) return logs.add('Voice ID is missing')
if (!options.text) return logs.add('Text is missing')
if (!options.saveUrlInVariableId)
return logs.add('Save variable is missing')
try {
const response = await got
.post(baseUrl + '/v1/text-to-speech/' + options.voiceId, {
headers: {
Accept: 'audio/mpeg',
'xi-api-key': credentials.apiKey,
},
json: {
model_id: options.modelId,
text: options.text,
},
})
.arrayBuffer()
const url = await uploadFileToBucket({
file: Buffer.from(response),
key: `tmp/elevenlabs/audio/${createId() + createId()}.mp3`,
mimeType: 'audio/mpeg',
})
variables.set(options.saveUrlInVariableId, url)
} catch (err) {
if (err instanceof HTTPError) {
return logs.add({
status: 'error',
description: err.message,
details: await err.response.text(),
})
}
}
},
},
})