File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -237,6 +237,15 @@ describe("inworldTTS", () => {
237237 ) ;
238238 } ) ;
239239
240+ it ( "rejects malformed base64 audio chunks" , async ( ) => {
241+ const body = JSON . stringify ( { result : { audioContent : "not-base64!" } } ) ;
242+ queueGuardedResponse ( new Response ( body , { status : 200 } ) ) ;
243+
244+ await expect ( inworldTTS ( { text : "test" , apiKey : "fixture-api-key" } ) ) . rejects . toThrow (
245+ "Inworld TTS returned malformed base64 audio data" ,
246+ ) ;
247+ } ) ;
248+
240249 it ( "throws on HTTP errors with response body" , async ( ) => {
241250 queueGuardedResponse ( new Response ( "bad request body" , { status : 400 } ) ) ;
242251
Original file line number Diff line number Diff line change 11// Inworld plugin module implements tts behavior.
2- import { MAX_AUDIO_BYTES } from "openclaw/plugin-sdk/media-runtime" ;
2+ import { canonicalizeBase64 , MAX_AUDIO_BYTES } from "openclaw/plugin-sdk/media-runtime" ;
33import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime" ;
44import type { SpeechVoiceOption } from "openclaw/plugin-sdk/speech-core" ;
55import { fetchWithSsrFGuard , type SsrFPolicy } from "openclaw/plugin-sdk/ssrf-runtime" ;
@@ -186,7 +186,11 @@ export async function inworldTTS(params: {
186186 }
187187
188188 if ( parsed . result ?. audioContent ) {
189- const chunk = Buffer . from ( parsed . result . audioContent , "base64" ) ;
189+ const canonicalAudio = canonicalizeBase64 ( parsed . result . audioContent ) ;
190+ if ( ! canonicalAudio ) {
191+ throw new Error ( "Inworld TTS returned malformed base64 audio data" ) ;
192+ }
193+ const chunk = Buffer . from ( canonicalAudio , "base64" ) ;
190194 const nextDecodedAudioBytes = decodedAudioBytes + chunk . length ;
191195 if ( nextDecodedAudioBytes > MAX_AUDIO_BYTES ) {
192196 throw new Error (
You can’t perform that action at this time.
0 commit comments