


























@@ -5,6 +5,10 @@ import {
55normalizeSeed,
66requireInRange,
77} from "openclaw/plugin-sdk/speech";
8+import {
9+fetchWithSsrFGuard,
10+ssrfPolicyFromHttpBaseUrlAllowedHostname,
11+} from "openclaw/plugin-sdk/ssrf-runtime";
812import { isValidElevenLabsVoiceId, normalizeElevenLabsBaseUrl } from "./shared.js";
9131014function assertElevenLabsVoiceSettings(settings: {
@@ -61,17 +65,15 @@ export async function elevenLabsTTS(params: {
6165const normalizedLanguage = normalizeLanguageCode(languageCode);
6266const normalizedNormalization = normalizeApplyTextNormalization(applyTextNormalization);
6367const normalizedSeed = normalizeSeed(seed);
68+const normalizedBaseUrl = normalizeElevenLabsBaseUrl(baseUrl);
69+const url = new URL(`${normalizedBaseUrl}/v1/text-to-speech/${voiceId}`);
70+if (outputFormat) {
71+url.searchParams.set("output_format", outputFormat);
72+}
647365-const controller = new AbortController();
66-const timeout = setTimeout(() => controller.abort(), timeoutMs);
67-68-try {
69-const url = new URL(`${normalizeElevenLabsBaseUrl(baseUrl)}/v1/text-to-speech/${voiceId}`);
70-if (outputFormat) {
71-url.searchParams.set("output_format", outputFormat);
72-}
73-74-const response = await fetch(url.toString(), {
74+const { response, release } = await fetchWithSsrFGuard({
75+url: url.toString(),
76+init: {
7577method: "POST",
7678headers: {
7779"xi-api-key": apiKey,
@@ -93,13 +95,16 @@ export async function elevenLabsTTS(params: {
9395speed: voiceSettings.speed,
9496},
9597}),
96-signal: controller.signal,
97-});
98-98+},
99+ timeoutMs,
100+policy: ssrfPolicyFromHttpBaseUrlAllowedHostname(normalizedBaseUrl),
101+auditContext: "elevenlabs.tts",
102+});
103+try {
99104await assertOkOrThrowProviderError(response, "ElevenLabs API error");
100105101106return Buffer.from(await response.arrayBuffer());
102107} finally {
103-clearTimeout(timeout);
108+await release();
104109}
105110}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。