Troubleshooting

View as Markdown

Connection Issues

Cannot Establish WebSocket Connection

Symptoms: Connection fails immediately or times out

Possible Causes:

  • Invalid API key
  • Network/firewall blocking WebSocket connections
  • Incorrect WebSocket URL

Solutions:

  1. Verify API Key:

    1// Ensure Authorization header is correct
    2headers: {
    3 Authorization: `Bearer ${API_KEY}` // Not "Token" or "Key"
    4}
  2. Check WebSocket URL:

    1// Correct URL format
    2const url = new URL("wss://api.smallest.ai/waves/v1/pulse/get_text");
    3// Not "ws://" or "https://"
  3. Test Network Connectivity:

    $# Test WebSocket endpoint
    $curl -i -N -H "Connection: Upgrade" \
    > -H "Upgrade: websocket" \
    > -H "Sec-WebSocket-Version: 13" \
    > -H "Sec-WebSocket-Key: test" \
    > https://api.smallest.ai/waves/v1/pulse/get_text

Connection Drops Unexpectedly

Symptoms: Connection closes without sending end signal

Possible Causes:

  • Network instability
  • Server timeout
  • Invalid audio data

Solutions:

  1. Implement Reconnection Logic:

    1let ws;
    2let reconnectAttempts = 0;
    3
    4function connect() {
    5 ws = new WebSocket(url.toString(), { headers });
    6
    7 ws.onclose = (event) => {
    8 if (event.code !== 1000 && reconnectAttempts < 5) {
    9 setTimeout(connect, 1000 * Math.pow(2, reconnectAttempts++));
    10 }
    11 };
    12}
  2. Monitor Connection State:

    1setInterval(() => {
    2 if (ws.readyState !== WebSocket.OPEN) {
    3 console.warn("Connection not open, state:", ws.readyState);
    4 }
    5}, 5000);

Audio Encoding Problems

No Transcription Received

Symptoms: Connection established but no transcript messages

Possible Causes:

  • Incorrect audio encoding
  • Mismatched sample rate
  • Invalid audio format

Solutions:

  1. Verify Encoding Parameters:

    1// Ensure encoding matches your audio format
    2url.searchParams.append("encoding", "linear16"); // or linear32, alaw, mulaw, opus, ogg_opus
    3url.searchParams.append("sample_rate", "16000"); // Must match audio
  2. Check Audio Format:

    1import soundfile as sf
    2
    3audio, sample_rate = sf.read("audio.wav")
    4print(f"Sample rate: {sample_rate}")
    5print(f"Channels: {audio.shape}")
    6print(f"Format: {audio.dtype}")
    7# Should be: 16000 Hz, mono, int16
  3. Validate Chunk Format:

    1// Ensure chunks are binary (not base64 or text)
    2ws.send(audioChunk); // Uint8Array or ArrayBuffer
    3// Not: ws.send(JSON.stringify(audioChunk))

Poor Transcription Quality

Symptoms: Incorrect or garbled transcriptions

Possible Causes:

  • Wrong sample rate
  • Incorrect encoding
  • Audio quality issues

Solutions:

  1. Match Sample Rate:

    1// Audio must match sample_rate parameter
    2const audioContext = new AudioContext({ sampleRate: 16000 });
    3url.searchParams.append("sample_rate", "16000");
  2. Use Recommended Encoding:

    1// Use linear16 for best quality
    2url.searchParams.append("encoding", "linear16");
  3. Preprocess Audio:

    1# Normalize and clean audio before streaming
    2audio = audio / np.abs(audio).max() * 0.95 # Normalize
    3audio = audio.astype(np.int16) # Convert to int16

Response Handling Issues

Partial Transcripts Not Updating

Symptoms: Only final transcripts received, no partial updates

Possible Causes:

  • Not checking is_final field
  • Filtering out partial messages

Solutions:

  1. Handle Both Types:
    1ws.onmessage = (event) => {
    2 const message = JSON.parse(event.data);
    3
    4 if (!message.is_final) {
    5 // Show partial transcript
    6 displayPartial(message.transcript);
    7 } else {
    8 // Show final transcript
    9 displayFinal(message.transcript);
    10 }
    11};

