@memberjunction/livekit-room-server 5.43.0 → 5.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -76,16 +76,50 @@ import { LiveKitEgressService } from '@memberjunction/livekit-room-server';
|
|
|
76
76
|
|
|
77
77
|
const egress = new LiveKitEgressService();
|
|
78
78
|
const rec = await egress.StartRoomRecording({ RoomName: 'support-42' }); // → { EgressID, Status }
|
|
79
|
-
await egress.StopRecording(rec.EgressID);
|
|
79
|
+
const done = await egress.StopRecording(rec.EgressID);
|
|
80
|
+
// On stop/complete, RecordingInfo also surfaces the produced file:
|
|
81
|
+
// done.OutputLocation – the file's path/key in the egress sink
|
|
82
|
+
// done.OutputSizeBytes – byte count
|
|
83
|
+
// done.OutputDurationMs – duration in ms (normalized from the SDK's nanoseconds)
|
|
84
|
+
// These are what the server registers into MJStorage on the Meeting-Room Conversation
|
|
85
|
+
// (Conversation.RecordingFileID + EgressID). While recording is in progress they are undefined.
|
|
80
86
|
```
|
|
81
87
|
|
|
82
88
|
Egress output storage (S3 / GCS / Azure / LiveKit Cloud) is configured on the LiveKit project.
|
|
83
89
|
|
|
90
|
+
## Meeting-recording registration (egress → MJStorage → Conversation)
|
|
91
|
+
|
|
92
|
+
When the browser stops a room recording, MJServer's `RealtimeBridgeResolver.StopLiveKitRecording` calls
|
|
93
|
+
`registerMeetingRecordingFile` (`packages/MJServer/src/resolvers/meetingRecordingRegistration.ts`), which:
|
|
94
|
+
|
|
95
|
+
1. Resolves the room's **Meeting-Room Conversation** (by `EgressID`, then room name, else creates one).
|
|
96
|
+
2. Creates an **`MJ: Files`** row for the egress MP4 (`ProviderKey` = `OutputLocation`, `ContentType =
|
|
97
|
+
video/mp4`, `Status = Uploaded`). **v1 points the Files row directly at the egress output — no byte
|
|
98
|
+
copy** — so playback streams straight from the sink.
|
|
99
|
+
3. Stamps **`Conversation.RecordingFileID`** (+ `EgressID`) and returns the new file id on the result.
|
|
100
|
+
|
|
101
|
+
This requires the egress sink and the MJStorage account to target the **same** bucket/container, configured
|
|
102
|
+
via the provider:
|
|
103
|
+
|
|
104
|
+
- `MJ_MEETING_RECORDING_STORAGE_PROVIDER=<MJ: File Storage Providers ID>` (or
|
|
105
|
+
`meetingRecordingStorageProviderID` in `mj.config.cjs`).
|
|
106
|
+
|
|
107
|
+
Optional **copy-to-canonical** ("copy into Box") — set a *different* canonical provider via
|
|
108
|
+
`MJ_MEETING_RECORDING_CANONICAL_STORAGE_PROVIDER` (or `meetingRecordingCanonicalStorageProviderID`) to read
|
|
109
|
+
the bytes out of the sink and re-upload them into a separate provider, pointing the Files row there. OFF by
|
|
110
|
+
default.
|
|
111
|
+
|
|
112
|
+
Registration is **best-effort**: a missing storage provider or any failure leaves `RecordingFileID` unset
|
|
113
|
+
and logs — the stop-recording mutation still succeeds. See
|
|
114
|
+
[REALTIME_SESSION_CAPTURE_GUIDE.md](../../guides/REALTIME_SESSION_CAPTURE_GUIDE.md#meeting-room-recording-livekit-egress--mjstorage)
|
|
115
|
+
for the full loop incl. Meet-app playback.
|
|
116
|
+
|
|
84
117
|
## GraphQL surface
|
|
85
118
|
|
|
86
119
|
These are exposed to the browser via MJServer's `RealtimeBridgeResolver`:
|
|
87
|
-
`MintLiveKitClientToken`, `StartLiveKitAgentRoomSession`, `StartLiveKitRecording`, `StopLiveKitRecording
|
|
88
|
-
Call them from the browser with `GraphQLLiveKitClient` in
|
|
120
|
+
`MintLiveKitClientToken`, `StartLiveKitAgentRoomSession`, `StartLiveKitRecording`, `StopLiveKitRecording`
|
|
121
|
+
(returns `RecordingFileID` once registered). Call them from the browser with `GraphQLLiveKitClient` in
|
|
122
|
+
`@memberjunction/graphql-dataprovider`.
|
|
89
123
|
|
|
90
124
|
## License
|
|
91
125
|
|
|
@@ -32,6 +32,16 @@ export interface RecordingInfo {
|
|
|
32
32
|
RoomName: string;
|
|
33
33
|
/** The raw egress status string. */
|
|
34
34
|
Status: string;
|
|
35
|
+
/**
|
|
36
|
+
* The output file's path/key in the egress storage sink, once the egress has produced a result
|
|
37
|
+
* (populated on stop/complete). This is what a caller copies into MJStorage + records as the
|
|
38
|
+
* Conversation's recording. `undefined` while the recording is still in progress.
|
|
39
|
+
*/
|
|
40
|
+
OutputLocation?: string;
|
|
41
|
+
/** The output file size in bytes, when the egress result reports it. */
|
|
42
|
+
OutputSizeBytes?: number;
|
|
43
|
+
/** The recording duration in milliseconds, when the egress result reports it. */
|
|
44
|
+
OutputDurationMs?: number;
|
|
35
45
|
}
|
|
36
46
|
/** Starts/stops/lists LiveKit room recordings (composite egress). */
|
|
37
47
|
export declare class LiveKitEgressService {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"livekit-egress-service.d.ts","sourceRoot":"","sources":["../src/livekit-egress-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAuD,MAAM,oBAAoB,CAAC;AACvG,OAAO,EAAuB,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAExF,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mGAAmG;AACnG,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,EAAE,0BAA0B,GAAG,YAAY,GAAG,YAAY,CAAC,CAAC;AAE5G,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"livekit-egress-service.d.ts","sourceRoot":"","sources":["../src/livekit-egress-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAuD,MAAM,oBAAoB,CAAC;AACvG,OAAO,EAAuB,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAExF,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mGAAmG;AACnG,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,YAAY,EAAE,0BAA0B,GAAG,YAAY,GAAG,YAAY,CAAC,CAAC;AAE5G,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qEAAqE;AACrE,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAE1C;;;;;OAKG;gBACS,MAAM,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC,EAAE,gBAAgB;IAM5E;;;;;OAKG;IACU,kBAAkB,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC;IAOrF;;;;;OAKG;IACU,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAKpE;;;;;OAKG;IACU,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAK7E,wEAAwE;IACxE,OAAO,CAAC,eAAe;CAuBxB"}
|
|
@@ -62,7 +62,27 @@ export class LiveKitEgressService {
|
|
|
62
62
|
}
|
|
63
63
|
/** Maps an SDK `EgressInfo` to the normalized {@link RecordingInfo}. */
|
|
64
64
|
toRecordingInfo(info, roomName) {
|
|
65
|
-
|
|
65
|
+
const result = {
|
|
66
|
+
EgressID: info.egressId,
|
|
67
|
+
RoomName: info.roomName || roomName,
|
|
68
|
+
Status: String(info.status ?? 'unknown'),
|
|
69
|
+
};
|
|
70
|
+
// Once the egress has produced its file (on stop/complete), surface the output path + size +
|
|
71
|
+
// duration so a caller can copy the MP4 into MJStorage and record it on the Conversation.
|
|
72
|
+
const fileResult = info.fileResults?.[0];
|
|
73
|
+
if (fileResult) {
|
|
74
|
+
if (fileResult.filename) {
|
|
75
|
+
result.OutputLocation = fileResult.filename;
|
|
76
|
+
}
|
|
77
|
+
if (fileResult.size != null) {
|
|
78
|
+
result.OutputSizeBytes = Number(fileResult.size);
|
|
79
|
+
}
|
|
80
|
+
if (fileResult.duration != null) {
|
|
81
|
+
// EncodedFileResult.duration is reported in nanoseconds — normalize to milliseconds.
|
|
82
|
+
result.OutputDurationMs = Math.round(Number(fileResult.duration) / 1_000_000);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
66
86
|
}
|
|
67
87
|
}
|
|
68
88
|
//# sourceMappingURL=livekit-egress-service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"livekit-egress-service.js","sourceRoot":"","sources":["../src/livekit-egress-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAmB,MAAM,oBAAoB,CAAC;AACvG,OAAO,EAAE,mBAAmB,EAA4B,MAAM,yBAAyB,CAAC;AAexF,uFAAuF;AACvF,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,CAAC;
|
|
1
|
+
{"version":3,"file":"livekit-egress-service.js","sourceRoot":"","sources":["../src/livekit-egress-service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/livekit-room-server",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.44.0",
|
|
5
5
|
"description": "MemberJunction: Server-side LiveKit room support — mints scoped client/bot access tokens (livekit-server-sdk) and provides the session-start coordinator that opens a realtime model session and bridges it into a LiveKit room via AIBridgeEngine. The MJ realtime-bridge ↔ LiveKit UI seam.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
"author": "MemberJunction.com",
|
|
17
17
|
"license": "ISC",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@memberjunction/core": "5.
|
|
20
|
-
"@memberjunction/global": "5.
|
|
21
|
-
"@memberjunction/core-entities": "5.
|
|
22
|
-
"@memberjunction/ai": "5.
|
|
23
|
-
"@memberjunction/ai-bridge-base": "5.
|
|
24
|
-
"@memberjunction/ai-bridge-server": "5.
|
|
25
|
-
"@memberjunction/ai-bridge-livekit": "5.
|
|
19
|
+
"@memberjunction/core": "5.44.0",
|
|
20
|
+
"@memberjunction/global": "5.44.0",
|
|
21
|
+
"@memberjunction/core-entities": "5.44.0",
|
|
22
|
+
"@memberjunction/ai": "5.44.0",
|
|
23
|
+
"@memberjunction/ai-bridge-base": "5.44.0",
|
|
24
|
+
"@memberjunction/ai-bridge-server": "5.44.0",
|
|
25
|
+
"@memberjunction/ai-bridge-livekit": "5.44.0",
|
|
26
26
|
"livekit-server-sdk": "^2.9.7"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|