steep-balloon-41261
08/18/2025, 7:32 AMtall-airline-16756
08/18/2025, 7:32 AMtall-airline-16756
08/18/2025, 7:32 AMfierce-television-48756
08/18/2025, 7:33 AMtall-airline-16756
08/18/2025, 7:34 AMroomName
(camelCase) instead of room_name
when you’re setting up the request.
• Output Configuration: Make sure the output
field is set up correctly—as either a file output or a WebSocket URL. Like this:
const output = { case: 'websocketUrl', value: '<wss://your-service.com>' };
• Use EgressClient: Try using the startTrackEgress
method from the @livekit/server-sdk
package—it makes things a lot easier. For example:
const egressInfo = await egressClient.startTrackEgress('my-room', output, 'TR_XXXXXXXXXXXX');
• Validate Input: Make sure your roomName
and trackId
are valid strings without any special characters sneaking in.
If you’re still stuck after this, feel free to share the exact code snippet you’re using to create the TrackEgressRequest. I’d be happy to take a closer look and help you figure out what’s going on! Sources: livekit/livekit_egress.pb.go | packages/livekit-server-sdk/src/AccessToken.test.ts | cmd/lk/egress.gofierce-television-48756
08/18/2025, 8:18 AM[Egress] Starting Track Egress process. Room: ${roomName}, TrackID: ${trackId}
)*;*
if (*!*sessionId || *!*trackId || *!*roomId || *!*participantId) {
console*.*error("[Egress CRITICAL] Required IDs (sessionId, trackId, roomId, participantId) are MISSING!")*;*
return;
}
if (*!*roomName || typeof roomName !== 'string' || roomName*.*trim() === '') {
console*.*error([Egress CRITICAL] Invalid or empty roomName received: "${roomName}". Cannot start Egress.
)*;*
return;
}
// IMPORTANT: Update your NGROK URL here (for port 6081)
const websocketUrl = `wss://03a288d8b202.ngrok-free.app/?sessionId=${sessionId}&trackId=${trackId}&roomId=${roomId}&participantId=${participantId}&participantName=${encodeURIComponent(participantName)}`*;*
console*.*log([Egress] WebSocket URL created: ${websocketUrl}
)*;*
// --- FINAL FIX IS HERE (Based on LiveKit AI Assistant) ---
// The 'output' object requires a special structure for 'oneof' fields in protobuf.
const output = {
case*:* 'websocketUrl'*,*
value*:* websocketUrl*,*
}*;*
// The startTrackEgress function expects three separate arguments.
const egressInfo = await egressClient*.*startTrackEgress(
roomName*,*
output*,*
trackId
)*;*
// --- END FINAL FIX ---
console*.log(`[Egress] Track Egress started successfully. Egress ID: ${egressInfo.*_egressId_}`)*;*
// Store the Egress ID so we can stop it later
trackToEgressMap*.set(trackId,* egressInfo*.*_egressId_)*;*
return egressInfo*;*
} catch (error) {
console*.error([Egress] Error starting Track Egress for track ${trackId}:
,* error)*;*
// Don't throw the error back to the webhook, just log it
// throw error;
}
}*;*
/**
* Stops the running Egress for a track.
*/
exports*.*stopEgressForTrack = async (trackId) => {
const egressId = trackToEgressMap*.*get(trackId)*;*
if (egressId) {
try {
console*.*log([Egress] Stopping Egress for Track ID: ${trackId}, Egress ID: ${egressId}
)*;*
await egressClient*.*stopEgress(egressId)*;*
trackToEgressMap*.*delete(trackId)*;* // Cleanup is important
console*.*log([Egress] Successfully stopped Egress for track ${trackId}
)*;*
} catch (error) {
// An error can occur if Egress is already stopped, handle it
if (error*.message.*includes('Egress not found')) {
console*.*warn([Egress] Egress already stopped or not found for ID: ${egressId}
)*;*
trackToEgressMap*.*delete(trackId)*;* // Still remove from the map
} else {
console*.error([Egress] Error stopping Egress:
,* error)*;*
}
}
} else {
console*.*warn([Egress] Stop request received but no active Egress found for trackId: ${trackId}
)*;*
}
}*;*tall-airline-16756
08/18/2025, 8:18 AMoutput
field for the protobuf TrackEgressRequest
. Here are a few important things to keep in mind to make sure everything runs smoothly:
• Output Field: You’ve got the output
field correctly set up as a oneof field with case: 'websocketUrl'
and value: websocketUrl
, which fits perfectly with the protobuf requirements.
• Room Name Validation: Your check to make sure roomName
is a non-empty string is great—it helps avoid passing any invalid data.
• WebSocket URL: The WebSocket URL you’re generating dynamically looks properly formatted.
• Error Handling: Using a try-catch block to log errors without interrupting the webhook flow is a solid approach.
If you’re still running into that JSON encoding error, here are a few things you might want to double-check:
1. Make sure roomName
and trackId
are valid strings without any special or control characters.
2. Confirm that your @livekit/server-sdk
package is up-to-date to avoid any compatibility hiccups.
3. Try logging the output
object right before you pass it to startTrackEgress
to verify its structure.
If the problem keeps popping up, just let me know—we can dig into some more debugging steps together!fierce-television-48756
08/18/2025, 8:22 AMtall-airline-16756
08/18/2025, 8:23 AMnpm install @livekit/server-sdk@2.13.2
Just a quick heads-up—before you upgrade, it’s a good idea to check out the changelog to see if there are any important changes or cool new features. Let me know if you need a hand with it! Sources: pnpm-lock.yaml | packages/livekit-rtc/CHANGELOG.mdfierce-television-48756
08/18/2025, 8:23 AMtall-airline-16756
08/18/2025, 8:24 AMpackage.json
file and look for @livekit/server-sdk
under dependencies
or devDependencies
.fierce-television-48756
08/18/2025, 8:27 AMtall-airline-16756
08/18/2025, 8:27 AMnpm install @livekit/server-sdk@2.13.2
Feel free to reach out if you want a hand with the update or have any other questions—I’m here to help!fierce-television-48756
08/18/2025, 8:31 AMtall-airline-16756
08/18/2025, 8:31 AMnpm cache clean --force
• Make sure you’re connected to the right npm registry by running:
`npm config get registry`The default should be <https://registry.npmjs.org/>
. If it’s not, you can set it with:
npm config set registry <https://registry.npmjs.org/>
• Give the installation another shot with:
npm install @livekit/server-sdk@2.13.2
If you’re still having issues or want a hand with anything else, just let me know—I’m here to help! Sources: packages/livekit-server-sdk/CHANGELOG.md | pnpm-lock.yamlfierce-television-48756
08/18/2025, 3:16 PMTrackEgress
to stream a single audio track to my Node.js server via a WebSocket URL.
My server is receiving audio chunks from the Egress WebSocket (typically 1920 bytes per message), and I am piping this raw audio data directly to the Google Cloud Speech-to-Text streaming API.
The problem is that while Google STT sends back responses, the transcript
field is always empty, as if it's processing silence. My Google STT configuration is set to encoding: 'LINEAR16'
, sampleRateHertz: 16000
, and audioChannelCount: 1
.
My question is: What is the exact audio format of the data sent from a TrackEgress WebSocket stream? Is it guaranteed to be raw PCM LINEAR16
at 16kHz, mono? Is there any header or metadata within the stream that I need to strip before forwarding the audio chunks to the STT API?tall-airline-16756
08/18/2025, 3:16 PM