@eyepop.ai/eyepop 0.10.0 → 0.11.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 +49 -8
- package/dist/eyepop.min.js +1 -1
- package/dist/eyepop.min.js.LICENSE.txt +18 -0
- package/dist/index.d.mts +19 -6
- package/dist/index.d.ts +19 -6
- package/dist/index.js +488 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +478 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
package/dist/index.mjs
CHANGED
|
@@ -9035,6 +9035,39 @@ var LoadFromJob = class extends AbstractJob {
|
|
|
9035
9035
|
return response;
|
|
9036
9036
|
}
|
|
9037
9037
|
};
|
|
9038
|
+
var LoadLiveIngressJob = class extends AbstractJob {
|
|
9039
|
+
constructor(ingressId, getSession, client, requestLogger) {
|
|
9040
|
+
super(getSession, client, requestLogger);
|
|
9041
|
+
this._ingressId = ingressId;
|
|
9042
|
+
}
|
|
9043
|
+
get [Symbol.toStringTag]() {
|
|
9044
|
+
return "loadLiveIngressJob";
|
|
9045
|
+
}
|
|
9046
|
+
async startJob() {
|
|
9047
|
+
const body = {
|
|
9048
|
+
"sourceType": "LIVE_INGRESS",
|
|
9049
|
+
"liveIngressId": this._ingressId
|
|
9050
|
+
};
|
|
9051
|
+
const session = await this._getSession();
|
|
9052
|
+
const headers = {
|
|
9053
|
+
"Authorization": `Bearer ${session.accessToken}`,
|
|
9054
|
+
"Accept": "application/jsonl",
|
|
9055
|
+
"Content-Type": "application/json"
|
|
9056
|
+
};
|
|
9057
|
+
const patchUrl = `${session.baseUrl.replace(/\/+$/, "")}/pipelines/${session.pipelineId}/source?mode=queue&processing=sync`;
|
|
9058
|
+
this._requestLogger.debug("before PATCH %s with url %s as source", patchUrl, this._ingressId);
|
|
9059
|
+
const response = await this._client.fetch(patchUrl, {
|
|
9060
|
+
headers,
|
|
9061
|
+
method: "PATCH",
|
|
9062
|
+
body: JSON.stringify(body),
|
|
9063
|
+
signal: this._controller.signal,
|
|
9064
|
+
// @ts-ignore
|
|
9065
|
+
dispatcher: this._dispatcher
|
|
9066
|
+
});
|
|
9067
|
+
this._requestLogger.debug("after PATCH %s with url %s as source", patchUrl, this._ingressId);
|
|
9068
|
+
return response;
|
|
9069
|
+
}
|
|
9070
|
+
};
|
|
9038
9071
|
|
|
9039
9072
|
// src/shims/http_client.ts
|
|
9040
9073
|
var createHttpClient;
|
|
@@ -9203,6 +9236,374 @@ var Semaphore = class {
|
|
|
9203
9236
|
}
|
|
9204
9237
|
};
|
|
9205
9238
|
|
|
9239
|
+
// node_modules/uuid/dist/esm-node/rng.js
|
|
9240
|
+
import crypto from "crypto";
|
|
9241
|
+
var rnds8Pool = new Uint8Array(256);
|
|
9242
|
+
var poolPtr = rnds8Pool.length;
|
|
9243
|
+
function rng() {
|
|
9244
|
+
if (poolPtr > rnds8Pool.length - 16) {
|
|
9245
|
+
crypto.randomFillSync(rnds8Pool);
|
|
9246
|
+
poolPtr = 0;
|
|
9247
|
+
}
|
|
9248
|
+
return rnds8Pool.slice(poolPtr, poolPtr += 16);
|
|
9249
|
+
}
|
|
9250
|
+
|
|
9251
|
+
// node_modules/uuid/dist/esm-node/stringify.js
|
|
9252
|
+
var byteToHex = [];
|
|
9253
|
+
for (let i = 0; i < 256; ++i) {
|
|
9254
|
+
byteToHex.push((i + 256).toString(16).slice(1));
|
|
9255
|
+
}
|
|
9256
|
+
function unsafeStringify(arr, offset = 0) {
|
|
9257
|
+
return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
|
|
9258
|
+
}
|
|
9259
|
+
|
|
9260
|
+
// node_modules/uuid/dist/esm-node/native.js
|
|
9261
|
+
import crypto2 from "crypto";
|
|
9262
|
+
var native_default = {
|
|
9263
|
+
randomUUID: crypto2.randomUUID
|
|
9264
|
+
};
|
|
9265
|
+
|
|
9266
|
+
// node_modules/uuid/dist/esm-node/v4.js
|
|
9267
|
+
function v4(options, buf, offset) {
|
|
9268
|
+
if (native_default.randomUUID && !buf && !options) {
|
|
9269
|
+
return native_default.randomUUID();
|
|
9270
|
+
}
|
|
9271
|
+
options = options || {};
|
|
9272
|
+
const rnds = options.random || (options.rng || rng)();
|
|
9273
|
+
rnds[6] = rnds[6] & 15 | 64;
|
|
9274
|
+
rnds[8] = rnds[8] & 63 | 128;
|
|
9275
|
+
if (buf) {
|
|
9276
|
+
offset = offset || 0;
|
|
9277
|
+
for (let i = 0; i < 16; ++i) {
|
|
9278
|
+
buf[offset + i] = rnds[i];
|
|
9279
|
+
}
|
|
9280
|
+
return buf;
|
|
9281
|
+
}
|
|
9282
|
+
return unsafeStringify(rnds);
|
|
9283
|
+
}
|
|
9284
|
+
var v4_default = v4;
|
|
9285
|
+
|
|
9286
|
+
// src/web_rtc_base.ts
|
|
9287
|
+
var WebRtcBase = class {
|
|
9288
|
+
constructor(getSession, client, requestLogger) {
|
|
9289
|
+
this._pc = null;
|
|
9290
|
+
this._getSession = getSession;
|
|
9291
|
+
this._client = client;
|
|
9292
|
+
this._requestLogger = requestLogger;
|
|
9293
|
+
this._eTag = "";
|
|
9294
|
+
this._queuedCandidates = [];
|
|
9295
|
+
this._offerData = null;
|
|
9296
|
+
}
|
|
9297
|
+
static linkToIceServers(links) {
|
|
9298
|
+
const servers = links !== null ? links.split(", ").map((link) => {
|
|
9299
|
+
const m = link.match(/^<(.+?)>; rel="ice-server"(; username="(.*?)"; credential="(.*?)"; credential-type="password")?/i);
|
|
9300
|
+
if (!m) {
|
|
9301
|
+
return null;
|
|
9302
|
+
}
|
|
9303
|
+
const iceServer = {
|
|
9304
|
+
urls: [m[1]],
|
|
9305
|
+
username: Whip.unquoteCredential(m[3]),
|
|
9306
|
+
credential: Whip.unquoteCredential(m[4])
|
|
9307
|
+
// credentialType: m[3]? "password" : undefined
|
|
9308
|
+
};
|
|
9309
|
+
return iceServer;
|
|
9310
|
+
}) : [];
|
|
9311
|
+
return servers.filter(function(el) {
|
|
9312
|
+
return el != null;
|
|
9313
|
+
});
|
|
9314
|
+
}
|
|
9315
|
+
static editAnswer(answer, videoCodec, audioCodec, videoBitrate, audioBitrate, audioVoice) {
|
|
9316
|
+
const sections = answer.split("m=");
|
|
9317
|
+
for (let i = 0; i < sections.length; i++) {
|
|
9318
|
+
const section = sections[i];
|
|
9319
|
+
if (section.startsWith("video")) {
|
|
9320
|
+
sections[i] = Whip.setVideoBitrate(Whip.setCodec(section, videoCodec), videoBitrate);
|
|
9321
|
+
} else if (section.startsWith("audio")) {
|
|
9322
|
+
sections[i] = Whip.setAudioBitrate(Whip.setCodec(section, audioCodec), audioBitrate, audioVoice);
|
|
9323
|
+
}
|
|
9324
|
+
}
|
|
9325
|
+
return sections.join("m=");
|
|
9326
|
+
}
|
|
9327
|
+
static setCodec(section, codec) {
|
|
9328
|
+
const lines = section.split("\r\n");
|
|
9329
|
+
const lines2 = [];
|
|
9330
|
+
const payloadFormats = [];
|
|
9331
|
+
for (const line of lines) {
|
|
9332
|
+
if (!line.startsWith("a=rtpmap:")) {
|
|
9333
|
+
lines2.push(line);
|
|
9334
|
+
} else {
|
|
9335
|
+
if (codec && line.toLowerCase().includes(codec)) {
|
|
9336
|
+
payloadFormats.push(line.slice("a=rtpmap:".length).split(" ")[0]);
|
|
9337
|
+
lines2.push(line);
|
|
9338
|
+
}
|
|
9339
|
+
}
|
|
9340
|
+
}
|
|
9341
|
+
const lines3 = [];
|
|
9342
|
+
for (const line of lines2) {
|
|
9343
|
+
if (line.startsWith("a=fmtp:")) {
|
|
9344
|
+
if (payloadFormats.includes(line.slice("a=fmtp:".length).split(" ")[0])) {
|
|
9345
|
+
lines3.push(line);
|
|
9346
|
+
}
|
|
9347
|
+
} else if (line.startsWith("a=rtcp-fb:")) {
|
|
9348
|
+
if (payloadFormats.includes(line.slice("a=rtcp-fb:".length).split(" ")[0])) {
|
|
9349
|
+
lines3.push(line);
|
|
9350
|
+
}
|
|
9351
|
+
} else {
|
|
9352
|
+
lines3.push(line);
|
|
9353
|
+
}
|
|
9354
|
+
}
|
|
9355
|
+
return lines3.join("\r\n");
|
|
9356
|
+
}
|
|
9357
|
+
static setVideoBitrate(section, bitrate) {
|
|
9358
|
+
let lines = section.split("\r\n");
|
|
9359
|
+
for (let i = 0; i < lines.length; i++) {
|
|
9360
|
+
if (lines[i].startsWith("c=")) {
|
|
9361
|
+
lines = [...lines.slice(0, i + 1), "b=TIAS:" + (bitrate * 1024).toString(), ...lines.slice(i + 1)];
|
|
9362
|
+
break;
|
|
9363
|
+
}
|
|
9364
|
+
}
|
|
9365
|
+
return lines.join("\r\n");
|
|
9366
|
+
}
|
|
9367
|
+
static setAudioBitrate(section, bitrate, voice) {
|
|
9368
|
+
let opusPayloadFormat = "";
|
|
9369
|
+
let lines = section.split("\r\n");
|
|
9370
|
+
for (let i = 0; i < lines.length; i++) {
|
|
9371
|
+
if (lines[i].startsWith("a=rtpmap:") && lines[i].toLowerCase().includes("opus/")) {
|
|
9372
|
+
opusPayloadFormat = lines[i].slice("a=rtpmap:".length).split(" ")[0];
|
|
9373
|
+
break;
|
|
9374
|
+
}
|
|
9375
|
+
}
|
|
9376
|
+
if (opusPayloadFormat === "") {
|
|
9377
|
+
return section;
|
|
9378
|
+
}
|
|
9379
|
+
for (let i = 0; i < lines.length; i++) {
|
|
9380
|
+
if (lines[i].startsWith("a=fmtp:" + opusPayloadFormat + " ")) {
|
|
9381
|
+
if (voice) {
|
|
9382
|
+
lines[i] = "a=fmtp:" + opusPayloadFormat + " minptime=10;useinbandfec=1;maxaveragebitrate=" + ((bitrate ?? 0) * 1024).toString();
|
|
9383
|
+
} else {
|
|
9384
|
+
lines[i] = "a=fmtp:" + opusPayloadFormat + " maxplaybackrate=48000;stereo=1;sprop-stereo=1;maxaveragebitrate" + ((bitrate ?? 0) * 1024).toString();
|
|
9385
|
+
}
|
|
9386
|
+
}
|
|
9387
|
+
}
|
|
9388
|
+
return lines.join("\r\n");
|
|
9389
|
+
}
|
|
9390
|
+
static parseOffer(offer) {
|
|
9391
|
+
let medias = [];
|
|
9392
|
+
let iceUfrag = "";
|
|
9393
|
+
let icePwd = "";
|
|
9394
|
+
for (const line of offer.split("\r\n")) {
|
|
9395
|
+
if (line.startsWith("m=")) {
|
|
9396
|
+
medias.push(line.slice("m=".length));
|
|
9397
|
+
} else if (iceUfrag === "" && line.startsWith("a=ice-ufrag:")) {
|
|
9398
|
+
iceUfrag = line.slice("a=ice-ufrag:".length);
|
|
9399
|
+
} else if (icePwd === "" && line.startsWith("a=ice-pwd:")) {
|
|
9400
|
+
icePwd = line.slice("a=ice-pwd:".length);
|
|
9401
|
+
}
|
|
9402
|
+
}
|
|
9403
|
+
return {
|
|
9404
|
+
iceUfrag,
|
|
9405
|
+
icePwd,
|
|
9406
|
+
medias
|
|
9407
|
+
};
|
|
9408
|
+
}
|
|
9409
|
+
static generateSdpFragment(offerData, candidates) {
|
|
9410
|
+
const candidatesByMedia = /* @__PURE__ */ new Map();
|
|
9411
|
+
for (const candidate of candidates) {
|
|
9412
|
+
if (candidate.sdpMLineIndex !== null) {
|
|
9413
|
+
const mid2 = candidate.sdpMLineIndex;
|
|
9414
|
+
let matched = candidatesByMedia.get(mid2);
|
|
9415
|
+
if (matched === void 0) {
|
|
9416
|
+
matched = [];
|
|
9417
|
+
candidatesByMedia.set(mid2, matched);
|
|
9418
|
+
}
|
|
9419
|
+
matched.push(candidate);
|
|
9420
|
+
}
|
|
9421
|
+
}
|
|
9422
|
+
let frag = "a=ice-ufrag:" + offerData.iceUfrag + "\r\na=ice-pwd:" + offerData.icePwd + "\r\n";
|
|
9423
|
+
let mid = 0;
|
|
9424
|
+
for (const media of offerData.medias) {
|
|
9425
|
+
let matched = candidatesByMedia.get(mid);
|
|
9426
|
+
if (matched !== void 0) {
|
|
9427
|
+
frag += "m=" + media + "\r\na=mid:" + mid + "\r\n";
|
|
9428
|
+
for (const candidate of matched) {
|
|
9429
|
+
frag += "a=" + candidate.candidate + "\r\n";
|
|
9430
|
+
}
|
|
9431
|
+
}
|
|
9432
|
+
mid++;
|
|
9433
|
+
}
|
|
9434
|
+
return frag;
|
|
9435
|
+
}
|
|
9436
|
+
static unquoteCredential(v) {
|
|
9437
|
+
if (!v) {
|
|
9438
|
+
return "";
|
|
9439
|
+
}
|
|
9440
|
+
return JSON.parse(`"${v}"`);
|
|
9441
|
+
}
|
|
9442
|
+
};
|
|
9443
|
+
|
|
9444
|
+
// src/whip.ts
|
|
9445
|
+
var Whip = class _Whip extends WebRtcBase {
|
|
9446
|
+
constructor(stream, getSession, client, requestLogger) {
|
|
9447
|
+
super(getSession, client, requestLogger);
|
|
9448
|
+
this._ingressId = v4_default().toString();
|
|
9449
|
+
this._stream = stream;
|
|
9450
|
+
}
|
|
9451
|
+
ingressId() {
|
|
9452
|
+
if (!this._ingressId) {
|
|
9453
|
+
throw new Error("not initialized");
|
|
9454
|
+
}
|
|
9455
|
+
return this._ingressId;
|
|
9456
|
+
}
|
|
9457
|
+
async start() {
|
|
9458
|
+
const session = await this._getSession();
|
|
9459
|
+
const ingressUrl = new URL("/liveIngress/whip/" + this._ingressId, session.baseUrl);
|
|
9460
|
+
this._requestLogger.debug("before GET: %s", ingressUrl);
|
|
9461
|
+
const headers = {
|
|
9462
|
+
"Authorization": `Bearer ${session.accessToken}`
|
|
9463
|
+
};
|
|
9464
|
+
const response = await this._client.fetch(ingressUrl, {
|
|
9465
|
+
headers,
|
|
9466
|
+
method: "GET"
|
|
9467
|
+
});
|
|
9468
|
+
if (response.status >= 300) {
|
|
9469
|
+
return Promise.reject(`unknown status code for GET '${ingressUrl}': ${response.status} (${response.statusText})`);
|
|
9470
|
+
}
|
|
9471
|
+
return this.onIceServers(response);
|
|
9472
|
+
}
|
|
9473
|
+
async onIceServers(response) {
|
|
9474
|
+
if (!this._stream) {
|
|
9475
|
+
throw new Error("onIceServers no stream");
|
|
9476
|
+
}
|
|
9477
|
+
const stream = this._stream;
|
|
9478
|
+
const pc = new RTCPeerConnection({
|
|
9479
|
+
iceServers: _Whip.linkToIceServers(response.headers.get("Link"))
|
|
9480
|
+
});
|
|
9481
|
+
this._pc = pc;
|
|
9482
|
+
pc.onicecandidate = (evt) => this.onLocalCandidate(evt);
|
|
9483
|
+
return new Promise(async (resolve2, reject) => {
|
|
9484
|
+
pc.oniceconnectionstatechange = () => {
|
|
9485
|
+
switch (pc.iceConnectionState) {
|
|
9486
|
+
case "failed":
|
|
9487
|
+
case "disconnected":
|
|
9488
|
+
reject(`peer connection: ${pc.iceConnectionState}`);
|
|
9489
|
+
break;
|
|
9490
|
+
case "connected":
|
|
9491
|
+
resolve2(this);
|
|
9492
|
+
break;
|
|
9493
|
+
}
|
|
9494
|
+
};
|
|
9495
|
+
stream.getTracks().forEach((track) => {
|
|
9496
|
+
this._requestLogger.debug("onIceServers our stream has track: %s", track);
|
|
9497
|
+
pc.addTrack(track, stream);
|
|
9498
|
+
});
|
|
9499
|
+
stream.addEventListener("addtrack", (trackEvent) => {
|
|
9500
|
+
this._requestLogger.debug("onIceServers got lazy track: ", trackEvent.track);
|
|
9501
|
+
pc.addTrack(trackEvent.track, stream);
|
|
9502
|
+
});
|
|
9503
|
+
await this.onLocalOffer(await pc.createOffer());
|
|
9504
|
+
});
|
|
9505
|
+
}
|
|
9506
|
+
async onLocalCandidate(evt) {
|
|
9507
|
+
if (evt.candidate !== null) {
|
|
9508
|
+
if (this._eTag === "") {
|
|
9509
|
+
this._queuedCandidates.push(evt.candidate);
|
|
9510
|
+
} else {
|
|
9511
|
+
await this.sendLocalCandidates([evt.candidate]);
|
|
9512
|
+
}
|
|
9513
|
+
}
|
|
9514
|
+
return this;
|
|
9515
|
+
}
|
|
9516
|
+
async onLocalOffer(offer) {
|
|
9517
|
+
if (!this._pc) {
|
|
9518
|
+
throw new Error("onLocalOffer no peer connection");
|
|
9519
|
+
}
|
|
9520
|
+
if (!offer.sdp) {
|
|
9521
|
+
throw new Error("onLocalOffer no sdp");
|
|
9522
|
+
}
|
|
9523
|
+
this._offerData = _Whip.parseOffer(offer.sdp);
|
|
9524
|
+
await this._pc.setLocalDescription(offer);
|
|
9525
|
+
const session = await this._getSession();
|
|
9526
|
+
const ingressUrl = new URL("/liveIngress/whip/" + this._ingressId, session.baseUrl);
|
|
9527
|
+
this._requestLogger.debug("before GET: %s", ingressUrl);
|
|
9528
|
+
const headers = {
|
|
9529
|
+
"Authorization": `Bearer ${session.accessToken}`,
|
|
9530
|
+
"Content-Type": "application/sdp"
|
|
9531
|
+
};
|
|
9532
|
+
const response = await this._client.fetch(ingressUrl, {
|
|
9533
|
+
headers,
|
|
9534
|
+
method: "POST",
|
|
9535
|
+
body: offer.sdp
|
|
9536
|
+
});
|
|
9537
|
+
if (response.status != 201) {
|
|
9538
|
+
return Promise.reject(`unknown status code for POST '${ingressUrl}': ${response.status} (${response.statusText})`);
|
|
9539
|
+
}
|
|
9540
|
+
this._eTag = response.headers.get("ETag") ?? "";
|
|
9541
|
+
return this.onRemoteAnswer(new RTCSessionDescription({
|
|
9542
|
+
type: "answer",
|
|
9543
|
+
sdp: await response.text()
|
|
9544
|
+
}));
|
|
9545
|
+
}
|
|
9546
|
+
async onRemoteAnswer(answer) {
|
|
9547
|
+
if (!this._pc) {
|
|
9548
|
+
throw new Error("onLocalOffer no peer connection");
|
|
9549
|
+
}
|
|
9550
|
+
answer = new RTCSessionDescription({
|
|
9551
|
+
type: "answer",
|
|
9552
|
+
sdp: _Whip.editAnswer(
|
|
9553
|
+
answer.sdp,
|
|
9554
|
+
"h264/90000",
|
|
9555
|
+
void 0,
|
|
9556
|
+
5e3,
|
|
9557
|
+
void 0,
|
|
9558
|
+
true
|
|
9559
|
+
)
|
|
9560
|
+
});
|
|
9561
|
+
await this._pc.setRemoteDescription(new RTCSessionDescription(answer));
|
|
9562
|
+
if (this._queuedCandidates.length !== 0) {
|
|
9563
|
+
await this.sendLocalCandidates(this._queuedCandidates);
|
|
9564
|
+
this._queuedCandidates = [];
|
|
9565
|
+
}
|
|
9566
|
+
return this;
|
|
9567
|
+
}
|
|
9568
|
+
async sendLocalCandidates(candidates) {
|
|
9569
|
+
if (!this._offerData) {
|
|
9570
|
+
throw new Error("sendLocalCandidates no offerData");
|
|
9571
|
+
}
|
|
9572
|
+
const session = await this._getSession();
|
|
9573
|
+
const ingressUrl = new URL("/liveIngress/whip/" + this._ingressId, session.baseUrl);
|
|
9574
|
+
this._requestLogger.debug("before PATCH: %s", ingressUrl);
|
|
9575
|
+
const headers = {
|
|
9576
|
+
"Authorization": `Bearer ${session.accessToken}`,
|
|
9577
|
+
"Content-Type": "application/trickle-ice-sdpfrag",
|
|
9578
|
+
"If-Match": this._eTag
|
|
9579
|
+
};
|
|
9580
|
+
const response = await this._client.fetch(ingressUrl, {
|
|
9581
|
+
headers,
|
|
9582
|
+
method: "PATCH",
|
|
9583
|
+
body: _Whip.generateSdpFragment(this._offerData, candidates)
|
|
9584
|
+
});
|
|
9585
|
+
if (response.status != 204) {
|
|
9586
|
+
return Promise.reject(`unknown status code for PATCH '${ingressUrl}': ${response.status} (${response.statusText})`);
|
|
9587
|
+
}
|
|
9588
|
+
return this;
|
|
9589
|
+
}
|
|
9590
|
+
async close() {
|
|
9591
|
+
const pc = this._pc;
|
|
9592
|
+
const stream = this._stream;
|
|
9593
|
+
this._stream = null;
|
|
9594
|
+
this._pc = null;
|
|
9595
|
+
if (stream) {
|
|
9596
|
+
const tracks = stream.getTracks();
|
|
9597
|
+
tracks.forEach((track) => {
|
|
9598
|
+
track.stop();
|
|
9599
|
+
});
|
|
9600
|
+
}
|
|
9601
|
+
if (pc) {
|
|
9602
|
+
return pc.close();
|
|
9603
|
+
}
|
|
9604
|
+
}
|
|
9605
|
+
};
|
|
9606
|
+
|
|
9206
9607
|
// src/shims/local_file.ts
|
|
9207
9608
|
var resolve;
|
|
9208
9609
|
if ("document" in globalThis && "implementation" in globalThis.document) {
|
|
@@ -9258,6 +9659,8 @@ var Endpoint = class {
|
|
|
9258
9659
|
this._client = null;
|
|
9259
9660
|
this._state = "Idle" /* Idle */;
|
|
9260
9661
|
this._stateChangeHandler = null;
|
|
9662
|
+
this._ingressEventHandler = null;
|
|
9663
|
+
this._ingressEventWs = null;
|
|
9261
9664
|
this._limit = new Semaphore(this._options.jobQueueLength ?? 1024);
|
|
9262
9665
|
let rootLogger;
|
|
9263
9666
|
if (options.logger) {
|
|
@@ -9272,6 +9675,51 @@ var Endpoint = class {
|
|
|
9272
9675
|
this._stateChangeHandler = handler;
|
|
9273
9676
|
return this;
|
|
9274
9677
|
}
|
|
9678
|
+
async startIngressWs() {
|
|
9679
|
+
if (this._ingressEventWs || !this._baseUrl || !this._client) {
|
|
9680
|
+
return;
|
|
9681
|
+
}
|
|
9682
|
+
try {
|
|
9683
|
+
const getTokenUrl = `${this._baseUrl}/liveIngress/events/token`;
|
|
9684
|
+
const headers = {
|
|
9685
|
+
"Authorization": await this.authorizationHeader()
|
|
9686
|
+
};
|
|
9687
|
+
this._requestLogger.debug("before GET %s", getTokenUrl);
|
|
9688
|
+
let response = await this._client.fetch(getTokenUrl, { headers });
|
|
9689
|
+
if (response.status == 401) {
|
|
9690
|
+
this._requestLogger.debug("after GET %s: 401, about to retry with fresh access token", getTokenUrl);
|
|
9691
|
+
this._token = null;
|
|
9692
|
+
const headers2 = {
|
|
9693
|
+
"Authorization": await this.authorizationHeader()
|
|
9694
|
+
};
|
|
9695
|
+
this.updateState("FetchConfig" /* FetchConfig */);
|
|
9696
|
+
response = await this._client.fetch(getTokenUrl, { headers: headers2 });
|
|
9697
|
+
}
|
|
9698
|
+
if (response.status != 200) {
|
|
9699
|
+
const message = await response.text();
|
|
9700
|
+
return Promise.reject(`Unexpected status ${response.status}: ${message}`);
|
|
9701
|
+
}
|
|
9702
|
+
const wsAuthToken = await response.json();
|
|
9703
|
+
const wsUrl = this._baseUrl.startsWith("https://") ? `${this._baseUrl.replace("https://", "wss://")}/liveIngress/events/${wsAuthToken.token}` : `${this._baseUrl.replace("http://", "ws://")}/liveIngress/events/${wsAuthToken.token}`;
|
|
9704
|
+
this._ingressEventWs = new WebSocket(wsUrl);
|
|
9705
|
+
this._ingressEventWs.addEventListener("message", (event) => {
|
|
9706
|
+
const ingressEvent = JSON.parse(event.data);
|
|
9707
|
+
if (this._ingressEventHandler) {
|
|
9708
|
+
this._ingressEventHandler(ingressEvent);
|
|
9709
|
+
}
|
|
9710
|
+
});
|
|
9711
|
+
} finally {
|
|
9712
|
+
this.updateState();
|
|
9713
|
+
}
|
|
9714
|
+
}
|
|
9715
|
+
onIngressEvent(handler) {
|
|
9716
|
+
this._ingressEventHandler = handler;
|
|
9717
|
+
this.startIngressWs().then(() => {
|
|
9718
|
+
}).catch((reason) => {
|
|
9719
|
+
this._logger.warn("unexpected error starting the ingress event handler: %s", reason);
|
|
9720
|
+
});
|
|
9721
|
+
return this;
|
|
9722
|
+
}
|
|
9275
9723
|
state() {
|
|
9276
9724
|
return this._state;
|
|
9277
9725
|
}
|
|
@@ -9304,9 +9752,18 @@ var Endpoint = class {
|
|
|
9304
9752
|
pipelineId: this._pipelineId
|
|
9305
9753
|
};
|
|
9306
9754
|
}
|
|
9755
|
+
async liveIngress(stream) {
|
|
9756
|
+
if (!this._baseUrl || !this._client) {
|
|
9757
|
+
return Promise.reject("endpoint not connected, use connect() before ingress()");
|
|
9758
|
+
}
|
|
9759
|
+
const job = new Whip(stream, async () => {
|
|
9760
|
+
return this.session();
|
|
9761
|
+
}, this._client, this._requestLogger);
|
|
9762
|
+
return job.start();
|
|
9763
|
+
}
|
|
9307
9764
|
async upload(params) {
|
|
9308
9765
|
if (!this._baseUrl || !this._pipelineId || !this._client || !this._limit) {
|
|
9309
|
-
return Promise.reject("endpoint not connected, use
|
|
9766
|
+
return Promise.reject("endpoint not connected, use connect() before upload()");
|
|
9310
9767
|
}
|
|
9311
9768
|
params = await resolve(params);
|
|
9312
9769
|
if (!params.mimeType) {
|
|
@@ -9325,7 +9782,7 @@ var Endpoint = class {
|
|
|
9325
9782
|
}
|
|
9326
9783
|
async loadFrom(location) {
|
|
9327
9784
|
if (!this._baseUrl || !this._pipelineId || !this._client || !this._limit) {
|
|
9328
|
-
throw new Error("endpoint not connected, use
|
|
9785
|
+
throw new Error("endpoint not connected, use connect() before loadFrom()");
|
|
9329
9786
|
}
|
|
9330
9787
|
await this._limit.acquire();
|
|
9331
9788
|
this.updateState();
|
|
@@ -9338,6 +9795,21 @@ var Endpoint = class {
|
|
|
9338
9795
|
this.jobStatus(job, statusCode);
|
|
9339
9796
|
});
|
|
9340
9797
|
}
|
|
9798
|
+
async loadLiveIngress(ingressId) {
|
|
9799
|
+
if (!this._baseUrl || !this._pipelineId || !this._client || !this._limit) {
|
|
9800
|
+
throw new Error("endpoint not connected, use connect() before loadLiveIngress()");
|
|
9801
|
+
}
|
|
9802
|
+
await this._limit.acquire();
|
|
9803
|
+
this.updateState();
|
|
9804
|
+
const job = new LoadLiveIngressJob(ingressId, async () => {
|
|
9805
|
+
return this.session();
|
|
9806
|
+
}, this._client, this._requestLogger);
|
|
9807
|
+
return job.start(() => {
|
|
9808
|
+
this.jobDone(job);
|
|
9809
|
+
}, (statusCode) => {
|
|
9810
|
+
this.jobStatus(job, statusCode);
|
|
9811
|
+
});
|
|
9812
|
+
}
|
|
9341
9813
|
// noinspection TypeScriptValidateTypes
|
|
9342
9814
|
async connect() {
|
|
9343
9815
|
if (this._client) {
|
|
@@ -9375,6 +9847,9 @@ var Endpoint = class {
|
|
|
9375
9847
|
}
|
|
9376
9848
|
this._requestLogger.debug("after PATCH %s", stop_url);
|
|
9377
9849
|
}
|
|
9850
|
+
if (!this._ingressEventWs && this._ingressEventHandler) {
|
|
9851
|
+
await this.startIngressWs();
|
|
9852
|
+
}
|
|
9378
9853
|
return result;
|
|
9379
9854
|
}
|
|
9380
9855
|
jobDone(job) {
|
|
@@ -9537,7 +10012,7 @@ var _EyePopPlot = class _EyePopPlot {
|
|
|
9537
10012
|
}
|
|
9538
10013
|
}
|
|
9539
10014
|
}
|
|
9540
|
-
object(obj, x_scale, y_scale) {
|
|
10015
|
+
object(obj, x_scale = 1, y_scale = 1) {
|
|
9541
10016
|
const context = this._context;
|
|
9542
10017
|
const x = obj.x * x_scale;
|
|
9543
10018
|
const y = obj.y * y_scale;
|