@roboflow/inference-sdk 0.1.8 → 0.1.10

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.es.js CHANGED
@@ -1,24 +1,24 @@
1
- var N = Object.defineProperty;
2
- var A = (r, e, t) => e in r ? N(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
3
- var d = (r, e, t) => A(r, typeof e != "symbol" ? e + "" : e, t);
4
- var U;
5
- const x = typeof process < "u" && ((U = process.env) != null && U.RF_API_BASE_URL) ? process.env.RF_API_BASE_URL : "https://api.roboflow.com", q = [
1
+ var q = Object.defineProperty;
2
+ var K = (r, e, t) => e in r ? q(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
3
+ var l = (r, e, t) => K(r, typeof e != "symbol" ? e + "" : e, t);
4
+ var L;
5
+ const B = typeof process < "u" && ((L = process.env) != null && L.RF_API_BASE_URL) ? process.env.RF_API_BASE_URL : "https://api.roboflow.com", j = [
6
6
  "https://serverless.roboflow.com"
7
7
  ];
8
- class b {
8
+ class T {
9
9
  /**
10
10
  * @private
11
11
  * Use InferenceHTTPClient.init() instead
12
12
  */
13
13
  constructor(e, t = "https://serverless.roboflow.com") {
14
- d(this, "apiKey");
15
- d(this, "serverUrl");
14
+ l(this, "apiKey");
15
+ l(this, "serverUrl");
16
16
  this.apiKey = e, this.serverUrl = t;
17
17
  }
18
18
  static init({ apiKey: e, serverUrl: t }) {
19
19
  if (!e)
20
20
  throw new Error("apiKey is required");
21
- return new b(e, t);
21
+ return new T(e, t);
22
22
  }
23
23
  /**
24
24
  * Initialize a WebRTC worker pipeline
@@ -48,60 +48,61 @@ class b {
48
48
  async initializeWebrtcWorker({
49
49
  offer: e,
50
50
  workflowSpec: t,
51
- workspaceName: a,
51
+ workspaceName: n,
52
52
  workflowId: o,
53
- config: n = {}
53
+ config: a = {}
54
54
  }) {
55
55
  if (!e || !e.sdp || !e.type)
56
56
  throw new Error("offer with sdp and type is required");
57
- const i = !!t, l = !!(a && o);
58
- if (!i && !l)
57
+ const i = !!t, p = !!(n && o);
58
+ if (!i && !p)
59
59
  throw new Error("Either workflowSpec OR (workspaceName + workflowId) is required");
60
- if (i && l)
60
+ if (i && p)
61
61
  throw new Error("Provide either workflowSpec OR (workspaceName + workflowId), not both");
62
62
  const {
63
- imageInputName: c = "image",
64
- streamOutputNames: s = [],
65
- dataOutputNames: u = ["string"],
66
- threadPoolWorkers: h = 4,
67
- workflowsParameters: y = {},
68
- iceServers: w,
69
- processingTimeout: R,
70
- requestedPlan: g,
71
- requestedRegion: v,
72
- realtimeProcessing: m = !0
73
- } = n, p = {
63
+ imageInputName: d = "image",
64
+ streamOutputNames: c = [],
65
+ dataOutputNames: s = [],
66
+ threadPoolWorkers: y = 4,
67
+ workflowsParameters: S = {},
68
+ iceServers: h,
69
+ processingTimeout: u,
70
+ requestedPlan: f,
71
+ requestedRegion: C,
72
+ realtimeProcessing: b = !0,
73
+ rtspUrl: R
74
+ } = a, v = {
74
75
  type: "WorkflowConfiguration",
75
- image_input_name: c,
76
- workflows_parameters: y,
77
- workflows_thread_pool_workers: h,
76
+ image_input_name: d,
77
+ workflows_parameters: S,
78
+ workflows_thread_pool_workers: y,
78
79
  cancel_thread_pool_tasks_on_exit: !0,
79
80
  video_metadata_input_name: "video_metadata"
80
81
  };
81
- i ? p.workflow_specification = t : (p.workspace_name = a, p.workflow_id = o);
82
- const S = {
83
- workflow_configuration: p,
82
+ i ? v.workflow_specification = t : (v.workspace_name = n, v.workflow_id = o);
83
+ const m = {
84
+ workflow_configuration: v,
84
85
  api_key: this.apiKey,
85
- webrtc_realtime_processing: m,
86
+ webrtc_realtime_processing: b,
86
87
  webrtc_offer: {
87
88
  sdp: e.sdp,
88
89
  type: e.type
89
90
  },
90
- webrtc_config: w ? { iceServers: w } : null,
91
- stream_output: s,
92
- data_output: u
91
+ webrtc_config: h ? { iceServers: h } : null,
92
+ stream_output: c,
93
+ data_output: s
93
94
  };
94
- R !== void 0 && (S.processing_timeout = R), g !== void 0 && (S.requested_plan = g), v !== void 0 && (S.requested_region = v);
95
- const C = await fetch(`${this.serverUrl}/initialise_webrtc_worker`, {
95
+ u !== void 0 && (m.processing_timeout = u), f !== void 0 && (m.requested_plan = f), C !== void 0 && (m.requested_region = C), R && (m.rtsp_url = R);
96
+ const w = await fetch(`${this.serverUrl}/initialise_webrtc_worker`, {
96
97
  method: "POST",
97
98
  headers: { "Content-Type": "application/json" },
98
- body: JSON.stringify(S)
99
+ body: JSON.stringify(m)
99
100
  });
100
- if (!C.ok) {
101
- const k = await C.text().catch(() => "");
102
- throw new Error(`initialise_webrtc_worker failed (${C.status}): ${k}`);
101
+ if (!w.ok) {
102
+ const E = await w.text().catch(() => "");
103
+ throw new Error(`initialise_webrtc_worker failed (${w.status}): ${E}`);
103
104
  }
104
- return await C.json();
105
+ return await w.json();
105
106
  }
106
107
  async terminatePipeline({ pipelineId: e }) {
107
108
  if (!e)
@@ -131,11 +132,11 @@ class b {
131
132
  * ```
132
133
  */
133
134
  async fetchTurnConfig() {
134
- if (!q.includes(this.serverUrl))
135
+ if (!j.includes(this.serverUrl))
135
136
  return null;
136
137
  try {
137
138
  const e = await fetch(
138
- `${x}/webrtc_turn_config?api_key=${this.apiKey}`,
139
+ `${B}/webrtc_turn_config?api_key=${this.apiKey}`,
139
140
  {
140
141
  method: "GET",
141
142
  headers: { "Content-Type": "application/json" }
@@ -144,26 +145,26 @@ class b {
144
145
  if (!e.ok)
145
146
  return console.warn(`[RFWebRTC] Failed to fetch TURN config (${e.status}), using defaults`), null;
146
147
  const t = await e.json();
147
- let a;
148
+ let n;
148
149
  if (Array.isArray(t))
149
- a = t;
150
+ n = t;
150
151
  else if (t.iceServers && Array.isArray(t.iceServers))
151
- a = t.iceServers;
152
+ n = t.iceServers;
152
153
  else if (t.urls)
153
- a = [t];
154
+ n = [t];
154
155
  else
155
156
  return console.warn("[RFWebRTC] Invalid TURN config format, using defaults"), null;
156
- return a.map((n) => ({
157
- urls: Array.isArray(n.urls) ? n.urls : [n.urls],
158
- username: n.username,
159
- credential: n.credential
157
+ return n.map((a) => ({
158
+ urls: Array.isArray(a.urls) ? a.urls : [a.urls],
159
+ username: a.username,
160
+ credential: a.credential
160
161
  }));
161
162
  } catch (e) {
162
163
  return console.warn("[RFWebRTC] Error fetching TURN config:", e), null;
163
164
  }
164
165
  }
165
166
  }
166
- const ee = {
167
+ const ae = {
167
168
  /**
168
169
  * Create a connector that uses API key directly
169
170
  *
@@ -187,30 +188,31 @@ const ee = {
187
188
  typeof window < "u" && console.warn(
188
189
  "[Security Warning] Using API key directly in browser will expose it. Use connectors.withProxyUrl() for production. See: https://docs.roboflow.com/api-reference/authentication#securing-your-api-key"
189
190
  );
190
- const a = b.init({ apiKey: r, serverUrl: t });
191
+ const n = T.init({ apiKey: r, serverUrl: t });
191
192
  return {
192
- connectWrtc: async (o, n) => (console.debug("wrtcParams", n), await a.initializeWebrtcWorker({
193
+ connectWrtc: async (o, a) => (console.debug("wrtcParams", a), await n.initializeWebrtcWorker({
193
194
  offer: o,
194
- workflowSpec: n.workflowSpec,
195
- workspaceName: n.workspaceName,
196
- workflowId: n.workflowId,
195
+ workflowSpec: a.workflowSpec,
196
+ workspaceName: a.workspaceName,
197
+ workflowId: a.workflowId,
197
198
  config: {
198
- imageInputName: n.imageInputName,
199
- streamOutputNames: n.streamOutputNames,
200
- dataOutputNames: n.dataOutputNames,
201
- threadPoolWorkers: n.threadPoolWorkers,
202
- workflowsParameters: n.workflowsParameters,
203
- iceServers: n.iceServers,
204
- processingTimeout: n.processingTimeout,
205
- requestedPlan: n.requestedPlan,
206
- requestedRegion: n.requestedRegion,
207
- realtimeProcessing: n.realtimeProcessing
199
+ imageInputName: a.imageInputName,
200
+ streamOutputNames: a.streamOutputNames,
201
+ dataOutputNames: a.dataOutputNames,
202
+ threadPoolWorkers: a.threadPoolWorkers,
203
+ workflowsParameters: a.workflowsParameters,
204
+ iceServers: a.iceServers,
205
+ processingTimeout: a.processingTimeout,
206
+ requestedPlan: a.requestedPlan,
207
+ requestedRegion: a.requestedRegion,
208
+ realtimeProcessing: a.realtimeProcessing,
209
+ rtspUrl: a.rtspUrl
208
210
  }
209
211
  })),
210
212
  /**
211
213
  * Fetch TURN server configuration for improved WebRTC connectivity
212
214
  */
213
- getIceServers: async () => await a.fetchTurnConfig(),
215
+ getIceServers: async () => await n.fetchTurnConfig(),
214
216
  // Store apiKey for cleanup
215
217
  _apiKey: r,
216
218
  _serverUrl: t
@@ -282,20 +284,20 @@ const ee = {
282
284
  withProxyUrl(r, e = {}) {
283
285
  const { turnConfigUrl: t } = e;
284
286
  return {
285
- connectWrtc: async (a, o) => {
286
- const n = await fetch(r, {
287
+ connectWrtc: async (n, o) => {
288
+ const a = await fetch(r, {
287
289
  method: "POST",
288
290
  headers: { "Content-Type": "application/json" },
289
291
  body: JSON.stringify({
290
- offer: a,
292
+ offer: n,
291
293
  wrtcParams: o
292
294
  })
293
295
  });
294
- if (!n.ok) {
295
- const i = await n.text().catch(() => "");
296
- throw new Error(`Proxy request failed (${n.status}): ${i}`);
296
+ if (!a.ok) {
297
+ const i = await a.text().catch(() => "");
298
+ throw new Error(`Proxy request failed (${a.status}): ${i}`);
297
299
  }
298
- return await n.json();
300
+ return await a.json();
299
301
  },
300
302
  /**
301
303
  * Fetch TURN server configuration from the proxy backend
@@ -303,19 +305,19 @@ const ee = {
303
305
  */
304
306
  getIceServers: t ? async () => {
305
307
  try {
306
- const a = await fetch(t, {
308
+ const n = await fetch(t, {
307
309
  method: "GET",
308
310
  headers: { "Content-Type": "application/json" }
309
311
  });
310
- return a.ok ? (await a.json()).iceServers || null : (console.warn(`[RFWebRTC] Failed to fetch TURN config from proxy (${a.status})`), null);
311
- } catch (a) {
312
- return console.warn("[RFWebRTC] Error fetching TURN config from proxy:", a), null;
312
+ return n.ok ? (await n.json()).iceServers || null : (console.warn(`[RFWebRTC] Failed to fetch TURN config from proxy (${n.status})`), null);
313
+ } catch (n) {
314
+ return console.warn("[RFWebRTC] Error fetching TURN config from proxy:", n), null;
313
315
  }
314
316
  } : void 0
315
317
  };
316
318
  }
317
319
  };
318
- async function K(r = { video: !0 }) {
320
+ async function V(r = { video: !0 }) {
319
321
  try {
320
322
  console.log("[RFStreams] requesting with", r);
321
323
  const e = await navigator.mediaDevices.getUserMedia(r);
@@ -323,27 +325,27 @@ async function K(r = { video: !0 }) {
323
325
  } catch (e) {
324
326
  console.warn("[RFStreams] failed, falling back", e);
325
327
  const t = await navigator.mediaDevices.getUserMedia({ video: !0, audio: !1 });
326
- return console.log("[RFStreams] fallback stream", t.getVideoTracks().map((a) => ({ id: a.id, label: a.label }))), t;
328
+ return console.log("[RFStreams] fallback stream", t.getVideoTracks().map((n) => ({ id: n.id, label: n.label }))), t;
327
329
  }
328
330
  }
329
- function W(r) {
331
+ function O(r) {
330
332
  r && (r.getTracks().forEach((e) => e.stop()), console.log("[RFStreams] Stream stopped"));
331
333
  }
332
- const te = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
334
+ const oe = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
333
335
  __proto__: null,
334
- stopStream: W,
335
- useCamera: K
336
- }, Symbol.toStringTag, { value: "Module" })), T = 49152, j = 262144, B = 10;
337
- function V(r) {
336
+ stopStream: O,
337
+ useCamera: V
338
+ }, Symbol.toStringTag, { value: "Module" })), k = 49152, $ = 262144, M = 10;
339
+ function z(r) {
338
340
  return new Promise((e) => setTimeout(e, r));
339
341
  }
340
- class I {
342
+ class D {
341
343
  constructor(e, t) {
342
- d(this, "file");
343
- d(this, "channel");
344
- d(this, "totalChunks");
345
- d(this, "cancelled", !1);
346
- this.file = e, this.channel = t, this.totalChunks = Math.ceil(e.size / T);
344
+ l(this, "file");
345
+ l(this, "channel");
346
+ l(this, "totalChunks");
347
+ l(this, "cancelled", !1);
348
+ this.file = e, this.channel = t, this.totalChunks = Math.ceil(e.size / k);
347
349
  }
348
350
  /**
349
351
  * Cancel the upload
@@ -358,45 +360,45 @@ class I {
358
360
  */
359
361
  async upload(e) {
360
362
  const t = this.file.size;
361
- for (let a = 0; a < this.totalChunks; a++) {
363
+ for (let n = 0; n < this.totalChunks; n++) {
362
364
  if (this.cancelled)
363
365
  throw new Error("Upload cancelled");
364
366
  if (this.channel.readyState !== "open")
365
367
  throw new Error("Video upload interrupted");
366
- const o = a * T, n = Math.min(o + T, t), i = this.file.slice(o, n), l = new Uint8Array(await i.arrayBuffer()), c = new ArrayBuffer(8 + l.length), s = new DataView(c);
367
- for (s.setUint32(0, a, !0), s.setUint32(4, this.totalChunks, !0), new Uint8Array(c, 8).set(l); this.channel.bufferedAmount > j; ) {
368
+ const o = n * k, a = Math.min(o + k, t), i = this.file.slice(o, a), p = new Uint8Array(await i.arrayBuffer()), d = new ArrayBuffer(8 + p.length), c = new DataView(d);
369
+ for (c.setUint32(0, n, !0), c.setUint32(4, this.totalChunks, !0), new Uint8Array(d, 8).set(p); this.channel.bufferedAmount > $; ) {
368
370
  if (this.channel.readyState !== "open")
369
371
  throw new Error("Video upload interrupted");
370
- await V(B);
372
+ await z(M);
371
373
  }
372
- this.channel.send(c), e && e(n, t);
374
+ this.channel.send(d), e && e(a, t);
373
375
  }
374
376
  }
375
377
  }
376
- const $ = 12;
377
- class P {
378
+ const H = 12;
379
+ class N {
378
380
  constructor() {
379
- d(this, "pendingFrames", /* @__PURE__ */ new Map());
381
+ l(this, "pendingFrames", /* @__PURE__ */ new Map());
380
382
  }
381
383
  /**
382
384
  * Process an incoming chunk and return the complete message if all chunks received
383
385
  */
384
- processChunk(e, t, a, o) {
385
- if (a === 1)
386
+ processChunk(e, t, n, o) {
387
+ if (n === 1)
386
388
  return o;
387
389
  this.pendingFrames.has(e) || this.pendingFrames.set(e, {
388
390
  chunks: /* @__PURE__ */ new Map(),
389
- totalChunks: a
391
+ totalChunks: n
390
392
  });
391
- const n = this.pendingFrames.get(e);
392
- if (n.chunks.set(t, o), n.chunks.size === a) {
393
- const i = Array.from(n.chunks.values()).reduce((s, u) => s + u.length, 0), l = new Uint8Array(i);
394
- let c = 0;
395
- for (let s = 0; s < a; s++) {
396
- const u = n.chunks.get(s);
397
- l.set(u, c), c += u.length;
393
+ const a = this.pendingFrames.get(e);
394
+ if (a.chunks.set(t, o), a.chunks.size === n) {
395
+ const i = Array.from(a.chunks.values()).reduce((c, s) => c + s.length, 0), p = new Uint8Array(i);
396
+ let d = 0;
397
+ for (let c = 0; c < n; c++) {
398
+ const s = a.chunks.get(c);
399
+ p.set(s, d), d += s.length;
398
400
  }
399
- return this.pendingFrames.delete(e), l;
401
+ return this.pendingFrames.delete(e), p;
400
402
  }
401
403
  return null;
402
404
  }
@@ -407,136 +409,151 @@ class P {
407
409
  this.pendingFrames.clear();
408
410
  }
409
411
  }
410
- function L(r) {
411
- const e = new DataView(r), t = e.getUint32(0, !0), a = e.getUint32(4, !0), o = e.getUint32(8, !0), n = new Uint8Array(r, $);
412
- return { frameId: t, chunkIndex: a, totalChunks: o, payload: n };
412
+ function A(r) {
413
+ const e = new DataView(r), t = e.getUint32(0, !0), n = e.getUint32(4, !0), o = e.getUint32(8, !0), a = new Uint8Array(r, H);
414
+ return { frameId: t, chunkIndex: n, totalChunks: o, payload: a };
413
415
  }
414
- async function M(r, e = 6e3) {
416
+ async function G(r, e = 6e3) {
415
417
  if (r.iceGatheringState === "complete") return;
416
418
  let t = !1;
417
- const a = (o) => {
419
+ const n = (o) => {
418
420
  o.candidate && o.candidate.type === "srflx" && (t = !0);
419
421
  };
420
- r.addEventListener("icecandidate", a);
422
+ r.addEventListener("icecandidate", n);
421
423
  try {
422
424
  await Promise.race([
423
425
  new Promise((o) => {
424
- const n = () => {
425
- r.iceGatheringState === "complete" && (r.removeEventListener("icegatheringstatechange", n), o());
426
+ const a = () => {
427
+ r.iceGatheringState === "complete" && (r.removeEventListener("icegatheringstatechange", a), o());
426
428
  };
427
- r.addEventListener("icegatheringstatechange", n);
429
+ r.addEventListener("icegatheringstatechange", a);
428
430
  }),
429
- new Promise((o, n) => {
431
+ new Promise((o, a) => {
430
432
  setTimeout(() => {
431
- t ? o() : (console.error("[ICE] timeout with NO srflx candidate! Connection may fail."), n(new Error("ICE gathering timeout without srflx candidate")));
433
+ t ? o() : (console.error("[ICE] timeout with NO srflx candidate! Connection may fail."), a(new Error("ICE gathering timeout without srflx candidate")));
432
434
  }, e);
433
435
  })
434
436
  ]);
435
437
  } finally {
436
- r.removeEventListener("icecandidate", a);
438
+ r.removeEventListener("icecandidate", n);
437
439
  }
438
440
  }
439
- function z(r) {
441
+ function J(r) {
440
442
  return new Promise((e) => {
441
443
  r.addEventListener("track", (t) => {
442
444
  t.streams && t.streams[0] && e(t.streams[0]);
443
445
  });
444
446
  });
445
447
  }
446
- const H = [
448
+ const Z = [
447
449
  { urls: ["stun:stun.l.google.com:19302"] }
448
450
  ];
449
- async function G(r, e, t) {
450
- if (!r && !e || r && e)
451
- throw new Error("Either localStream or file must be provided, but not both");
452
- const a = t ?? H, o = new RTCPeerConnection({
453
- iceServers: a
451
+ async function Q(r, e, t, n, o) {
452
+ if ([!!r, !!e, !!n].filter(Boolean).length !== 1)
453
+ throw new Error("Exactly one of localStream, file, or rtspUrl must be provided");
454
+ const c = t ?? Z, s = new RTCPeerConnection({
455
+ iceServers: c
454
456
  });
457
+ o != null && o.onPeerConnectionCreated && await o.onPeerConnectionCreated(s);
455
458
  try {
456
- o.addTransceiver("video", { direction: "recvonly" });
457
- } catch (s) {
458
- console.warn("[RFWebRTC] Could not add transceiver:", s);
459
+ s.addTransceiver("video", { direction: "recvonly" });
460
+ } catch (f) {
461
+ console.warn("[RFWebRTC] Could not add transceiver:", f);
459
462
  }
460
- r && r.getVideoTracks().forEach((s) => {
461
- try {
462
- s.contentHint = "detail";
463
- } catch {
463
+ if (r)
464
+ for (const f of r.getVideoTracks()) {
465
+ const C = s.addTrack(f, r);
466
+ o != null && o.onTrackAdded && await o.onTrackAdded(f, C, s);
464
467
  }
465
- o.addTrack(s, r);
466
- });
467
- const n = z(o), i = o.createDataChannel("inference", {
468
+ const y = J(s), S = s.createDataChannel("inference", {
468
469
  ordered: !0
469
470
  });
470
- let l;
471
- e && (l = o.createDataChannel("video_upload"));
472
- const c = await o.createOffer();
473
- return await o.setLocalDescription(c), await M(o), {
474
- pc: o,
475
- offer: o.localDescription,
476
- remoteStreamPromise: n,
477
- dataChannel: i,
478
- uploadChannel: l
471
+ let h;
472
+ e && (h = s.createDataChannel("video_upload"));
473
+ let u = await s.createOffer();
474
+ if (o != null && o.onOfferCreated) {
475
+ const f = await o.onOfferCreated(u);
476
+ f && (u = f);
477
+ }
478
+ return await s.setLocalDescription(u), await G(s), {
479
+ pc: s,
480
+ offer: s.localDescription,
481
+ remoteStreamPromise: y,
482
+ dataChannel: S,
483
+ uploadChannel: h
479
484
  };
480
485
  }
481
- async function J(r) {
482
- const e = r.getSenders().find((a) => a.track && a.track.kind === "video");
486
+ async function X(r) {
487
+ const e = r.getSenders().find((n) => n.track && n.track.kind === "video");
483
488
  if (!e) return;
484
489
  const t = e.getParameters();
485
490
  t.encodings = t.encodings || [{}], t.encodings[0].scaleResolutionDownBy = 1;
486
491
  try {
487
492
  await e.setParameters(t);
488
- } catch (a) {
489
- console.warn("[RFWebRTC] Failed to set encoding parameters:", a);
493
+ } catch (n) {
494
+ console.warn("[RFWebRTC] Failed to set encoding parameters:", n);
490
495
  }
491
496
  }
492
- function Z(r, e = 3e4) {
493
- return new Promise((t, a) => {
497
+ function Y(r, e = 3e4) {
498
+ return new Promise((t, n) => {
494
499
  if (r.readyState === "open") {
495
500
  t();
496
501
  return;
497
502
  }
498
503
  const o = () => {
499
- r.removeEventListener("open", o), r.removeEventListener("error", n), clearTimeout(i), t();
500
- }, n = () => {
501
- r.removeEventListener("open", o), r.removeEventListener("error", n), clearTimeout(i), a(new Error("Datachannel error"));
504
+ r.removeEventListener("open", o), r.removeEventListener("error", a), clearTimeout(i), t();
505
+ }, a = () => {
506
+ r.removeEventListener("open", o), r.removeEventListener("error", a), clearTimeout(i), n(new Error("Datachannel error"));
502
507
  }, i = setTimeout(() => {
503
- r.removeEventListener("open", o), r.removeEventListener("error", n), a(new Error("Datachannel open timeout"));
508
+ r.removeEventListener("open", o), r.removeEventListener("error", a), n(new Error("Datachannel open timeout"));
504
509
  }, e);
505
- r.addEventListener("open", o), r.addEventListener("error", n);
510
+ r.addEventListener("open", o), r.addEventListener("error", a);
506
511
  });
507
512
  }
508
- class O {
513
+ class x {
509
514
  /** @private */
510
- constructor(e, t, a, o, n, i) {
511
- d(this, "pc");
512
- d(this, "_localStream");
513
- d(this, "remoteStreamPromise");
514
- d(this, "pipelineId");
515
- d(this, "apiKey");
516
- d(this, "dataChannel");
517
- d(this, "reassembler");
518
- d(this, "uploadChannel");
519
- d(this, "uploader");
520
- d(this, "onComplete");
521
- this.pc = e, this._localStream = i == null ? void 0 : i.localStream, this.remoteStreamPromise = t, this.pipelineId = a, this.apiKey = o, this.dataChannel = n, this.reassembler = new P(), this.uploadChannel = i == null ? void 0 : i.uploadChannel, this.onComplete = i == null ? void 0 : i.onComplete, this.dataChannel.binaryType = "arraybuffer";
522
- const l = i == null ? void 0 : i.onData;
523
- l && (this.dataChannel.addEventListener("message", (c) => {
515
+ constructor(e, t, n, o, a, i) {
516
+ /**
517
+ * The underlying RTCPeerConnection.
518
+ * Exposed for advanced use cases like getting stats or accessing senders.
519
+ */
520
+ l(this, "peerConnection");
521
+ l(this, "_localStream");
522
+ l(this, "remoteStreamPromise");
523
+ l(this, "pipelineId");
524
+ l(this, "apiKey");
525
+ /**
526
+ * The data channel used for receiving inference results.
527
+ * Exposed for advanced use cases.
528
+ */
529
+ l(this, "dataChannel");
530
+ l(this, "reassembler");
531
+ /**
532
+ * The data channel used for uploading video files (only available in file upload mode).
533
+ * Exposed for advanced use cases.
534
+ */
535
+ l(this, "uploadChannel");
536
+ l(this, "uploader");
537
+ l(this, "onComplete");
538
+ this.peerConnection = e, this._localStream = i == null ? void 0 : i.localStream, this.remoteStreamPromise = t, this.pipelineId = n, this.apiKey = o, this.dataChannel = a, this.reassembler = new N(), this.uploadChannel = i == null ? void 0 : i.uploadChannel, this.onComplete = i == null ? void 0 : i.onComplete, this.dataChannel.binaryType = "arraybuffer";
539
+ const p = i == null ? void 0 : i.onData;
540
+ p && (this.dataChannel.addEventListener("message", (d) => {
524
541
  try {
525
- if (c.data instanceof ArrayBuffer) {
526
- const { frameId: s, chunkIndex: u, totalChunks: h, payload: y } = L(c.data), w = this.reassembler.processChunk(s, u, h, y);
527
- if (w) {
528
- const g = new TextDecoder("utf-8").decode(w), v = JSON.parse(g);
529
- l(v);
542
+ if (d.data instanceof ArrayBuffer) {
543
+ const { frameId: c, chunkIndex: s, totalChunks: y, payload: S } = A(d.data), h = this.reassembler.processChunk(c, s, y, S);
544
+ if (h) {
545
+ const f = new TextDecoder("utf-8").decode(h), C = JSON.parse(f);
546
+ p(C);
530
547
  }
531
548
  } else {
532
- const s = JSON.parse(c.data);
533
- l(s);
549
+ const c = JSON.parse(d.data);
550
+ p(c);
534
551
  }
535
- } catch (s) {
536
- console.error("[RFWebRTC] Failed to parse data channel message:", s);
552
+ } catch (c) {
553
+ console.error("[RFWebRTC] Failed to parse data channel message:", c);
537
554
  }
538
- }), this.dataChannel.addEventListener("error", (c) => {
539
- console.error("[RFWebRTC] Data channel error:", c);
555
+ }), this.dataChannel.addEventListener("error", (d) => {
556
+ console.error("[RFWebRTC] Data channel error:", d);
540
557
  })), this.dataChannel.addEventListener("close", () => {
541
558
  this.reassembler.clear(), this.onComplete && this.onComplete();
542
559
  });
@@ -591,11 +608,11 @@ class O {
591
608
  async cleanup() {
592
609
  if (this.uploader && this.uploader.cancel(), this.reassembler.clear(), this.pipelineId && this.apiKey)
593
610
  try {
594
- await b.init({ apiKey: this.apiKey }).terminatePipeline({ pipelineId: this.pipelineId });
611
+ await T.init({ apiKey: this.apiKey }).terminatePipeline({ pipelineId: this.pipelineId });
595
612
  } catch (e) {
596
613
  console.warn("[RFWebRTC] Failed to terminate pipeline:", e);
597
614
  }
598
- this.pc && this.pc.connectionState !== "closed" && this.pc.close(), this._localStream && W(this._localStream);
615
+ this.peerConnection && this.peerConnection.connectionState !== "closed" && this.peerConnection.close(), this._localStream && O(this._localStream);
599
616
  }
600
617
  /**
601
618
  * Start uploading a file through the connection
@@ -615,7 +632,7 @@ class O {
615
632
  async startUpload(e, t) {
616
633
  if (!this.uploadChannel)
617
634
  throw new Error("No upload channel available. This connection was not created for file uploads.");
618
- await Z(this.uploadChannel), this.uploader = new I(e, this.uploadChannel), await this.uploader.upload(t);
635
+ await Y(this.uploadChannel), this.uploader = new D(e, this.uploadChannel), await this.uploader.upload(t);
619
636
  }
620
637
  /**
621
638
  * Cancel any ongoing file upload
@@ -676,117 +693,144 @@ class O {
676
693
  }
677
694
  }
678
695
  }
679
- async function D({
696
+ async function F({
680
697
  source: r,
681
- connector: e,
682
- wrtcParams: t,
683
- onData: a,
684
- onComplete: o,
685
- onFileUploadProgress: n,
686
- options: i = {}
698
+ rtspUrl: e,
699
+ connector: t,
700
+ wrtcParams: n,
701
+ onData: o,
702
+ onComplete: a,
703
+ onFileUploadProgress: i,
704
+ options: p = {},
705
+ hooks: d
687
706
  }) {
688
- var k;
689
- if (!e || typeof e.connectWrtc != "function")
707
+ var P;
708
+ if (!t || typeof t.connectWrtc != "function")
690
709
  throw new Error("connector must have a connectWrtc method");
691
- const l = r instanceof File, c = l ? void 0 : r, s = l ? r : void 0;
692
- let u = t.iceServers;
693
- if ((!u || u.length === 0) && e.getIceServers)
710
+ const c = !!e, s = !c && r instanceof File, y = !c && !s && r ? r : void 0, S = s ? r : void 0;
711
+ let h = n.iceServers;
712
+ if ((!h || h.length === 0) && t.getIceServers)
694
713
  try {
695
- const f = await e.getIceServers();
696
- f && f.length > 0 && (u = f, console.log("[RFWebRTC] Using TURN servers from connector"));
697
- } catch (f) {
698
- console.warn("[RFWebRTC] Failed to fetch TURN config, using defaults:", f);
714
+ const g = await t.getIceServers();
715
+ g && g.length > 0 && (h = g, console.log("[RFWebRTC] Using TURN servers from connector"));
716
+ } catch (g) {
717
+ console.warn("[RFWebRTC] Failed to fetch TURN config, using defaults:", g);
699
718
  }
700
- const { pc: h, offer: y, remoteStreamPromise: w, dataChannel: R, uploadChannel: g } = await G(
701
- c,
702
- s,
703
- u
719
+ const { pc: u, offer: f, remoteStreamPromise: C, dataChannel: b, uploadChannel: R } = await Q(
720
+ y,
721
+ S,
722
+ h,
723
+ e,
724
+ d
704
725
  ), v = {
705
- ...t,
706
- iceServers: u,
707
- realtimeProcessing: t.realtimeProcessing ?? !l
708
- }, m = await e.connectWrtc(
709
- { sdp: y.sdp, type: y.type },
726
+ ...n,
727
+ iceServers: h,
728
+ realtimeProcessing: n.realtimeProcessing ?? !s,
729
+ rtspUrl: e
730
+ }, m = await t.connectWrtc(
731
+ { sdp: f.sdp, type: f.type },
710
732
  v
711
- ), p = { sdp: m.sdp, type: m.type };
712
- if (!(p != null && p.sdp) || !(p != null && p.type))
733
+ ), w = { sdp: m.sdp, type: m.type };
734
+ if (!(w != null && w.sdp) || !(w != null && w.type))
713
735
  throw console.error("[RFWebRTC] Invalid answer from server:", m), new Error("connector.connectWrtc must return answer with sdp and type");
714
- const S = ((k = m == null ? void 0 : m.context) == null ? void 0 : k.pipeline_id) || null;
715
- await h.setRemoteDescription(p), await new Promise((f, F) => {
736
+ const U = ((P = m == null ? void 0 : m.context) == null ? void 0 : P.pipeline_id) || null;
737
+ await u.setRemoteDescription(w), await new Promise((g, I) => {
716
738
  const _ = () => {
717
- h.connectionState === "connected" ? (h.removeEventListener("connectionstatechange", _), f()) : h.connectionState === "failed" && (h.removeEventListener("connectionstatechange", _), F(new Error("WebRTC connection failed")));
739
+ u.connectionState === "connected" ? (u.removeEventListener("connectionstatechange", _), g()) : u.connectionState === "failed" && (u.removeEventListener("connectionstatechange", _), I(new Error("WebRTC connection failed")));
718
740
  };
719
- h.addEventListener("connectionstatechange", _), _(), setTimeout(() => {
720
- h.removeEventListener("connectionstatechange", _), F(new Error("WebRTC connection timeout after 30s"));
741
+ u.addEventListener("connectionstatechange", _), _(), setTimeout(() => {
742
+ u.removeEventListener("connectionstatechange", _), I(new Error("WebRTC connection timeout after 30s"));
721
743
  }, 3e4);
722
- }), c && i.disableInputStreamDownscaling !== !1 && await J(h);
723
- const C = e._apiKey || null, E = new O(
724
- h,
725
- w,
726
- S,
744
+ }), y && p.disableInputStreamDownscaling !== !1 && await X(u);
745
+ const E = t._apiKey || null, W = new x(
746
+ u,
727
747
  C,
728
- R,
748
+ U,
749
+ E,
750
+ b,
729
751
  {
730
- localStream: c,
731
- uploadChannel: g,
732
- onData: a,
733
- onComplete: o
752
+ localStream: y,
753
+ uploadChannel: R,
754
+ onData: o,
755
+ onComplete: a
734
756
  }
735
757
  );
736
- return s && g && E.startUpload(s, n).catch((f) => {
737
- console.error("[RFWebRTC] Upload error:", f);
738
- }), E;
758
+ return S && R && W.startUpload(S, i).catch((g) => {
759
+ console.error("[RFWebRTC] Upload error:", g);
760
+ }), W;
739
761
  }
740
- async function Q({
762
+ async function ee({
741
763
  source: r,
742
764
  connector: e,
743
765
  wrtcParams: t,
744
- onData: a,
745
- options: o = {}
766
+ onData: n,
767
+ options: o = {},
768
+ hooks: a
746
769
  }) {
747
770
  if (r instanceof File)
748
771
  throw new Error("useStream requires a MediaStream. Use useVideoFile for File uploads.");
749
- return D({
772
+ return F({
750
773
  source: r,
751
774
  connector: e,
752
775
  wrtcParams: t,
753
- onData: a,
754
- options: o
776
+ onData: n,
777
+ options: o,
778
+ hooks: a
755
779
  });
756
780
  }
757
- async function X({
781
+ async function te({
758
782
  file: r,
759
783
  connector: e,
760
784
  wrtcParams: t,
761
- onData: a,
785
+ onData: n,
762
786
  onUploadProgress: o,
763
- onComplete: n
787
+ onComplete: a,
788
+ hooks: i
764
789
  }) {
765
- return D({
790
+ return F({
766
791
  source: r,
767
792
  connector: e,
768
793
  wrtcParams: {
769
794
  ...t,
770
795
  realtimeProcessing: t.realtimeProcessing ?? !0
771
796
  },
772
- onData: a,
773
- onComplete: n,
774
- onFileUploadProgress: o
797
+ onData: n,
798
+ onComplete: a,
799
+ onFileUploadProgress: o,
800
+ hooks: i
801
+ });
802
+ }
803
+ async function re({
804
+ rtspUrl: r,
805
+ connector: e,
806
+ wrtcParams: t,
807
+ onData: n,
808
+ hooks: o
809
+ }) {
810
+ if (!r.startsWith("rtsp://") && !r.startsWith("rtsps://"))
811
+ throw new Error("Invalid RTSP URL: must start with rtsp:// or rtsps://");
812
+ return F({
813
+ rtspUrl: r,
814
+ connector: e,
815
+ wrtcParams: t,
816
+ onData: n,
817
+ hooks: o
775
818
  });
776
819
  }
777
- const re = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
820
+ const ie = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
778
821
  __proto__: null,
779
- ChunkReassembler: P,
780
- FileUploader: I,
781
- RFWebRTCConnection: O,
782
- parseBinaryHeader: L,
783
- useStream: Q,
784
- useVideoFile: X
822
+ ChunkReassembler: N,
823
+ FileUploader: D,
824
+ RFWebRTCConnection: x,
825
+ parseBinaryHeader: A,
826
+ useRtspStream: re,
827
+ useStream: ee,
828
+ useVideoFile: te
785
829
  }, Symbol.toStringTag, { value: "Module" }));
786
830
  export {
787
- b as InferenceHTTPClient,
788
- ee as connectors,
789
- te as streams,
790
- re as webrtc
831
+ T as InferenceHTTPClient,
832
+ ae as connectors,
833
+ oe as streams,
834
+ ie as webrtc
791
835
  };
792
836
  //# sourceMappingURL=index.es.js.map