@roboflow/inference-sdk 0.1.8 → 0.1.9
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 +264 -243
- 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.d.ts +50 -0
- 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 A = Object.defineProperty;
|
|
2
|
+
var q = (r, e, t) => e in r ? A(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
|
|
3
|
+
var l = (r, e, t) => q(r, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
var L;
|
|
5
|
+
const K = typeof process < "u" && ((L = process.env) != null && L.RF_API_BASE_URL) ? process.env.RF_API_BASE_URL : "https://api.roboflow.com", B = [
|
|
6
6
|
"https://serverless.roboflow.com"
|
|
7
7
|
];
|
|
8
|
-
class
|
|
8
|
+
class E {
|
|
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 E(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, u = !!(n && o);
|
|
58
|
+
if (!i && !u)
|
|
59
59
|
throw new Error("Either workflowSpec OR (workspaceName + workflowId) is required");
|
|
60
|
-
if (i &&
|
|
60
|
+
if (i && u)
|
|
61
61
|
throw new Error("Provide either workflowSpec OR (workspaceName + workflowId), not both");
|
|
62
62
|
const {
|
|
63
63
|
imageInputName: c = "image",
|
|
64
64
|
streamOutputNames: s = [],
|
|
65
|
-
dataOutputNames:
|
|
66
|
-
threadPoolWorkers:
|
|
67
|
-
workflowsParameters:
|
|
68
|
-
iceServers:
|
|
69
|
-
processingTimeout:
|
|
70
|
-
requestedPlan:
|
|
65
|
+
dataOutputNames: h = ["string"],
|
|
66
|
+
threadPoolWorkers: y = 4,
|
|
67
|
+
workflowsParameters: f = {},
|
|
68
|
+
iceServers: d,
|
|
69
|
+
processingTimeout: m,
|
|
70
|
+
requestedPlan: S,
|
|
71
71
|
requestedRegion: v,
|
|
72
|
-
realtimeProcessing:
|
|
73
|
-
|
|
72
|
+
realtimeProcessing: _ = !0,
|
|
73
|
+
rtspUrl: k
|
|
74
|
+
} = a, w = {
|
|
74
75
|
type: "WorkflowConfiguration",
|
|
75
76
|
image_input_name: c,
|
|
76
|
-
workflows_parameters:
|
|
77
|
-
workflows_thread_pool_workers:
|
|
77
|
+
workflows_parameters: f,
|
|
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 ? w.workflow_specification = t : (w.workspace_name = n, w.workflow_id = o);
|
|
83
|
+
const p = {
|
|
84
|
+
workflow_configuration: w,
|
|
84
85
|
api_key: this.apiKey,
|
|
85
|
-
webrtc_realtime_processing:
|
|
86
|
+
webrtc_realtime_processing: _,
|
|
86
87
|
webrtc_offer: {
|
|
87
88
|
sdp: e.sdp,
|
|
88
89
|
type: e.type
|
|
89
90
|
},
|
|
90
|
-
webrtc_config:
|
|
91
|
+
webrtc_config: d ? { iceServers: d } : null,
|
|
91
92
|
stream_output: s,
|
|
92
|
-
data_output:
|
|
93
|
+
data_output: h
|
|
93
94
|
};
|
|
94
|
-
|
|
95
|
-
const
|
|
95
|
+
m !== void 0 && (p.processing_timeout = m), S !== void 0 && (p.requested_plan = S), v !== void 0 && (p.requested_region = v), k && (p.rtsp_url = k);
|
|
96
|
+
const R = 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(p)
|
|
99
100
|
});
|
|
100
|
-
if (!
|
|
101
|
-
const
|
|
102
|
-
throw new Error(`initialise_webrtc_worker failed (${
|
|
101
|
+
if (!R.ok) {
|
|
102
|
+
const b = await R.text().catch(() => "");
|
|
103
|
+
throw new Error(`initialise_webrtc_worker failed (${R.status}): ${b}`);
|
|
103
104
|
}
|
|
104
|
-
return await
|
|
105
|
+
return await R.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 (!B.includes(this.serverUrl))
|
|
135
136
|
return null;
|
|
136
137
|
try {
|
|
137
138
|
const e = await fetch(
|
|
138
|
-
`${
|
|
139
|
+
`${K}/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 ne = {
|
|
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 = E.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 j(r = { video: !0 }) {
|
|
319
321
|
try {
|
|
320
322
|
console.log("[RFStreams] requesting with", r);
|
|
321
323
|
const e = await navigator.mediaDevices.getUserMedia(r);
|
|
@@ -323,26 +325,26 @@ 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 P(r) {
|
|
330
332
|
r && (r.getTracks().forEach((e) => e.stop()), console.log("[RFStreams] Stream stopped"));
|
|
331
333
|
}
|
|
332
|
-
const
|
|
334
|
+
const ae = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
333
335
|
__proto__: null,
|
|
334
|
-
stopStream:
|
|
335
|
-
useCamera:
|
|
336
|
-
}, Symbol.toStringTag, { value: "Module" })), T = 49152,
|
|
337
|
-
function
|
|
336
|
+
stopStream: P,
|
|
337
|
+
useCamera: j
|
|
338
|
+
}, Symbol.toStringTag, { value: "Module" })), T = 49152, V = 262144, $ = 10;
|
|
339
|
+
function M(r) {
|
|
338
340
|
return new Promise((e) => setTimeout(e, r));
|
|
339
341
|
}
|
|
340
|
-
class
|
|
342
|
+
class O {
|
|
341
343
|
constructor(e, t) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
344
|
+
l(this, "file");
|
|
345
|
+
l(this, "channel");
|
|
346
|
+
l(this, "totalChunks");
|
|
347
|
+
l(this, "cancelled", !1);
|
|
346
348
|
this.file = e, this.channel = t, this.totalChunks = Math.ceil(e.size / T);
|
|
347
349
|
}
|
|
348
350
|
/**
|
|
@@ -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 (s.setUint32(0,
|
|
368
|
+
const o = n * T, a = Math.min(o + T, t), i = this.file.slice(o, a), u = new Uint8Array(await i.arrayBuffer()), c = new ArrayBuffer(8 + u.length), s = new DataView(c);
|
|
369
|
+
for (s.setUint32(0, n, !0), s.setUint32(4, this.totalChunks, !0), new Uint8Array(c, 8).set(u); this.channel.bufferedAmount > V; ) {
|
|
368
370
|
if (this.channel.readyState !== "open")
|
|
369
371
|
throw new Error("Video upload interrupted");
|
|
370
|
-
await
|
|
372
|
+
await M($);
|
|
371
373
|
}
|
|
372
|
-
this.channel.send(c), e && e(
|
|
374
|
+
this.channel.send(c), e && e(a, t);
|
|
373
375
|
}
|
|
374
376
|
}
|
|
375
377
|
}
|
|
376
|
-
const
|
|
377
|
-
class
|
|
378
|
+
const z = 12;
|
|
379
|
+
class D {
|
|
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(
|
|
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((s, h) => s + h.length, 0), u = new Uint8Array(i);
|
|
394
396
|
let c = 0;
|
|
395
|
-
for (let s = 0; s <
|
|
396
|
-
const
|
|
397
|
-
|
|
397
|
+
for (let s = 0; s < n; s++) {
|
|
398
|
+
const h = a.chunks.get(s);
|
|
399
|
+
u.set(h, c), c += h.length;
|
|
398
400
|
}
|
|
399
|
-
return this.pendingFrames.delete(e),
|
|
401
|
+
return this.pendingFrames.delete(e), u;
|
|
400
402
|
}
|
|
401
403
|
return null;
|
|
402
404
|
}
|
|
@@ -407,130 +409,130 @@ 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 N(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, z);
|
|
414
|
+
return { frameId: t, chunkIndex: n, totalChunks: o, payload: a };
|
|
413
415
|
}
|
|
414
|
-
async function
|
|
416
|
+
async function H(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 G(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 J = [
|
|
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 Z(r, e, t, n) {
|
|
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 ?? J, s = new RTCPeerConnection({
|
|
455
|
+
iceServers: c
|
|
454
456
|
});
|
|
455
457
|
try {
|
|
456
|
-
|
|
457
|
-
} catch (
|
|
458
|
-
console.warn("[RFWebRTC] Could not add transceiver:",
|
|
458
|
+
s.addTransceiver("video", { direction: "recvonly" });
|
|
459
|
+
} catch (m) {
|
|
460
|
+
console.warn("[RFWebRTC] Could not add transceiver:", m);
|
|
459
461
|
}
|
|
460
|
-
r && r.getVideoTracks().forEach((
|
|
462
|
+
r && r.getVideoTracks().forEach((m) => {
|
|
461
463
|
try {
|
|
462
|
-
|
|
464
|
+
m.contentHint = "detail";
|
|
463
465
|
} catch {
|
|
464
466
|
}
|
|
465
|
-
|
|
467
|
+
s.addTrack(m, r);
|
|
466
468
|
});
|
|
467
|
-
const
|
|
469
|
+
const h = G(s), y = s.createDataChannel("inference", {
|
|
468
470
|
ordered: !0
|
|
469
471
|
});
|
|
470
|
-
let
|
|
471
|
-
e && (
|
|
472
|
-
const
|
|
473
|
-
return await
|
|
474
|
-
pc:
|
|
475
|
-
offer:
|
|
476
|
-
remoteStreamPromise:
|
|
477
|
-
dataChannel:
|
|
478
|
-
uploadChannel:
|
|
472
|
+
let f;
|
|
473
|
+
e && (f = s.createDataChannel("video_upload"));
|
|
474
|
+
const d = await s.createOffer();
|
|
475
|
+
return await s.setLocalDescription(d), await H(s), {
|
|
476
|
+
pc: s,
|
|
477
|
+
offer: s.localDescription,
|
|
478
|
+
remoteStreamPromise: h,
|
|
479
|
+
dataChannel: y,
|
|
480
|
+
uploadChannel: f
|
|
479
481
|
};
|
|
480
482
|
}
|
|
481
|
-
async function
|
|
482
|
-
const e = r.getSenders().find((
|
|
483
|
+
async function Q(r) {
|
|
484
|
+
const e = r.getSenders().find((n) => n.track && n.track.kind === "video");
|
|
483
485
|
if (!e) return;
|
|
484
486
|
const t = e.getParameters();
|
|
485
487
|
t.encodings = t.encodings || [{}], t.encodings[0].scaleResolutionDownBy = 1;
|
|
486
488
|
try {
|
|
487
489
|
await e.setParameters(t);
|
|
488
|
-
} catch (
|
|
489
|
-
console.warn("[RFWebRTC] Failed to set encoding parameters:",
|
|
490
|
+
} catch (n) {
|
|
491
|
+
console.warn("[RFWebRTC] Failed to set encoding parameters:", n);
|
|
490
492
|
}
|
|
491
493
|
}
|
|
492
|
-
function
|
|
493
|
-
return new Promise((t,
|
|
494
|
+
function X(r, e = 3e4) {
|
|
495
|
+
return new Promise((t, n) => {
|
|
494
496
|
if (r.readyState === "open") {
|
|
495
497
|
t();
|
|
496
498
|
return;
|
|
497
499
|
}
|
|
498
500
|
const o = () => {
|
|
499
|
-
r.removeEventListener("open", o), r.removeEventListener("error",
|
|
500
|
-
},
|
|
501
|
-
r.removeEventListener("open", o), r.removeEventListener("error",
|
|
501
|
+
r.removeEventListener("open", o), r.removeEventListener("error", a), clearTimeout(i), t();
|
|
502
|
+
}, a = () => {
|
|
503
|
+
r.removeEventListener("open", o), r.removeEventListener("error", a), clearTimeout(i), n(new Error("Datachannel error"));
|
|
502
504
|
}, i = setTimeout(() => {
|
|
503
|
-
r.removeEventListener("open", o), r.removeEventListener("error",
|
|
505
|
+
r.removeEventListener("open", o), r.removeEventListener("error", a), n(new Error("Datachannel open timeout"));
|
|
504
506
|
}, e);
|
|
505
|
-
r.addEventListener("open", o), r.addEventListener("error",
|
|
507
|
+
r.addEventListener("open", o), r.addEventListener("error", a);
|
|
506
508
|
});
|
|
507
509
|
}
|
|
508
|
-
class
|
|
510
|
+
class x {
|
|
509
511
|
/** @private */
|
|
510
|
-
constructor(e, t,
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
this.pc = e, this._localStream = i == null ? void 0 : i.localStream, this.remoteStreamPromise = t, this.pipelineId =
|
|
522
|
-
const
|
|
523
|
-
|
|
512
|
+
constructor(e, t, n, o, a, i) {
|
|
513
|
+
l(this, "pc");
|
|
514
|
+
l(this, "_localStream");
|
|
515
|
+
l(this, "remoteStreamPromise");
|
|
516
|
+
l(this, "pipelineId");
|
|
517
|
+
l(this, "apiKey");
|
|
518
|
+
l(this, "dataChannel");
|
|
519
|
+
l(this, "reassembler");
|
|
520
|
+
l(this, "uploadChannel");
|
|
521
|
+
l(this, "uploader");
|
|
522
|
+
l(this, "onComplete");
|
|
523
|
+
this.pc = e, this._localStream = i == null ? void 0 : i.localStream, this.remoteStreamPromise = t, this.pipelineId = n, this.apiKey = o, this.dataChannel = a, this.reassembler = new D(), this.uploadChannel = i == null ? void 0 : i.uploadChannel, this.onComplete = i == null ? void 0 : i.onComplete, this.dataChannel.binaryType = "arraybuffer";
|
|
524
|
+
const u = i == null ? void 0 : i.onData;
|
|
525
|
+
u && (this.dataChannel.addEventListener("message", (c) => {
|
|
524
526
|
try {
|
|
525
527
|
if (c.data instanceof ArrayBuffer) {
|
|
526
|
-
const { frameId: s, chunkIndex:
|
|
527
|
-
if (
|
|
528
|
-
const
|
|
529
|
-
|
|
528
|
+
const { frameId: s, chunkIndex: h, totalChunks: y, payload: f } = N(c.data), d = this.reassembler.processChunk(s, h, y, f);
|
|
529
|
+
if (d) {
|
|
530
|
+
const S = new TextDecoder("utf-8").decode(d), v = JSON.parse(S);
|
|
531
|
+
u(v);
|
|
530
532
|
}
|
|
531
533
|
} else {
|
|
532
534
|
const s = JSON.parse(c.data);
|
|
533
|
-
|
|
535
|
+
u(s);
|
|
534
536
|
}
|
|
535
537
|
} catch (s) {
|
|
536
538
|
console.error("[RFWebRTC] Failed to parse data channel message:", s);
|
|
@@ -591,11 +593,11 @@ class O {
|
|
|
591
593
|
async cleanup() {
|
|
592
594
|
if (this.uploader && this.uploader.cancel(), this.reassembler.clear(), this.pipelineId && this.apiKey)
|
|
593
595
|
try {
|
|
594
|
-
await
|
|
596
|
+
await E.init({ apiKey: this.apiKey }).terminatePipeline({ pipelineId: this.pipelineId });
|
|
595
597
|
} catch (e) {
|
|
596
598
|
console.warn("[RFWebRTC] Failed to terminate pipeline:", e);
|
|
597
599
|
}
|
|
598
|
-
this.pc && this.pc.connectionState !== "closed" && this.pc.close(), this._localStream &&
|
|
600
|
+
this.pc && this.pc.connectionState !== "closed" && this.pc.close(), this._localStream && P(this._localStream);
|
|
599
601
|
}
|
|
600
602
|
/**
|
|
601
603
|
* Start uploading a file through the connection
|
|
@@ -615,7 +617,7 @@ class O {
|
|
|
615
617
|
async startUpload(e, t) {
|
|
616
618
|
if (!this.uploadChannel)
|
|
617
619
|
throw new Error("No upload channel available. This connection was not created for file uploads.");
|
|
618
|
-
await
|
|
620
|
+
await X(this.uploadChannel), this.uploader = new O(e, this.uploadChannel), await this.uploader.upload(t);
|
|
619
621
|
}
|
|
620
622
|
/**
|
|
621
623
|
* Cancel any ongoing file upload
|
|
@@ -676,117 +678,136 @@ class O {
|
|
|
676
678
|
}
|
|
677
679
|
}
|
|
678
680
|
}
|
|
679
|
-
async function
|
|
681
|
+
async function F({
|
|
680
682
|
source: r,
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
683
|
+
rtspUrl: e,
|
|
684
|
+
connector: t,
|
|
685
|
+
wrtcParams: n,
|
|
686
|
+
onData: o,
|
|
687
|
+
onComplete: a,
|
|
688
|
+
onFileUploadProgress: i,
|
|
689
|
+
options: u = {}
|
|
687
690
|
}) {
|
|
688
|
-
var
|
|
689
|
-
if (!
|
|
691
|
+
var W;
|
|
692
|
+
if (!t || typeof t.connectWrtc != "function")
|
|
690
693
|
throw new Error("connector must have a connectWrtc method");
|
|
691
|
-
const
|
|
692
|
-
let
|
|
693
|
-
if ((!
|
|
694
|
+
const c = !!e, s = !c && r instanceof File, h = !c && !s && r ? r : void 0, y = s ? r : void 0;
|
|
695
|
+
let f = n.iceServers;
|
|
696
|
+
if ((!f || f.length === 0) && t.getIceServers)
|
|
694
697
|
try {
|
|
695
|
-
const
|
|
696
|
-
|
|
697
|
-
} catch (
|
|
698
|
-
console.warn("[RFWebRTC] Failed to fetch TURN config, using defaults:",
|
|
698
|
+
const g = await t.getIceServers();
|
|
699
|
+
g && g.length > 0 && (f = g, console.log("[RFWebRTC] Using TURN servers from connector"));
|
|
700
|
+
} catch (g) {
|
|
701
|
+
console.warn("[RFWebRTC] Failed to fetch TURN config, using defaults:", g);
|
|
699
702
|
}
|
|
700
|
-
const { pc:
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
703
|
+
const { pc: d, offer: m, remoteStreamPromise: S, dataChannel: v, uploadChannel: _ } = await Z(
|
|
704
|
+
h,
|
|
705
|
+
y,
|
|
706
|
+
f,
|
|
707
|
+
e
|
|
708
|
+
), k = {
|
|
709
|
+
...n,
|
|
710
|
+
iceServers: f,
|
|
711
|
+
realtimeProcessing: n.realtimeProcessing ?? !s,
|
|
712
|
+
rtspUrl: e
|
|
713
|
+
}, w = await t.connectWrtc(
|
|
714
|
+
{ sdp: m.sdp, type: m.type },
|
|
715
|
+
k
|
|
716
|
+
), p = { sdp: w.sdp, type: w.type };
|
|
712
717
|
if (!(p != null && p.sdp) || !(p != null && p.type))
|
|
713
|
-
throw console.error("[RFWebRTC] Invalid answer from server:",
|
|
714
|
-
const
|
|
715
|
-
await
|
|
716
|
-
const
|
|
717
|
-
|
|
718
|
+
throw console.error("[RFWebRTC] Invalid answer from server:", w), new Error("connector.connectWrtc must return answer with sdp and type");
|
|
719
|
+
const R = ((W = w == null ? void 0 : w.context) == null ? void 0 : W.pipeline_id) || null;
|
|
720
|
+
await d.setRemoteDescription(p), await new Promise((g, I) => {
|
|
721
|
+
const C = () => {
|
|
722
|
+
d.connectionState === "connected" ? (d.removeEventListener("connectionstatechange", C), g()) : d.connectionState === "failed" && (d.removeEventListener("connectionstatechange", C), I(new Error("WebRTC connection failed")));
|
|
718
723
|
};
|
|
719
|
-
|
|
720
|
-
|
|
724
|
+
d.addEventListener("connectionstatechange", C), C(), setTimeout(() => {
|
|
725
|
+
d.removeEventListener("connectionstatechange", C), I(new Error("WebRTC connection timeout after 30s"));
|
|
721
726
|
}, 3e4);
|
|
722
|
-
}),
|
|
723
|
-
const
|
|
724
|
-
|
|
725
|
-
w,
|
|
727
|
+
}), h && u.disableInputStreamDownscaling !== !1 && await Q(d);
|
|
728
|
+
const U = t._apiKey || null, b = new x(
|
|
729
|
+
d,
|
|
726
730
|
S,
|
|
727
|
-
C,
|
|
728
731
|
R,
|
|
732
|
+
U,
|
|
733
|
+
v,
|
|
729
734
|
{
|
|
730
|
-
localStream:
|
|
731
|
-
uploadChannel:
|
|
732
|
-
onData:
|
|
733
|
-
onComplete:
|
|
735
|
+
localStream: h,
|
|
736
|
+
uploadChannel: _,
|
|
737
|
+
onData: o,
|
|
738
|
+
onComplete: a
|
|
734
739
|
}
|
|
735
740
|
);
|
|
736
|
-
return
|
|
737
|
-
console.error("[RFWebRTC] Upload error:",
|
|
738
|
-
}),
|
|
741
|
+
return y && _ && b.startUpload(y, i).catch((g) => {
|
|
742
|
+
console.error("[RFWebRTC] Upload error:", g);
|
|
743
|
+
}), b;
|
|
739
744
|
}
|
|
740
|
-
async function
|
|
745
|
+
async function Y({
|
|
741
746
|
source: r,
|
|
742
747
|
connector: e,
|
|
743
748
|
wrtcParams: t,
|
|
744
|
-
onData:
|
|
749
|
+
onData: n,
|
|
745
750
|
options: o = {}
|
|
746
751
|
}) {
|
|
747
752
|
if (r instanceof File)
|
|
748
753
|
throw new Error("useStream requires a MediaStream. Use useVideoFile for File uploads.");
|
|
749
|
-
return
|
|
754
|
+
return F({
|
|
750
755
|
source: r,
|
|
751
756
|
connector: e,
|
|
752
757
|
wrtcParams: t,
|
|
753
|
-
onData:
|
|
758
|
+
onData: n,
|
|
754
759
|
options: o
|
|
755
760
|
});
|
|
756
761
|
}
|
|
757
|
-
async function
|
|
762
|
+
async function ee({
|
|
758
763
|
file: r,
|
|
759
764
|
connector: e,
|
|
760
765
|
wrtcParams: t,
|
|
761
|
-
onData:
|
|
766
|
+
onData: n,
|
|
762
767
|
onUploadProgress: o,
|
|
763
|
-
onComplete:
|
|
768
|
+
onComplete: a
|
|
764
769
|
}) {
|
|
765
|
-
return
|
|
770
|
+
return F({
|
|
766
771
|
source: r,
|
|
767
772
|
connector: e,
|
|
768
773
|
wrtcParams: {
|
|
769
774
|
...t,
|
|
770
775
|
realtimeProcessing: t.realtimeProcessing ?? !0
|
|
771
776
|
},
|
|
772
|
-
onData:
|
|
773
|
-
onComplete:
|
|
777
|
+
onData: n,
|
|
778
|
+
onComplete: a,
|
|
774
779
|
onFileUploadProgress: o
|
|
775
780
|
});
|
|
776
781
|
}
|
|
777
|
-
|
|
782
|
+
async function te({
|
|
783
|
+
rtspUrl: r,
|
|
784
|
+
connector: e,
|
|
785
|
+
wrtcParams: t,
|
|
786
|
+
onData: n
|
|
787
|
+
}) {
|
|
788
|
+
if (!r.startsWith("rtsp://") && !r.startsWith("rtsps://"))
|
|
789
|
+
throw new Error("Invalid RTSP URL: must start with rtsp:// or rtsps://");
|
|
790
|
+
return F({
|
|
791
|
+
rtspUrl: r,
|
|
792
|
+
connector: e,
|
|
793
|
+
wrtcParams: t,
|
|
794
|
+
onData: n
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
const oe = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
778
798
|
__proto__: null,
|
|
779
|
-
ChunkReassembler:
|
|
780
|
-
FileUploader:
|
|
781
|
-
RFWebRTCConnection:
|
|
782
|
-
parseBinaryHeader:
|
|
783
|
-
|
|
784
|
-
|
|
799
|
+
ChunkReassembler: D,
|
|
800
|
+
FileUploader: O,
|
|
801
|
+
RFWebRTCConnection: x,
|
|
802
|
+
parseBinaryHeader: N,
|
|
803
|
+
useRtspStream: te,
|
|
804
|
+
useStream: Y,
|
|
805
|
+
useVideoFile: ee
|
|
785
806
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
786
807
|
export {
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
808
|
+
E as InferenceHTTPClient,
|
|
809
|
+
ne as connectors,
|
|
810
|
+
ae as streams,
|
|
811
|
+
oe as webrtc
|
|
791
812
|
};
|
|
792
813
|
//# sourceMappingURL=index.es.js.map
|