Skip to content

Commit acd9ceb

Browse files
[IMP] rec addr
1 parent e5aaa79 commit acd9ceb

File tree

3 files changed

+33
-6
lines changed

3 files changed

+33
-6
lines changed

src/models/channel.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ interface ChannelCreateOptions {
5454
key?: string;
5555
/** Whether to enable WebRTC functionality */
5656
useWebRtc?: boolean;
57-
useRecording?: boolean;
57+
recordingAddress?: string | null;
5858
}
5959
interface JoinResult {
6060
/** The channel instance */
@@ -106,7 +106,7 @@ export class Channel extends EventEmitter {
106106
issuer: string,
107107
options: ChannelCreateOptions = {}
108108
): Promise<Channel> {
109-
const { key, useWebRtc = true, useRecording = true } = options;
109+
const { key, useWebRtc = true, recordingAddress } = options;
110110
const safeIssuer = `${remoteAddress}::${issuer}`;
111111
const oldChannel = Channel.recordsByIssuer.get(safeIssuer);
112112
if (oldChannel) {
@@ -116,7 +116,7 @@ export class Channel extends EventEmitter {
116116
const channelOptions: ChannelCreateOptions & {
117117
worker?: Worker;
118118
router?: Router;
119-
} = { key, useRecording: useWebRtc && useRecording };
119+
} = { key, recordingAddress: useWebRtc ? recordingAddress : null };
120120
if (useWebRtc) {
121121
channelOptions.worker = await getWorker();
122122
channelOptions.router = await channelOptions.worker.createRouter({
@@ -187,7 +187,7 @@ export class Channel extends EventEmitter {
187187
const now = new Date();
188188
this.createDate = now.toISOString();
189189
this.remoteAddress = remoteAddress;
190-
this.recorder = config.recording.enabled && options.useRecording ? new Recorder(this) : undefined;
190+
this.recorder = config.recording.enabled && options.recordingAddress ? new Recorder(this, options.recordingAddress) : undefined;
191191
this.key = key ? Buffer.from(key, "base64") : undefined;
192192
this.uuid = crypto.randomUUID();
193193
this.name = `${remoteAddress}*${this.uuid.slice(-5)}`;
@@ -300,6 +300,7 @@ export class Channel extends EventEmitter {
300300
* @fires Channel#close
301301
*/
302302
close(): void {
303+
this.recorder?.stop();
303304
for (const session of this.sessions.values()) {
304305
session.off("close", this._onSessionClose);
305306
session.close({ code: SESSION_CLOSE_CODE.CHANNEL_CLOSED });

src/models/recorder.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ export class Recorder extends EventEmitter {
88
channel: Channel;
99
state: "started" | "stopped" = "stopped";
1010
ffmpeg = null;
11+
/** Path to which the final recording will be uploaded to */
12+
recordingAddress: string;
1113

12-
constructor(channel: Channel) {
14+
constructor(channel: Channel, recordingAddress: string) {
1315
super();
1416
this.channel = channel;
17+
this.recordingAddress = recordingAddress;
1518
}
1619

1720
async start() {

src/services/http.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,29 @@ function setupRoutes(routeListener: RouteListener): void {
7979
return res.end(JSON.stringify(channelStats));
8080
}
8181
});
82+
/**
83+
* GET /v1/channel
84+
*
85+
* Creates (or reuses) a media channel for the authenticated client.
86+
*
87+
* ### Headers
88+
* - `Authorization: Bearer <JWT>` — required.
89+
* The JWT must include the `iss` (issuer) claim identifying the caller.
90+
*
91+
* ### Query Parameters
92+
* - `webRTC` — optional, defaults to `"true"`.
93+
* When set to `"false"`, disables WebRTC setup and creates a non-media channel.
94+
* - `recordingAddress` — optional.
95+
* If provided, enables recording and specifies the destination address
96+
* for recorded media streams. This address should most likely include a secret token,
97+
* so that it can be used publicly. For example http://example.com/recording/123?token=asdasdasdasd
98+
*
99+
* ### Responses
100+
* - `200 OK` — returns `{ uuid: string, url: string }`
101+
* - `401 Unauthorized` — missing or invalid Authorization header
102+
* - `403 Forbidden` — missing `iss` claim
103+
* - `500 Internal Server Error` — failed to create the channel
104+
*/
82105
routeListener.get(`/v${API_VERSION}/channel`, {
83106
callback: async (req, res, { host, protocol, remoteAddress, searchParams }) => {
84107
try {
@@ -99,7 +122,7 @@ function setupRoutes(routeListener: RouteListener): void {
99122
const channel = await Channel.create(remoteAddress, claims.iss, {
100123
key: claims.key,
101124
useWebRtc: searchParams.get("webRTC") !== "false",
102-
useRecording: searchParams.get("recording") !== "false"
125+
recordingAddress: searchParams.get("recordingAddress")
103126
});
104127
res.setHeader("Content-Type", "application/json");
105128
res.statusCode = 200;

0 commit comments

Comments
 (0)