-
Notifications
You must be signed in to change notification settings - Fork 13
Description
The StreamingTranscriber class fails to authenticate properly in browser environments, throwing the:
SyntaxError: Failed to construct 'WebSocket': The subprotocol '[object Object]' is invalid.
at factory (/node_modules/.vite/deps/assemblyai.js?v=dc373e06:132:12)
This occurs because the StreamingTranscriber incorrectly passes authentication headers to the WebSocket constructor, which is not supported in browser environments.
This bug completely breaks the StreamingTranscriber functionality in browser environments.
Environment
- SDK Version: Latest TypeScript SDK
- Environment: Browser (client-side)
- Authentication Method: Both API key and temporary token fail
- Error Location:
polyfillWebSocketFactory
call inconnect()
method
Root Cause Analysis
The issue stems from inconsistent authentication handling between StreamingTranscriber
and RealtimeTranscriber
classes:
❌ Current Broken Implementation (StreamingTranscriber)
✅ Working Implementation (RealtimeTranscriber)
Key Issues in StreamingTranscriber
-
Browser WebSocket API Incompatibility: The StreamingTranscriber always passes a headers object to
polyfillWebSocketFactory()
, but browser WebSocket constructors don't support custom headers. The browser WebSocket API signature is:new WebSocket(url, protocols?) // protocols is string[] or string, NOT an object
When
{headers: {...}}
is passed as the second parameter, browsers interpret it as subprotocols, causing the[object Object]
error. -
Headers passed for token authentication: When using a temporary token, the StreamingTranscriber still tries to pass headers to the WebSocket constructor, which fails in browsers since tokens should be sent via URL parameters instead.
-
Missing token URL parameter: Unlike RealtimeTranscriber, the StreamingTranscriber doesn't add the token to the WebSocket URL as a query parameter in the
connectionUrl()
method. -
No browser environment detection: StreamingTranscriber lacks the browser compatibility warning that RealtimeTranscriber provides.
Proposed Fix
1. Update connect()
method in StreamingTranscriber:
connect() {
return new Promise<BeginEvent>((resolve) => {
if (this.socket) {
throw new Error("Already connected");
}
const url = this.connectionUrl();
// Handle authentication like RealtimeTranscriber
if (this.token) {
this.socket = polyfillWebSocketFactory(url.toString());
} else {
if (conditions.browser) {
console.warn(
`API key authentication is not supported for StreamingTranscriber in browser environment. Use temporary token authentication instead.
Learn more at https://github.com/AssemblyAI/assemblyai-node-sdk/blob/main/docs/compat.md#browser-compatibility.`
);
}
this.socket = polyfillWebSocketFactory(url.toString(), {
headers: { Authorization: this.apiKey },
});
}
// ... rest of the method
});
}
2. Update connectionUrl()
method in StreamingTranscriber:
private connectionUrl(): URL {
const url = new URL(this.params.websocketBaseUrl ?? "");
if (url.protocol !== "wss:") {
throw new Error("Invalid protocol, must be wss");
}
const searchParams = new URLSearchParams();
// Add token to URL parameters like RealtimeTranscriber
if (this.token) {
searchParams.set("token", this.token);
}
searchParams.set("sample_rate", this.params.sampleRate.toString());
// ... rest of existing parameter handling
url.search = searchParams.toString();
return url;
}