Performance Issues

High Latency

Symptoms: Long delay between speaking and transcription

Possible Causes:

  • Chunk size too large
  • Streaming rate too slow
  • Network latency

Solutions:

  1. Optimize Chunk Size:

    1// Use recommended 4096 bytes
    2const chunkSize = 4096;
  2. Increase Streaming Rate:

    1// Send chunks every 50ms
    2setTimeout(sendChunk, 50); // Not 200ms or longer
  3. Check Network:

    $# Test latency to API
    $ping api.smallest.ai

Memory Issues

Symptoms: Application crashes or slows down during streaming

Possible Causes:

  • Buffering too much audio
  • Not cleaning up resources

Solutions:

  1. Stream Directly:

    1// Stream chunks immediately, don't buffer entire file
    2const stream = fs.createReadStream("audio.wav", { highWaterMark: 4096 });
    3stream.on("data", (chunk) => ws.send(chunk));
  2. Clean Up Resources:

    1ws.onclose = () => {
    2 // Clean up audio resources
    3 if (audioContext) audioContext.close();
    4 if (stream) stream.destroy();
    5};

Browser-Specific Issues

CORS Errors

Symptoms: WebSocket connection blocked in browser

Solutions:

  1. Use WSS (Secure WebSocket):

    1// Always use wss:// in browsers
    2const url = new URL("wss://api.smallest.ai/waves/v1/pulse/get_text");
  2. Handle Authentication:

    1// Note: Browsers may not support custom headers in WebSocket
    2// Consider using query parameter for API key (if supported)
    3// Or use a proxy server for authentication

Microphone Access Denied

Symptoms: Cannot access microphone in browser

Solutions:

  1. Request Permissions:

    1navigator.mediaDevices.getUserMedia({ audio: true })
    2 .then(stream => {
    3 // Use stream
    4 })
    5 .catch(error => {
    6 console.error("Microphone access denied:", error);
    7 // Show user instructions
    8 });
  2. Handle HTTPS Requirement:

    • Microphone access requires HTTPS (or localhost)
    • Ensure your page is served over HTTPS

Debugging Tips

Enable Verbose Logging

1ws.onopen = () => console.log("βœ“ Connected");
2ws.onmessage = (event) => {
3 console.log("πŸ“¨ Received:", JSON.parse(event.data));
4};
5ws.onerror = (error) => console.error("βœ— Error:", error);
6ws.onclose = (event) => console.log("βœ— Closed:", event.code, event.reason);

Validate Audio Before Sending

1function validateAudioChunk(chunk) {
2 if (!(chunk instanceof ArrayBuffer || chunk instanceof Uint8Array)) {
3 throw new Error("Audio chunk must be ArrayBuffer or Uint8Array");
4 }
5 if (chunk.byteLength === 0) {
6 throw new Error("Audio chunk cannot be empty");
7 }
8 if (chunk.byteLength > 8192) {
9 console.warn("Chunk size exceeds recommended 4096 bytes");
10 }
11 return true;
12}

Monitor Session State

1let sessionStats = {
2 chunksSent: 0,
3 messagesReceived: 0,
4 partialCount: 0,
5 finalCount: 0
6};
7
8ws.onmessage = (event) => {
9 sessionStats.messagesReceived++;
10 const message = JSON.parse(event.data);
11 if (message.is_final) {
12 sessionStats.finalCount++;
13 } else {
14 sessionStats.partialCount++;
15 }
16 console.log("Session stats:", sessionStats);
17};

HTTP errors

For 401, 403, 429, and 500 (including WebSocket handshake failures), see the Error reference. Browsers cannot set custom headers on WebSocket handshakes, so browser clients should authenticate via the ?token=<KEY> query parameter where supported.

Getting Help

If you continue to experience issues:

  1. Check API Status: Verify the API is operational

  2. Review Documentation: Ensure you’re following the correct API version

  3. Test with Sample Code: Use the provided examples as a baseline

  4. Note down: Reach out with:

    • Session ID (if available)
    • Error messages
    • Code snippets (sanitized of API keys)
    • Network conditions (if applicable)
  5. Reach out to us: