@daydreamlive/browser 0.2.0 → 0.3.1

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/dist/index.cjs CHANGED
@@ -196,7 +196,6 @@ var WHIPClient = class {
196
196
  await this.audioSender.replaceTrack(audioTrack);
197
197
  }
198
198
  this.setCodecPreferences();
199
- await this.applyBitrateConstraints();
200
199
  const offer = await this.pc.createOffer({
201
200
  offerToReceiveAudio: false,
202
201
  offerToReceiveVideo: false
@@ -368,6 +367,9 @@ var WHIPClient = class {
368
367
  this.abortController = null;
369
368
  }
370
369
  if (this.pc) {
370
+ this.pc.oniceconnectionstatechange = null;
371
+ this.pc.onconnectionstatechange = null;
372
+ this.pc.ontrack = null;
371
373
  try {
372
374
  this.pc.getTransceivers().forEach((t) => {
373
375
  try {
@@ -410,7 +412,9 @@ var WHIPClient = class {
410
412
  }
411
413
  }
412
414
  isConnected() {
413
- return this.pc !== null && this.pc.connectionState === "connected";
415
+ if (!this.pc) return false;
416
+ const iceState = this.pc.iceConnectionState;
417
+ return iceState === "connected" || iceState === "completed";
414
418
  }
415
419
  getUrlWithCachedRedirect() {
416
420
  const originalUrl = new URL(this.url);
@@ -590,10 +594,10 @@ var Broadcast = class extends TypedEventEmitter {
590
594
  setupConnectionMonitoring() {
591
595
  const pc = this.whipClient.getPeerConnection();
592
596
  if (!pc) return;
593
- pc.onconnectionstatechange = () => {
597
+ pc.oniceconnectionstatechange = () => {
594
598
  if (this.state === "ended") return;
595
- const connState = pc.connectionState;
596
- if (connState === "connected") {
599
+ const iceState = pc.iceConnectionState;
600
+ if (iceState === "connected" || iceState === "completed") {
597
601
  this.clearGraceTimeout();
598
602
  if (this.state === "reconnecting") {
599
603
  this.stateMachine.transition("live");
@@ -601,19 +605,19 @@ var Broadcast = class extends TypedEventEmitter {
601
605
  }
602
606
  return;
603
607
  }
604
- if (connState === "disconnected") {
608
+ if (iceState === "disconnected") {
605
609
  this.clearGraceTimeout();
606
610
  this.whipClient.restartIce();
607
611
  this.disconnectedGraceTimeout = setTimeout(() => {
608
612
  if (this.state === "ended") return;
609
- const currentState = pc.connectionState;
613
+ const currentState = pc.iceConnectionState;
610
614
  if (currentState === "disconnected") {
611
615
  this.scheduleReconnect();
612
616
  }
613
617
  }, 2e3);
614
618
  return;
615
619
  }
616
- if (connState === "failed" || connState === "closed") {
620
+ if (iceState === "failed" || iceState === "closed") {
617
621
  this.clearGraceTimeout();
618
622
  this.scheduleReconnect();
619
623
  }
@@ -716,6 +720,7 @@ var WHEPClient = class {
716
720
  this.url = config.url;
717
721
  this.iceServers = config.iceServers ?? DEFAULT_ICE_SERVERS;
718
722
  this.connectionTimeout = config.connectionTimeout ?? DEFAULT_CONNECTION_TIMEOUT2;
723
+ this.skipIceGathering = config.skipIceGathering ?? true;
719
724
  this.onStats = config.onStats;
720
725
  this.statsIntervalMs = config.statsIntervalMs ?? 5e3;
721
726
  this.pcFactory = config.peerConnectionFactory ?? defaultPeerConnectionFactory;
@@ -741,7 +746,9 @@ var WHEPClient = class {
741
746
  };
742
747
  const offer = await this.pc.createOffer();
743
748
  await this.pc.setLocalDescription(offer);
744
- await this.waitForIceGathering();
749
+ if (!this.skipIceGathering) {
750
+ await this.waitForIceGathering();
751
+ }
745
752
  this.abortController = new AbortController();
746
753
  const timeoutId = this.timers.setTimeout(
747
754
  () => this.abortController?.abort(),
@@ -840,6 +847,9 @@ var WHEPClient = class {
840
847
  this.abortController = null;
841
848
  }
842
849
  if (this.pc) {
850
+ this.pc.oniceconnectionstatechange = null;
851
+ this.pc.onconnectionstatechange = null;
852
+ this.pc.ontrack = null;
843
853
  try {
844
854
  this.pc.getTransceivers().forEach((t) => {
845
855
  try {
@@ -924,7 +934,10 @@ var Player = class extends TypedEventEmitter {
924
934
  get reconnectInfo() {
925
935
  if (this.state !== "buffering") return null;
926
936
  const baseDelay = this.reconnectConfig.baseDelayMs ?? 200;
927
- const delay = this.calculateReconnectDelay(this.reconnectAttempts - 1, baseDelay);
937
+ const delay = this.calculateReconnectDelay(
938
+ this.reconnectAttempts - 1,
939
+ baseDelay
940
+ );
928
941
  return {
929
942
  attempt: this.reconnectAttempts,
930
943
  maxAttempts: this.reconnectConfig.maxAttempts ?? 30,
@@ -1014,14 +1027,14 @@ var Player = class extends TypedEventEmitter {
1014
1027
  this.stateMachine.transition("ended");
1015
1028
  return;
1016
1029
  }
1017
- const maxAttempts = this.reconnectConfig.maxAttempts ?? 10;
1030
+ const maxAttempts = this.reconnectConfig.maxAttempts ?? 30;
1018
1031
  if (this.reconnectAttempts >= maxAttempts) {
1019
1032
  this.stateMachine.transition("ended");
1020
1033
  return;
1021
1034
  }
1022
1035
  this.clearReconnectTimeout();
1023
1036
  this.stateMachine.transition("buffering");
1024
- const baseDelay = this.reconnectConfig.baseDelayMs ?? 300;
1037
+ const baseDelay = this.reconnectConfig.baseDelayMs ?? 200;
1025
1038
  const delay = this.calculateReconnectDelay(
1026
1039
  this.reconnectAttempts,
1027
1040
  baseDelay
@@ -1066,6 +1079,7 @@ function createPlayer(whepUrl, options) {
1066
1079
  whepConfig: {
1067
1080
  iceServers: options?.iceServers,
1068
1081
  connectionTimeout: options?.connectionTimeout,
1082
+ skipIceGathering: options?.skipIceGathering,
1069
1083
  onStats: options?.onStats,
1070
1084
  statsIntervalMs: options?.statsIntervalMs
1071
1085
  }
@@ -1120,18 +1134,12 @@ function createRenderer(options) {
1120
1134
  height: options.height,
1121
1135
  dpr: Math.min(2, options.dpr)
1122
1136
  };
1123
- let crossfadeMs = options.crossfadeMs;
1124
1137
  let keepalive = options.keepalive;
1125
1138
  let captureCanvas = null;
1126
1139
  let captureCtx = null;
1127
1140
  let offscreen = null;
1128
1141
  let offscreenCtx = null;
1129
- let crossfadeCanvas = null;
1130
- let crossfadeCtx = null;
1131
1142
  let currentSource = null;
1132
- let pendingSource = null;
1133
- let crossfadeStart = null;
1134
- let cleanupFn = void 0;
1135
1143
  let frameIndex = 0;
1136
1144
  let rectCache = /* @__PURE__ */ new WeakMap();
1137
1145
  function initCanvas() {
@@ -1168,25 +1176,6 @@ function createRenderer(options) {
1168
1176
  offscreen = off;
1169
1177
  offscreenCtx = offCtx;
1170
1178
  }
1171
- try {
1172
- const cfCanvas = new OffscreenCanvas(pxW, pxH);
1173
- crossfadeCanvas = cfCanvas;
1174
- const cfCtx = cfCanvas.getContext("2d", { alpha: true });
1175
- if (cfCtx) {
1176
- cfCtx.imageSmoothingEnabled = true;
1177
- crossfadeCtx = cfCtx;
1178
- }
1179
- } catch {
1180
- const cfCanvas = document.createElement("canvas");
1181
- cfCanvas.width = pxW;
1182
- cfCanvas.height = pxH;
1183
- const cfCtx = cfCanvas.getContext("2d", { alpha: true });
1184
- if (cfCtx) {
1185
- cfCtx.imageSmoothingEnabled = true;
1186
- crossfadeCanvas = cfCanvas;
1187
- crossfadeCtx = cfCtx;
1188
- }
1189
- }
1190
1179
  offscreenCtx.fillStyle = "#111";
1191
1180
  offscreenCtx.fillRect(0, 0, pxW, pxH);
1192
1181
  captureCtx.drawImage(
@@ -1206,11 +1195,8 @@ function createRenderer(options) {
1206
1195
  const v = source.element;
1207
1196
  return typeof v.readyState === "number" && v.readyState >= 2 && (v.videoWidth || 0) > 0 && (v.videoHeight || 0) > 0;
1208
1197
  }
1209
- if (source.kind === "canvas") {
1210
- const c = source.element;
1211
- return (c.width || 0) > 0 && (c.height || 0) > 0;
1212
- }
1213
- return true;
1198
+ const c = source.element;
1199
+ return (c.width || 0) > 0 && (c.height || 0) > 0;
1214
1200
  }
1215
1201
  function getDrawRect(el, fit) {
1216
1202
  const canvas = offscreenCtx?.canvas;
@@ -1242,46 +1228,19 @@ function createRenderer(options) {
1242
1228
  });
1243
1229
  return { dx, dy, dw, dh };
1244
1230
  }
1245
- function blitSource(source, alpha, timestamp) {
1231
+ function blitSource(source) {
1246
1232
  if (!offscreenCtx) return;
1247
1233
  const ctx = offscreenCtx;
1248
- if (source.kind === "custom") {
1249
- if (alpha < 1 && crossfadeCtx && crossfadeCanvas) {
1250
- crossfadeCtx.clearRect(
1251
- 0,
1252
- 0,
1253
- crossfadeCtx.canvas.width,
1254
- crossfadeCtx.canvas.height
1255
- );
1256
- if (source.onFrame) source.onFrame(crossfadeCtx, timestamp);
1257
- const prev2 = ctx.globalAlpha;
1258
- try {
1259
- ctx.globalAlpha = Math.max(0, Math.min(1, alpha));
1260
- ctx.drawImage(crossfadeCanvas, 0, 0);
1261
- } finally {
1262
- ctx.globalAlpha = prev2;
1263
- }
1264
- } else {
1265
- if (source.onFrame) source.onFrame(ctx, timestamp);
1266
- }
1267
- return;
1268
- }
1269
1234
  const el = source.element;
1270
1235
  const rect = getDrawRect(el, source.fit ?? "contain");
1271
1236
  if (!rect) return;
1272
- const prev = ctx.globalAlpha;
1273
- try {
1274
- ctx.globalAlpha = Math.max(0, Math.min(1, alpha));
1275
- ctx.drawImage(
1276
- el,
1277
- rect.dx,
1278
- rect.dy,
1279
- rect.dw,
1280
- rect.dh
1281
- );
1282
- } finally {
1283
- ctx.globalAlpha = prev;
1284
- }
1237
+ ctx.drawImage(
1238
+ el,
1239
+ rect.dx,
1240
+ rect.dy,
1241
+ rect.dw,
1242
+ rect.dh
1243
+ );
1285
1244
  }
1286
1245
  initCanvas();
1287
1246
  return {
@@ -1296,57 +1255,18 @@ function createRenderer(options) {
1296
1255
  },
1297
1256
  isSourceReady,
1298
1257
  setActiveSource(source) {
1299
- if (cleanupFn) {
1300
- cleanupFn();
1301
- cleanupFn = void 0;
1302
- }
1303
- if (source === null) {
1304
- currentSource = null;
1305
- pendingSource = null;
1306
- crossfadeStart = null;
1307
- return;
1308
- }
1309
- pendingSource = source;
1310
- crossfadeStart = null;
1311
- if (source.kind === "custom" && source.onStart) {
1312
- const cleanup = source.onStart(offscreenCtx);
1313
- cleanupFn = cleanup || void 0;
1314
- return cleanupFn;
1315
- }
1258
+ currentSource = source;
1316
1259
  },
1317
- renderFrame(timestamp) {
1260
+ renderFrame(_timestamp) {
1318
1261
  const off = offscreenCtx;
1319
1262
  const cap = captureCtx;
1320
1263
  const capCanvas = captureCanvas;
1321
1264
  if (!off || !cap || !capCanvas) return;
1322
- if (pendingSource && isSourceReady(pendingSource)) {
1323
- if (crossfadeStart === null) crossfadeStart = timestamp;
1324
- }
1325
1265
  off.globalCompositeOperation = "source-over";
1326
- const willDraw = !!(pendingSource && isSourceReady(pendingSource) || currentSource);
1327
- if (willDraw) {
1266
+ if (currentSource && isSourceReady(currentSource)) {
1328
1267
  off.fillStyle = "#000";
1329
1268
  off.fillRect(0, 0, off.canvas.width, off.canvas.height);
1330
- }
1331
- const fading = pendingSource && crossfadeStart !== null && currentSource;
1332
- if (fading) {
1333
- const t = Math.min(1, (timestamp - crossfadeStart) / crossfadeMs);
1334
- blitSource(currentSource, 1 - t, timestamp);
1335
- blitSource(pendingSource, t, timestamp);
1336
- if (t >= 1) {
1337
- currentSource = pendingSource;
1338
- pendingSource = null;
1339
- crossfadeStart = null;
1340
- }
1341
- } else if (pendingSource && !currentSource) {
1342
- if (isSourceReady(pendingSource)) {
1343
- blitSource(pendingSource, 1, timestamp);
1344
- currentSource = pendingSource;
1345
- pendingSource = null;
1346
- crossfadeStart = null;
1347
- }
1348
- } else if (currentSource) {
1349
- blitSource(currentSource, 1, timestamp);
1269
+ blitSource(currentSource);
1350
1270
  }
1351
1271
  if (keepalive) {
1352
1272
  const w = off.canvas.width;
@@ -1396,34 +1316,17 @@ function createRenderer(options) {
1396
1316
  offscreen.width = pxW;
1397
1317
  offscreen.height = pxH;
1398
1318
  }
1399
- if (crossfadeCanvas instanceof HTMLCanvasElement) {
1400
- crossfadeCanvas.width = pxW;
1401
- crossfadeCanvas.height = pxH;
1402
- } else if (crossfadeCanvas instanceof OffscreenCanvas) {
1403
- crossfadeCanvas.width = pxW;
1404
- crossfadeCanvas.height = pxH;
1405
- }
1406
1319
  rectCache = /* @__PURE__ */ new WeakMap();
1407
1320
  },
1408
- setCrossfadeMs(ms) {
1409
- crossfadeMs = Math.max(0, ms);
1410
- },
1411
1321
  setKeepalive(enabled) {
1412
1322
  keepalive = enabled;
1413
1323
  },
1414
1324
  destroy() {
1415
- if (cleanupFn) {
1416
- cleanupFn();
1417
- cleanupFn = void 0;
1418
- }
1419
1325
  currentSource = null;
1420
- pendingSource = null;
1421
1326
  captureCanvas = null;
1422
1327
  captureCtx = null;
1423
1328
  offscreen = null;
1424
1329
  offscreenCtx = null;
1425
- crossfadeCanvas = null;
1426
- crossfadeCtx = null;
1427
1330
  }
1428
1331
  };
1429
1332
  }
@@ -1958,7 +1861,6 @@ var Compositor = class extends CompositorEventEmitter {
1958
1861
  2,
1959
1862
  options.dpr ?? (typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1)
1960
1863
  );
1961
- const crossfadeMs = options.crossfadeMs ?? 500;
1962
1864
  const keepalive = options.keepalive ?? true;
1963
1865
  this.registry = createRegistry({
1964
1866
  onRegister: (id, source) => this.emit("registered", id, source),
@@ -1968,7 +1870,6 @@ var Compositor = class extends CompositorEventEmitter {
1968
1870
  width,
1969
1871
  height,
1970
1872
  dpr,
1971
- crossfadeMs,
1972
1873
  keepalive
1973
1874
  });
1974
1875
  this.scheduler = createScheduler({