generated from amazon-archives/__template_Apache-2.0
-
Notifications
You must be signed in to change notification settings - Fork 102
Open
Labels
Description
Environment information
Service: AWS Transcribe (Streaming WebSocket API)
Frontend: React + WebSocket + MediaRecorder/AudioContext
Backend: AWS Lambda (Node.js) generating presigned URL using @aws-sdk/signature-v4
Region: eu-west-2
Audio format: PCM16, 16 kHz, mono
Describe the bug
When connecting to AWS Transcribe using a presigned WebSocket URL, the connection closes immediately with no error message from the service.
Even when sending empty or valid PCM16 audio chunks, the socket disconnects right after onopen.
The client never receives transcription events.
Reproduction steps
1. Generate Presigned URL in Lambda
const request = new HttpRequest({
protocol: "wss:",
hostname: `transcribestreaming.${region}.amazonaws.com`,
path: "/stream-transcription-websocket",
method: "GET",
query: {
"language-code": "en-US",
"media-encoding": "pcm",
"sample-rate": "16000"
},
headers: {
host: `transcribestreaming.${region}.amazonaws.com`,
},
});
const signer = new SignatureV4({
credentials: defaultProvider(),
region,
service: "transcribe",
sha256: Sha256,
});
const signedRequest = await signer.presign(request, { expiresIn: 300 });
const url = `wss://${signedRequest.hostname}:8443${signedRequest.path}?${queryStr}`;2. Connect From Frontend
const socket = new WebSocket(wsUrl);
socket.onopen = () => {
console.log("β
Connected to Transcribe");
};
socket.onmessage = (event) => {
console.log("Message:", event.data);
};
socket.onerror = (event) => {
console.error("WebSocket error:", event);
};
socket.onclose = (event) => {
console.log("π΄ Disconnected", event.code, event.reason, event.wasClean);
};3. Send Audio
processor.onaudioprocess = (e) => {
if (socket.readyState !== 1) return;
const float32Array = e.inputBuffer.getChannelData(0);
const int16Array = new Int16Array(float32Array.length);
for (let i = 0; i < float32Array.length; i++) {
int16Array[i] = Math.max(-32768, Math.min(32767, Math.floor(float32Array[i] * 32768)));
}
const audioEvent = {
headers: {
":content-type": { type: "string", value: "application/octet-stream" },
":event-type": { type: "string", value: "AudioEvent" },
":message-type": { type: "string", value: "event" },
},
body: new Uint8Array(int16Array.buffer),
};
socket.send(marshaller.marshall(audioEvent));
};β οΈ Observed Behavior
- WebSocket connects (
onopenfires β ). - Immediately disconnects, with no transcription events.
oncloseshows no reason (event.reasonempty).- Adding silent/empty audio does not change behavior.
β Expected Behavior
- WebSocket should remain open until closed by client.
- Transcribe should return transcription events or at least an error message when audio is invalid.
- Empty audio should result in clean closure, not silent disconnect.
β Questions for AWS Team
- Is there an issue with how the presigned URL is generated (path, port
:8443, or query params)? - Does Transcribe WebSocket require a special initial handshake message before sending audio chunks?
- What are the exact requirements for the AudioEvent payload format (PCM16, marshalling, headers)?
- Why does the connection close without returning an error or
BadRequestException?
Would you like me to also include a Minimal Working Example repo structure (with Lambda + React frontend code) in this issue so AWS support can reproduce it in one go?