@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.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.js +304 -260
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/inference-api.d.ts +14 -0
- package/dist/inference-api.d.ts.map +1 -1
- package/dist/webrtc-types.d.ts +63 -0
- package/dist/webrtc-types.d.ts.map +1 -1
- package/dist/webrtc.d.ts +75 -7
- package/dist/webrtc.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.es.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
const
|
|
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
|
|
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
|
-
|
|
15
|
-
|
|
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
|
|
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:
|
|
51
|
+
workspaceName: n,
|
|
52
52
|
workflowId: o,
|
|
53
|
-
config:
|
|
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,
|
|
58
|
-
if (!i && !
|
|
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 &&
|
|
60
|
+
if (i && p)
|
|
61
61
|
throw new Error("Provide either workflowSpec OR (workspaceName + workflowId), not both");
|
|
62
62
|
const {
|
|
63
|
-
imageInputName:
|
|
64
|
-
streamOutputNames:
|
|
65
|
-
dataOutputNames:
|
|
66
|
-
threadPoolWorkers:
|
|
67
|
-
workflowsParameters:
|
|
68
|
-
iceServers:
|
|
69
|
-
processingTimeout:
|
|
70
|
-
requestedPlan:
|
|
71
|
-
requestedRegion:
|
|
72
|
-
realtimeProcessing:
|
|
73
|
-
|
|
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:
|
|
76
|
-
workflows_parameters:
|
|
77
|
-
workflows_thread_pool_workers:
|
|
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 ?
|
|
82
|
-
const
|
|
83
|
-
workflow_configuration:
|
|
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:
|
|
86
|
+
webrtc_realtime_processing: b,
|
|
86
87
|
webrtc_offer: {
|
|
87
88
|
sdp: e.sdp,
|
|
88
89
|
type: e.type
|
|
89
90
|
},
|
|
90
|
-
webrtc_config:
|
|
91
|
-
stream_output:
|
|
92
|
-
data_output:
|
|
91
|
+
webrtc_config: h ? { iceServers: h } : null,
|
|
92
|
+
stream_output: c,
|
|
93
|
+
data_output: s
|
|
93
94
|
};
|
|
94
|
-
|
|
95
|
-
const
|
|
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(
|
|
99
|
+
body: JSON.stringify(m)
|
|
99
100
|
});
|
|
100
|
-
if (!
|
|
101
|
-
const
|
|
102
|
-
throw new Error(`initialise_webrtc_worker failed (${
|
|
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
|
|
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 (!
|
|
135
|
+
if (!j.includes(this.serverUrl))
|
|
135
136
|
return null;
|
|
136
137
|
try {
|
|
137
138
|
const e = await fetch(
|
|
138
|
-
`${
|
|
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
|
|
148
|
+
let n;
|
|
148
149
|
if (Array.isArray(t))
|
|
149
|
-
|
|
150
|
+
n = t;
|
|
150
151
|
else if (t.iceServers && Array.isArray(t.iceServers))
|
|
151
|
-
|
|
152
|
+
n = t.iceServers;
|
|
152
153
|
else if (t.urls)
|
|
153
|
-
|
|
154
|
+
n = [t];
|
|
154
155
|
else
|
|
155
156
|
return console.warn("[RFWebRTC] Invalid TURN config format, using defaults"), null;
|
|
156
|
-
return
|
|
157
|
-
urls: Array.isArray(
|
|
158
|
-
username:
|
|
159
|
-
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
|
|
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
|
|
191
|
+
const n = T.init({ apiKey: r, serverUrl: t });
|
|
191
192
|
return {
|
|
192
|
-
connectWrtc: async (o,
|
|
193
|
+
connectWrtc: async (o, a) => (console.debug("wrtcParams", a), await n.initializeWebrtcWorker({
|
|
193
194
|
offer: o,
|
|
194
|
-
workflowSpec:
|
|
195
|
-
workspaceName:
|
|
196
|
-
workflowId:
|
|
195
|
+
workflowSpec: a.workflowSpec,
|
|
196
|
+
workspaceName: a.workspaceName,
|
|
197
|
+
workflowId: a.workflowId,
|
|
197
198
|
config: {
|
|
198
|
-
imageInputName:
|
|
199
|
-
streamOutputNames:
|
|
200
|
-
dataOutputNames:
|
|
201
|
-
threadPoolWorkers:
|
|
202
|
-
workflowsParameters:
|
|
203
|
-
iceServers:
|
|
204
|
-
processingTimeout:
|
|
205
|
-
requestedPlan:
|
|
206
|
-
requestedRegion:
|
|
207
|
-
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
|
|
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 (
|
|
286
|
-
const
|
|
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:
|
|
292
|
+
offer: n,
|
|
291
293
|
wrtcParams: o
|
|
292
294
|
})
|
|
293
295
|
});
|
|
294
|
-
if (!
|
|
295
|
-
const i = await
|
|
296
|
-
throw new Error(`Proxy request failed (${
|
|
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
|
|
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
|
|
308
|
+
const n = await fetch(t, {
|
|
307
309
|
method: "GET",
|
|
308
310
|
headers: { "Content-Type": "application/json" }
|
|
309
311
|
});
|
|
310
|
-
return
|
|
311
|
-
} catch (
|
|
312
|
-
return console.warn("[RFWebRTC] Error fetching TURN config from proxy:",
|
|
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
|
|
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((
|
|
328
|
+
return console.log("[RFStreams] fallback stream", t.getVideoTracks().map((n) => ({ id: n.id, label: n.label }))), t;
|
|
327
329
|
}
|
|
328
330
|
}
|
|
329
|
-
function
|
|
331
|
+
function O(r) {
|
|
330
332
|
r && (r.getTracks().forEach((e) => e.stop()), console.log("[RFStreams] Stream stopped"));
|
|
331
333
|
}
|
|
332
|
-
const
|
|
334
|
+
const oe = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
333
335
|
__proto__: null,
|
|
334
|
-
stopStream:
|
|
335
|
-
useCamera:
|
|
336
|
-
}, Symbol.toStringTag, { value: "Module" })),
|
|
337
|
-
function
|
|
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
|
|
342
|
+
class D {
|
|
341
343
|
constructor(e, t) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
this.file = e, this.channel = t, this.totalChunks = Math.ceil(e.size /
|
|
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
|
|
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 =
|
|
367
|
-
for (
|
|
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
|
|
372
|
+
await z(M);
|
|
371
373
|
}
|
|
372
|
-
this.channel.send(
|
|
374
|
+
this.channel.send(d), e && e(a, t);
|
|
373
375
|
}
|
|
374
376
|
}
|
|
375
377
|
}
|
|
376
|
-
const
|
|
377
|
-
class
|
|
378
|
+
const H = 12;
|
|
379
|
+
class N {
|
|
378
380
|
constructor() {
|
|
379
|
-
|
|
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,
|
|
385
|
-
if (
|
|
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:
|
|
391
|
+
totalChunks: n
|
|
390
392
|
});
|
|
391
|
-
const
|
|
392
|
-
if (
|
|
393
|
-
const i = Array.from(
|
|
394
|
-
let
|
|
395
|
-
for (let
|
|
396
|
-
const
|
|
397
|
-
|
|
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),
|
|
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
|
|
411
|
-
const e = new DataView(r), t = e.getUint32(0, !0),
|
|
412
|
-
return { frameId: t, chunkIndex:
|
|
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
|
|
416
|
+
async function G(r, e = 6e3) {
|
|
415
417
|
if (r.iceGatheringState === "complete") return;
|
|
416
418
|
let t = !1;
|
|
417
|
-
const
|
|
419
|
+
const n = (o) => {
|
|
418
420
|
o.candidate && o.candidate.type === "srflx" && (t = !0);
|
|
419
421
|
};
|
|
420
|
-
r.addEventListener("icecandidate",
|
|
422
|
+
r.addEventListener("icecandidate", n);
|
|
421
423
|
try {
|
|
422
424
|
await Promise.race([
|
|
423
425
|
new Promise((o) => {
|
|
424
|
-
const
|
|
425
|
-
r.iceGatheringState === "complete" && (r.removeEventListener("icegatheringstatechange",
|
|
426
|
+
const a = () => {
|
|
427
|
+
r.iceGatheringState === "complete" && (r.removeEventListener("icegatheringstatechange", a), o());
|
|
426
428
|
};
|
|
427
|
-
r.addEventListener("icegatheringstatechange",
|
|
429
|
+
r.addEventListener("icegatheringstatechange", a);
|
|
428
430
|
}),
|
|
429
|
-
new Promise((o,
|
|
431
|
+
new Promise((o, a) => {
|
|
430
432
|
setTimeout(() => {
|
|
431
|
-
t ? o() : (console.error("[ICE] timeout with NO srflx candidate! Connection may fail."),
|
|
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",
|
|
438
|
+
r.removeEventListener("icecandidate", n);
|
|
437
439
|
}
|
|
438
440
|
}
|
|
439
|
-
function
|
|
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
|
|
448
|
+
const Z = [
|
|
447
449
|
{ urls: ["stun:stun.l.google.com:19302"] }
|
|
448
450
|
];
|
|
449
|
-
async function
|
|
450
|
-
if (
|
|
451
|
-
throw new Error("
|
|
452
|
-
const
|
|
453
|
-
iceServers:
|
|
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
|
-
|
|
457
|
-
} catch (
|
|
458
|
-
console.warn("[RFWebRTC] Could not add transceiver:",
|
|
459
|
+
s.addTransceiver("video", { direction: "recvonly" });
|
|
460
|
+
} catch (f) {
|
|
461
|
+
console.warn("[RFWebRTC] Could not add transceiver:", f);
|
|
459
462
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
s.
|
|
463
|
-
|
|
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
|
-
|
|
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
|
|
471
|
-
e && (
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
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
|
|
482
|
-
const e = r.getSenders().find((
|
|
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 (
|
|
489
|
-
console.warn("[RFWebRTC] Failed to set encoding parameters:",
|
|
493
|
+
} catch (n) {
|
|
494
|
+
console.warn("[RFWebRTC] Failed to set encoding parameters:", n);
|
|
490
495
|
}
|
|
491
496
|
}
|
|
492
|
-
function
|
|
493
|
-
return new Promise((t,
|
|
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",
|
|
500
|
-
},
|
|
501
|
-
r.removeEventListener("open", o), r.removeEventListener("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",
|
|
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",
|
|
510
|
+
r.addEventListener("open", o), r.addEventListener("error", a);
|
|
506
511
|
});
|
|
507
512
|
}
|
|
508
|
-
class
|
|
513
|
+
class x {
|
|
509
514
|
/** @private */
|
|
510
|
-
constructor(e, t,
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
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 (
|
|
526
|
-
const { frameId:
|
|
527
|
-
if (
|
|
528
|
-
const
|
|
529
|
-
|
|
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
|
|
533
|
-
|
|
549
|
+
const c = JSON.parse(d.data);
|
|
550
|
+
p(c);
|
|
534
551
|
}
|
|
535
|
-
} catch (
|
|
536
|
-
console.error("[RFWebRTC] Failed to parse data channel message:",
|
|
552
|
+
} catch (c) {
|
|
553
|
+
console.error("[RFWebRTC] Failed to parse data channel message:", c);
|
|
537
554
|
}
|
|
538
|
-
}), this.dataChannel.addEventListener("error", (
|
|
539
|
-
console.error("[RFWebRTC] Data channel error:",
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
696
|
+
async function F({
|
|
680
697
|
source: r,
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
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
|
|
689
|
-
if (!
|
|
707
|
+
var P;
|
|
708
|
+
if (!t || typeof t.connectWrtc != "function")
|
|
690
709
|
throw new Error("connector must have a connectWrtc method");
|
|
691
|
-
const
|
|
692
|
-
let
|
|
693
|
-
if ((!
|
|
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
|
|
696
|
-
|
|
697
|
-
} catch (
|
|
698
|
-
console.warn("[RFWebRTC] Failed to fetch TURN config, using defaults:",
|
|
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:
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
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
|
-
...
|
|
706
|
-
iceServers:
|
|
707
|
-
realtimeProcessing:
|
|
708
|
-
|
|
709
|
-
|
|
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
|
-
),
|
|
712
|
-
if (!(
|
|
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
|
|
715
|
-
await
|
|
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
|
-
|
|
739
|
+
u.connectionState === "connected" ? (u.removeEventListener("connectionstatechange", _), g()) : u.connectionState === "failed" && (u.removeEventListener("connectionstatechange", _), I(new Error("WebRTC connection failed")));
|
|
718
740
|
};
|
|
719
|
-
|
|
720
|
-
|
|
741
|
+
u.addEventListener("connectionstatechange", _), _(), setTimeout(() => {
|
|
742
|
+
u.removeEventListener("connectionstatechange", _), I(new Error("WebRTC connection timeout after 30s"));
|
|
721
743
|
}, 3e4);
|
|
722
|
-
}),
|
|
723
|
-
const
|
|
724
|
-
|
|
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
|
-
|
|
748
|
+
U,
|
|
749
|
+
E,
|
|
750
|
+
b,
|
|
729
751
|
{
|
|
730
|
-
localStream:
|
|
731
|
-
uploadChannel:
|
|
732
|
-
onData:
|
|
733
|
-
onComplete:
|
|
752
|
+
localStream: y,
|
|
753
|
+
uploadChannel: R,
|
|
754
|
+
onData: o,
|
|
755
|
+
onComplete: a
|
|
734
756
|
}
|
|
735
757
|
);
|
|
736
|
-
return
|
|
737
|
-
console.error("[RFWebRTC] Upload error:",
|
|
738
|
-
}),
|
|
758
|
+
return S && R && W.startUpload(S, i).catch((g) => {
|
|
759
|
+
console.error("[RFWebRTC] Upload error:", g);
|
|
760
|
+
}), W;
|
|
739
761
|
}
|
|
740
|
-
async function
|
|
762
|
+
async function ee({
|
|
741
763
|
source: r,
|
|
742
764
|
connector: e,
|
|
743
765
|
wrtcParams: t,
|
|
744
|
-
onData:
|
|
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
|
|
772
|
+
return F({
|
|
750
773
|
source: r,
|
|
751
774
|
connector: e,
|
|
752
775
|
wrtcParams: t,
|
|
753
|
-
onData:
|
|
754
|
-
options: o
|
|
776
|
+
onData: n,
|
|
777
|
+
options: o,
|
|
778
|
+
hooks: a
|
|
755
779
|
});
|
|
756
780
|
}
|
|
757
|
-
async function
|
|
781
|
+
async function te({
|
|
758
782
|
file: r,
|
|
759
783
|
connector: e,
|
|
760
784
|
wrtcParams: t,
|
|
761
|
-
onData:
|
|
785
|
+
onData: n,
|
|
762
786
|
onUploadProgress: o,
|
|
763
|
-
onComplete:
|
|
787
|
+
onComplete: a,
|
|
788
|
+
hooks: i
|
|
764
789
|
}) {
|
|
765
|
-
return
|
|
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:
|
|
773
|
-
onComplete:
|
|
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
|
|
820
|
+
const ie = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
778
821
|
__proto__: null,
|
|
779
|
-
ChunkReassembler:
|
|
780
|
-
FileUploader:
|
|
781
|
-
RFWebRTCConnection:
|
|
782
|
-
parseBinaryHeader:
|
|
783
|
-
|
|
784
|
-
|
|
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
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
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
|