Skip to content

Commit 7e67855

Browse files
authored
improvement(elevenlabs): wire stability and similarity_boost end-to-end (#4679)
* improvement(elevenlabs): wire stability and similarity_boost end-to-end * fix(elevenlabs): guard NaN in voice settings and always send both knobs together
1 parent a1b2130 commit 7e67855

5 files changed

Lines changed: 61 additions & 20 deletions

File tree

apps/sim/app/api/tools/tts/route.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,17 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
3535
)
3636
if (!parsed.success) return parsed.response
3737

38-
const { text, voiceId, apiKey, modelId, workspaceId, workflowId, executionId } =
39-
parsed.data.body
38+
const {
39+
text,
40+
voiceId,
41+
apiKey,
42+
modelId,
43+
stability,
44+
similarityBoost,
45+
workspaceId,
46+
workflowId,
47+
executionId,
48+
} = parsed.data.body
4049

4150
const voiceIdValidation = validateAlphanumericId(voiceId, 'voiceId', 255)
4251
if (!voiceIdValidation.isValid) {
@@ -57,6 +66,14 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
5766

5867
const endpoint = `https://api.elevenlabs.io/v1/text-to-speech/${voiceId}`
5968

69+
const hasVoiceSetting = stability !== undefined || similarityBoost !== undefined
70+
const voiceSettings = hasVoiceSetting
71+
? {
72+
stability: stability ?? 0.5,
73+
similarity_boost: similarityBoost ?? 0.75,
74+
}
75+
: undefined
76+
6077
const response = await fetch(endpoint, {
6178
method: 'POST',
6279
headers: {
@@ -67,6 +84,7 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
6784
body: JSON.stringify({
6885
text,
6986
model_id: modelId,
87+
...(voiceSettings ? { voice_settings: voiceSettings } : {}),
7088
}),
7189
signal: AbortSignal.timeout(DEFAULT_EXECUTION_TIMEOUT_MS),
7290
})

apps/sim/blocks/blocks/elevenlabs.ts

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { ElevenLabsBlockResponse } from '@/tools/elevenlabs/types'
55
export const ElevenLabsBlock: BlockConfig<ElevenLabsBlockResponse> = {
66
type: 'elevenlabs',
77
name: 'ElevenLabs',
8-
description: 'Convert TTS using ElevenLabs',
8+
description: 'Convert text to speech with ElevenLabs',
99
authMode: AuthMode.ApiKey,
1010
longDescription: 'Integrate ElevenLabs into the workflow. Can convert text to speech.',
1111
docsLink: 'https://docs.sim.ai/tools/elevenlabs',
@@ -42,6 +42,21 @@ export const ElevenLabsBlock: BlockConfig<ElevenLabsBlockResponse> = {
4242
{ label: 'eleven_flash_v2_5', id: 'eleven_flash_v2_5' },
4343
{ label: 'eleven_v3', id: 'eleven_v3' },
4444
],
45+
value: () => 'eleven_monolingual_v1',
46+
},
47+
{
48+
id: 'stability',
49+
title: 'Stability',
50+
type: 'short-input',
51+
placeholder: '0.0 to 1.0 (e.g., 0.5)',
52+
mode: 'advanced',
53+
},
54+
{
55+
id: 'similarityBoost',
56+
title: 'Similarity Boost',
57+
type: 'short-input',
58+
placeholder: '0.0 to 1.0 (e.g., 0.75)',
59+
mode: 'advanced',
4560
},
4661
{
4762
id: 'apiKey',
@@ -57,19 +72,30 @@ export const ElevenLabsBlock: BlockConfig<ElevenLabsBlockResponse> = {
5772
access: ['elevenlabs_tts'],
5873
config: {
5974
tool: () => 'elevenlabs_tts',
60-
params: (params) => ({
61-
apiKey: params.apiKey,
62-
text: params.text,
63-
voiceId: params.voiceId,
64-
modelId: params.modelId,
65-
}),
75+
params: (params) => {
76+
const parseUnitInterval = (value: unknown): number | undefined => {
77+
if (value === undefined || value === null || value === '') return undefined
78+
const n = Number(value)
79+
return Number.isFinite(n) ? n : undefined
80+
}
81+
return {
82+
apiKey: params.apiKey,
83+
text: params.text,
84+
voiceId: params.voiceId,
85+
modelId: params.modelId,
86+
stability: parseUnitInterval(params.stability),
87+
similarityBoost: parseUnitInterval(params.similarityBoost),
88+
}
89+
},
6690
},
6791
},
6892

6993
inputs: {
7094
text: { type: 'string', description: 'Text to convert' },
7195
voiceId: { type: 'string', description: 'Voice identifier' },
7296
modelId: { type: 'string', description: 'Model identifier' },
97+
stability: { type: 'number', description: 'Voice stability 0.0-1.0' },
98+
similarityBoost: { type: 'number', description: 'Similarity boost 0.0-1.0' },
7399
apiKey: { type: 'string', description: 'ElevenLabs API key' },
74100
},
75101

apps/sim/lib/api/contracts/tools/media/tts.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ export const ttsToolBodySchema = z.object({
77
voiceId: z.string({ error: 'Missing required parameters' }).min(1, 'Missing required parameters'),
88
apiKey: z.string({ error: 'Missing required parameters' }).min(1, 'Missing required parameters'),
99
modelId: z.string().optional().default('eleven_monolingual_v1'),
10+
stability: z.coerce.number().min(0).max(1).optional(),
11+
similarityBoost: z.coerce.number().min(0).max(1).optional(),
1012
workspaceId: z.string().optional(),
1113
workflowId: z.string().optional(),
1214
executionId: z.string().optional(),

apps/sim/tools/elevenlabs/tts.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { ToolConfig } from '@/tools/types'
44
export const elevenLabsTtsTool: ToolConfig<ElevenLabsTtsParams, ElevenLabsTtsResponse> = {
55
id: 'elevenlabs_tts',
66
name: 'ElevenLabs TTS',
7-
description: 'Convert TTS using ElevenLabs voices',
7+
description: 'Convert text to speech using ElevenLabs voices',
88
version: '1.0.0',
99

1010
params: {
@@ -34,7 +34,7 @@ export const elevenLabsTtsTool: ToolConfig<ElevenLabsTtsParams, ElevenLabsTtsRes
3434
description:
3535
'Voice stability setting from 0.0 to 1.0 (e.g., 0.5 for balanced, 0.75 for more stable). Higher values produce more consistent output',
3636
},
37-
similarity: {
37+
similarityBoost: {
3838
type: 'number',
3939
required: false,
4040
visibility: 'user-or-llm',
@@ -52,7 +52,7 @@ export const elevenLabsTtsTool: ToolConfig<ElevenLabsTtsParams, ElevenLabsTtsRes
5252
request: {
5353
url: '/api/tools/tts',
5454
method: 'POST',
55-
headers: (params) => ({
55+
headers: () => ({
5656
'Content-Type': 'application/json',
5757
}),
5858
body: (
@@ -65,7 +65,7 @@ export const elevenLabsTtsTool: ToolConfig<ElevenLabsTtsParams, ElevenLabsTtsRes
6565
voiceId: params.voiceId,
6666
modelId: params.modelId || 'eleven_monolingual_v1',
6767
stability: params.stability,
68-
similarity: params.similarity,
68+
similarityBoost: params.similarityBoost,
6969
workspaceId: params._context?.workspaceId,
7070
workflowId: params._context?.workflowId,
7171
executionId: params._context?.executionId,

apps/sim/tools/elevenlabs/types.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export interface ElevenLabsTtsParams {
77
voiceId: string
88
modelId?: string
99
stability?: number
10-
similarity?: number
10+
similarityBoost?: number
1111
}
1212

1313
export interface ElevenLabsTtsResponse extends ToolResponse {
@@ -17,9 +17,4 @@ export interface ElevenLabsTtsResponse extends ToolResponse {
1717
}
1818
}
1919

20-
export interface ElevenLabsBlockResponse extends ToolResponse {
21-
output: {
22-
audioUrl: string
23-
audioFile?: UserFile
24-
}
25-
}
20+
export type ElevenLabsBlockResponse = ElevenLabsTtsResponse

0 commit comments

Comments
 (0)