vue-streaming 0.1.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +425 -699
- package/dist/WebSocketStream.vue_vue_type_script_setup_true_lang-C_F2vNNk.js +1081 -0
- package/dist/WebSocketStream.vue_vue_type_script_setup_true_lang-C_F2vNNk.js.map +1 -0
- package/dist/WebSocketStream.vue_vue_type_script_setup_true_lang-EzMJEQkx.cjs +2 -0
- package/dist/WebSocketStream.vue_vue_type_script_setup_true_lang-EzMJEQkx.cjs.map +1 -0
- package/dist/components/index.cjs +2 -0
- package/dist/components/index.cjs.map +1 -0
- package/dist/components/index.js +15 -0
- package/dist/components/index.js.map +1 -0
- package/dist/composables/index.cjs +2 -0
- package/dist/composables/index.cjs.map +1 -0
- package/dist/composables/index.js +15 -0
- package/dist/composables/index.js.map +1 -0
- package/dist/index.cjs +1 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +62 -2
- package/dist/index.js.map +1 -1
- package/dist/types.cjs +2 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/usePointCloud-D0qcpYFY.js +115 -0
- package/dist/usePointCloud-D0qcpYFY.js.map +1 -0
- package/dist/usePointCloud-D2csBAs8.cjs +2 -0
- package/dist/usePointCloud-D2csBAs8.cjs.map +1 -0
- package/dist/useWebSocket-7-qar6to.cjs +4 -0
- package/dist/useWebSocket-7-qar6to.cjs.map +1 -0
- package/dist/useWebSocket-CrE6QkTW.js +1278 -0
- package/dist/useWebSocket-CrE6QkTW.js.map +1 -0
- package/dist/utils/index.cjs +2 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.js +503 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/vue-streaming.css +1 -0
- package/package.json +126 -69
- package/dist/index.d.cts +0 -49
- package/dist/index.d.ts +0 -49
- package/dist/index.global.js +0 -8
- package/dist/index.global.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,699 +1,425 @@
|
|
|
1
|
-
# vue-streaming
|
|
2
|
-
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
</
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
- **
|
|
30
|
-
- **
|
|
31
|
-
- **
|
|
32
|
-
- **
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
{
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
{
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
{
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
<
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
## 🔧 TypeScript Support
|
|
428
|
-
|
|
429
|
-
Vue Streaming is fully typed. Import types for enhanced development experience:
|
|
430
|
-
|
|
431
|
-
```typescript
|
|
432
|
-
import type {
|
|
433
|
-
StreamType,
|
|
434
|
-
StreamStatus,
|
|
435
|
-
StreamState,
|
|
436
|
-
StreamAPI,
|
|
437
|
-
} from "vue-streaming";
|
|
438
|
-
|
|
439
|
-
// Component instance type
|
|
440
|
-
import { StreamPlayer } from "vue-streaming";
|
|
441
|
-
type StreamPlayerInstance = InstanceType<typeof StreamPlayer>;
|
|
442
|
-
|
|
443
|
-
// Usage in composition function
|
|
444
|
-
function useStreamPlayer() {
|
|
445
|
-
const player = ref<StreamPlayerInstance>();
|
|
446
|
-
const status = computed(() => player.value?.status || "idle");
|
|
447
|
-
|
|
448
|
-
return { player, status };
|
|
449
|
-
}
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
## 🌐 Nuxt 3 / SSR Usage
|
|
453
|
-
|
|
454
|
-
For server-side rendering, wrap the component to prevent hydration issues:
|
|
455
|
-
|
|
456
|
-
```vue
|
|
457
|
-
<template>
|
|
458
|
-
<div>
|
|
459
|
-
<ClientOnly>
|
|
460
|
-
<StreamPlayer type="websocket" :config="config" :auto-open="true" />
|
|
461
|
-
<template #fallback>
|
|
462
|
-
<div>Loading stream player...</div>
|
|
463
|
-
</template>
|
|
464
|
-
</ClientOnly>
|
|
465
|
-
</div>
|
|
466
|
-
</template>
|
|
467
|
-
```
|
|
468
|
-
|
|
469
|
-
Or create an async component:
|
|
470
|
-
|
|
471
|
-
```vue
|
|
472
|
-
<script setup lang="ts">
|
|
473
|
-
import { defineAsyncComponent } from "vue";
|
|
474
|
-
|
|
475
|
-
const StreamPlayer = defineAsyncComponent(() =>
|
|
476
|
-
import("vue-streaming").then((m) => m.StreamPlayer)
|
|
477
|
-
);
|
|
478
|
-
</script>
|
|
479
|
-
```
|
|
480
|
-
|
|
481
|
-
## 📱 Real-World Examples
|
|
482
|
-
|
|
483
|
-
### Chat Application
|
|
484
|
-
|
|
485
|
-
```vue
|
|
486
|
-
<script setup lang="ts">
|
|
487
|
-
import { ref } from "vue";
|
|
488
|
-
import { StreamPlayer } from "vue-streaming";
|
|
489
|
-
|
|
490
|
-
const message = ref("");
|
|
491
|
-
const chatPlayer = ref<InstanceType<typeof StreamPlayer>>();
|
|
492
|
-
|
|
493
|
-
const config = {
|
|
494
|
-
url: "wss://chat.example.com/ws",
|
|
495
|
-
protocols: ["chat-v1"],
|
|
496
|
-
};
|
|
497
|
-
|
|
498
|
-
function sendMessage() {
|
|
499
|
-
if (message.value.trim()) {
|
|
500
|
-
chatPlayer.value?.send({
|
|
501
|
-
type: "message",
|
|
502
|
-
content: message.value,
|
|
503
|
-
timestamp: new Date().toISOString(),
|
|
504
|
-
});
|
|
505
|
-
message.value = "";
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
function handleChatMessage(msg: any) {
|
|
510
|
-
if (msg.type === "message") {
|
|
511
|
-
// Handle incoming chat message
|
|
512
|
-
console.log(`${msg.user}: ${msg.content}`);
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
</script>
|
|
516
|
-
|
|
517
|
-
<template>
|
|
518
|
-
<div class="chat-container">
|
|
519
|
-
<StreamPlayer
|
|
520
|
-
ref="chatPlayer"
|
|
521
|
-
type="websocket"
|
|
522
|
-
:config="config"
|
|
523
|
-
:auto-open="true"
|
|
524
|
-
@message="handleChatMessage"
|
|
525
|
-
>
|
|
526
|
-
<template #log="{ messages }">
|
|
527
|
-
<div class="chat-messages">
|
|
528
|
-
<div v-for="msg in messages" :key="msg.id" class="message">
|
|
529
|
-
<strong>{{ msg.user }}:</strong> {{ msg.content }}
|
|
530
|
-
</div>
|
|
531
|
-
</div>
|
|
532
|
-
</template>
|
|
533
|
-
|
|
534
|
-
<template #actions="{ isOpen }">
|
|
535
|
-
<div class="chat-input">
|
|
536
|
-
<input
|
|
537
|
-
v-model="message"
|
|
538
|
-
@keyup.enter="sendMessage"
|
|
539
|
-
:disabled="!isOpen"
|
|
540
|
-
placeholder="Type a message..."
|
|
541
|
-
/>
|
|
542
|
-
<button @click="sendMessage" :disabled="!isOpen">Send</button>
|
|
543
|
-
</div>
|
|
544
|
-
</template>
|
|
545
|
-
</StreamPlayer>
|
|
546
|
-
</div>
|
|
547
|
-
</template>
|
|
548
|
-
```
|
|
549
|
-
|
|
550
|
-
### Live Data Dashboard
|
|
551
|
-
|
|
552
|
-
```vue
|
|
553
|
-
<script setup lang="ts">
|
|
554
|
-
import { ref, computed } from "vue";
|
|
555
|
-
import { StreamPlayer } from "vue-streaming";
|
|
556
|
-
|
|
557
|
-
const metrics = ref<any[]>([]);
|
|
558
|
-
|
|
559
|
-
const config = {
|
|
560
|
-
url: "/api/metrics/stream",
|
|
561
|
-
headers: { Accept: "text/event-stream" },
|
|
562
|
-
};
|
|
563
|
-
|
|
564
|
-
function handleMetricsUpdate(data: any) {
|
|
565
|
-
if (data.type === "metrics") {
|
|
566
|
-
metrics.value = [...metrics.value, data.payload].slice(-50); // Keep last 50
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
const latestMetrics = computed(
|
|
571
|
-
() => metrics.value[metrics.value.length - 1]?.payload || {}
|
|
572
|
-
);
|
|
573
|
-
</script>
|
|
574
|
-
|
|
575
|
-
<template>
|
|
576
|
-
<div class="dashboard">
|
|
577
|
-
<h1>Live Metrics Dashboard</h1>
|
|
578
|
-
|
|
579
|
-
<div class="metrics-grid">
|
|
580
|
-
<div class="metric-card">
|
|
581
|
-
<h3>CPU Usage</h3>
|
|
582
|
-
<div class="metric-value">{{ latestMetrics.cpu }}%</div>
|
|
583
|
-
</div>
|
|
584
|
-
<div class="metric-card">
|
|
585
|
-
<h3>Memory</h3>
|
|
586
|
-
<div class="metric-value">{{ latestMetrics.memory }}MB</div>
|
|
587
|
-
</div>
|
|
588
|
-
</div>
|
|
589
|
-
|
|
590
|
-
<StreamPlayer
|
|
591
|
-
type="sse"
|
|
592
|
-
:config="config"
|
|
593
|
-
:auto-open="true"
|
|
594
|
-
@message="handleMetricsUpdate"
|
|
595
|
-
>
|
|
596
|
-
<template #log="{ messages, status }">
|
|
597
|
-
<div class="connection-status">
|
|
598
|
-
Status: <span :class="status">{{ status }}</span> | Updates:
|
|
599
|
-
{{ messages.length }}
|
|
600
|
-
</div>
|
|
601
|
-
</template>
|
|
602
|
-
</StreamPlayer>
|
|
603
|
-
</div>
|
|
604
|
-
</template>
|
|
605
|
-
```
|
|
606
|
-
|
|
607
|
-
## 🐛 Troubleshooting
|
|
608
|
-
|
|
609
|
-
### Common Issues
|
|
610
|
-
|
|
611
|
-
**Connection fails immediately**
|
|
612
|
-
|
|
613
|
-
```typescript
|
|
614
|
-
// Check if the URL is correct and accessible
|
|
615
|
-
const config = {
|
|
616
|
-
url: "ws://localhost:3000/ws", // http:// for ws://, https:// for wss://
|
|
617
|
-
};
|
|
618
|
-
```
|
|
619
|
-
|
|
620
|
-
**CORS issues with SSE/HTTP**
|
|
621
|
-
|
|
622
|
-
```typescript
|
|
623
|
-
const config = {
|
|
624
|
-
url: "/api/stream",
|
|
625
|
-
headers: {
|
|
626
|
-
"Access-Control-Allow-Origin": "*",
|
|
627
|
-
},
|
|
628
|
-
};
|
|
629
|
-
```
|
|
630
|
-
|
|
631
|
-
**Video not playing (HLS/WebRTC)**
|
|
632
|
-
|
|
633
|
-
```vue
|
|
634
|
-
<StreamPlayer
|
|
635
|
-
type="hls"
|
|
636
|
-
:config="hlsConfig"
|
|
637
|
-
:autoplay="true"
|
|
638
|
-
:muted="true" <!-- Required for autoplay in most browsers -->
|
|
639
|
-
:plays-inline="true"
|
|
640
|
-
/>
|
|
641
|
-
```
|
|
642
|
-
|
|
643
|
-
**Messages not displaying**
|
|
644
|
-
|
|
645
|
-
```javascript
|
|
646
|
-
// Check if logLimit is sufficient
|
|
647
|
-
<StreamPlayer :log-limit="1000" />
|
|
648
|
-
|
|
649
|
-
// Or handle messages manually
|
|
650
|
-
@message="msg => console.log('Received:', msg)"
|
|
651
|
-
```
|
|
652
|
-
|
|
653
|
-
### Browser Compatibility
|
|
654
|
-
|
|
655
|
-
- **WebSocket**: All modern browsers
|
|
656
|
-
- **SSE**: All modern browsers (IE/Edge requires polyfill)
|
|
657
|
-
- **HLS**: Requires HLS.js for non-Safari browsers
|
|
658
|
-
- **WebRTC**: Modern browsers (check specific API support)
|
|
659
|
-
|
|
660
|
-
### Performance Tips
|
|
661
|
-
|
|
662
|
-
1. **Limit message history**: Use reasonable `logLimit` values
|
|
663
|
-
2. **Debounce rapid updates**: Use `shallowRef` for message arrays
|
|
664
|
-
3. **Clean up properly**: Component handles cleanup automatically
|
|
665
|
-
4. **Use object URLs**: For large binary data in WebRTC/HLS
|
|
666
|
-
|
|
667
|
-
## 🤝 Contributing
|
|
668
|
-
|
|
669
|
-
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
670
|
-
|
|
671
|
-
### Development Setup
|
|
672
|
-
|
|
673
|
-
```bash
|
|
674
|
-
git clone https://github.com/yourusername/vue-streaming.git
|
|
675
|
-
cd vue-streaming
|
|
676
|
-
npm install
|
|
677
|
-
npm run dev
|
|
678
|
-
```
|
|
679
|
-
|
|
680
|
-
### Building
|
|
681
|
-
|
|
682
|
-
```bash
|
|
683
|
-
npm run build
|
|
684
|
-
npm run test
|
|
685
|
-
```
|
|
686
|
-
|
|
687
|
-
## 📄 License
|
|
688
|
-
|
|
689
|
-
MIT © Vue Streaming Contributors
|
|
690
|
-
|
|
691
|
-
---
|
|
692
|
-
|
|
693
|
-
<div align="center">
|
|
694
|
-
|
|
695
|
-
**[Documentation](https://github.com/yourusername/vue-streaming#readme) • [Examples](https://github.com/yourusername/vue-streaming/tree/main/examples) • [Issues](https://github.com/yourusername/vue-streaming/issues)**
|
|
696
|
-
|
|
697
|
-
Made with ❤️ for the Vue.js community
|
|
698
|
-
|
|
699
|
-
</div>
|
|
1
|
+
# vue-streaming
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://www.npmjs.com/package/keroloszakaria/vue-streaming">
|
|
5
|
+
<img src="https://img.shields.io/npm/v/keroloszakaria/vue-streaming.svg" alt="npm version" />
|
|
6
|
+
</a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/keroloszakaria/vue-streaming">
|
|
8
|
+
<img src="https://img.shields.io/npm/dm/keroloszakaria/vue-streaming.svg" alt="npm downloads" />
|
|
9
|
+
</a>
|
|
10
|
+
<a href="https://vuejs.org/">
|
|
11
|
+
<img src="https://img.shields.io/badge/Vue-3.3%2B-brightgreen.svg" alt="Vue 3" />
|
|
12
|
+
</a>
|
|
13
|
+
<a href="https://www.typescriptlang.org/">
|
|
14
|
+
<img src="https://img.shields.io/badge/TypeScript-Ready-blue.svg" alt="TypeScript" />
|
|
15
|
+
</a>
|
|
16
|
+
<a href="LICENSE">
|
|
17
|
+
<img src="https://img.shields.io/badge/license-MIT-yellow.svg" alt="License" />
|
|
18
|
+
</a>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
<p align="center">
|
|
22
|
+
Comprehensive <b>Vue 3 streaming library</b> with composables for WebSocket, Socket.IO, HLS, Laravel Echo, WebRTC, Point Cloud, and Data Streaming.
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- **useWebSocket** - Native WebSocket with auto-reconnect and heartbeat
|
|
30
|
+
- **useSocketIO** - Full Socket.IO support with rooms and events
|
|
31
|
+
- **useHLS** - HTTP Live Streaming with quality control
|
|
32
|
+
- **useLaravelEcho** - Pusher/Reverb broadcasting integration
|
|
33
|
+
- **useWebRTC** - Peer connections with data channels for point cloud/detection
|
|
34
|
+
- **usePointCloud** - LiDAR/3D point cloud streaming and decoding
|
|
35
|
+
- **useDataStream** - Generic data streaming with buffering and deduplication
|
|
36
|
+
- **Components** - StreamViewer, HLSPlayer, PointCloudViewer, WebRTCViewer
|
|
37
|
+
- **TypeScript** - Full TypeScript support with exported types
|
|
38
|
+
- **Tree-shakeable** - Import only what you need
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
`bash
|
|
45
|
+
npm install vue-streaming
|
|
46
|
+
|
|
47
|
+
# yarn
|
|
48
|
+
|
|
49
|
+
yarn add vue-streaming
|
|
50
|
+
|
|
51
|
+
# pnpm
|
|
52
|
+
|
|
53
|
+
pnpm add vue-streaming
|
|
54
|
+
`
|
|
55
|
+
|
|
56
|
+
### Optional Dependencies
|
|
57
|
+
|
|
58
|
+
Install based on the features you need:
|
|
59
|
+
|
|
60
|
+
`bash
|
|
61
|
+
|
|
62
|
+
# For HLS streaming
|
|
63
|
+
|
|
64
|
+
npm install hls.js
|
|
65
|
+
|
|
66
|
+
# For Socket.IO
|
|
67
|
+
|
|
68
|
+
npm install socket.io-client
|
|
69
|
+
|
|
70
|
+
# For Laravel Echo
|
|
71
|
+
|
|
72
|
+
npm install laravel-echo pusher-js
|
|
73
|
+
|
|
74
|
+
# For Point Cloud visualization
|
|
75
|
+
|
|
76
|
+
npm install three @types/three
|
|
77
|
+
|
|
78
|
+
# For DRACO compression
|
|
79
|
+
|
|
80
|
+
npm install draco3d
|
|
81
|
+
`
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Quick Start
|
|
86
|
+
|
|
87
|
+
### WebSocket
|
|
88
|
+
|
|
89
|
+
`vue
|
|
90
|
+
|
|
91
|
+
<script setup lang="ts">
|
|
92
|
+
import { useWebSocket } from 'vue-streaming'
|
|
93
|
+
|
|
94
|
+
const { isConnected, lastMessage, connect, send, disconnect } = useWebSocket({
|
|
95
|
+
url: 'wss://example.com/ws',
|
|
96
|
+
autoConnect: true,
|
|
97
|
+
autoReconnect: true
|
|
98
|
+
}, {
|
|
99
|
+
onMessage: (data) => console.log('Received:', data)
|
|
100
|
+
})
|
|
101
|
+
</script>
|
|
102
|
+
|
|
103
|
+
`
|
|
104
|
+
|
|
105
|
+
### Socket.IO
|
|
106
|
+
|
|
107
|
+
`vue
|
|
108
|
+
|
|
109
|
+
<script setup lang="ts">
|
|
110
|
+
import { useSocketIO } from 'vue-streaming'
|
|
111
|
+
|
|
112
|
+
const { isConnected, connect, emit, on } = useSocketIO({
|
|
113
|
+
url: 'https://example.com',
|
|
114
|
+
autoConnect: true
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
// Listen to events
|
|
118
|
+
on('chat:message', (msg) => console.log(msg))
|
|
119
|
+
|
|
120
|
+
// Emit events
|
|
121
|
+
emit('chat:send', { text: 'Hello!' })
|
|
122
|
+
</script>
|
|
123
|
+
|
|
124
|
+
`
|
|
125
|
+
|
|
126
|
+
### HLS Streaming
|
|
127
|
+
|
|
128
|
+
`vue
|
|
129
|
+
|
|
130
|
+
<script setup lang="ts">
|
|
131
|
+
import { ref, onMounted } from 'vue'
|
|
132
|
+
import { useHLS } from 'vue-streaming'
|
|
133
|
+
|
|
134
|
+
const videoRef = ref<HTMLVideoElement | null>(null)
|
|
135
|
+
|
|
136
|
+
const { attach, play, levels, setLevel } = useHLS({
|
|
137
|
+
url: 'https://example.com/stream.m3u8',
|
|
138
|
+
autoPlay: true
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
onMounted(() => {
|
|
142
|
+
if (videoRef.value) {
|
|
143
|
+
attach(videoRef.value)
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
</script>
|
|
147
|
+
|
|
148
|
+
<template>
|
|
149
|
+
<video ref="videoRef" controls />
|
|
150
|
+
</template>
|
|
151
|
+
`
|
|
152
|
+
|
|
153
|
+
### Laravel Echo
|
|
154
|
+
|
|
155
|
+
`vue
|
|
156
|
+
|
|
157
|
+
<script setup lang="ts">
|
|
158
|
+
import { useLaravelEcho } from 'vue-streaming'
|
|
159
|
+
|
|
160
|
+
const { channel, privateChannel, presenceChannel } = useLaravelEcho({
|
|
161
|
+
broadcaster: 'pusher',
|
|
162
|
+
key: 'your-pusher-key',
|
|
163
|
+
cluster: 'mt1'
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
// Public channel
|
|
167
|
+
const chat = channel('chat')
|
|
168
|
+
chat.listen('MessageSent', (e) => console.log(e))
|
|
169
|
+
|
|
170
|
+
// Private channel
|
|
171
|
+
const user = privateChannel('user.1')
|
|
172
|
+
user.listen('NotificationReceived', (e) => console.log(e))
|
|
173
|
+
|
|
174
|
+
// Presence channel
|
|
175
|
+
const room = presenceChannel('room.1')
|
|
176
|
+
room.here((users) => console.log('Online:', users))
|
|
177
|
+
room.joining((user) => console.log('Joined:', user))
|
|
178
|
+
room.leaving((user) => console.log('Left:', user))
|
|
179
|
+
</script>
|
|
180
|
+
|
|
181
|
+
`
|
|
182
|
+
|
|
183
|
+
### WebRTC with Point Cloud
|
|
184
|
+
|
|
185
|
+
`vue
|
|
186
|
+
|
|
187
|
+
<script setup lang="ts">
|
|
188
|
+
import { useWebRTC } from 'vue-streaming'
|
|
189
|
+
|
|
190
|
+
const {
|
|
191
|
+
isRunning,
|
|
192
|
+
connectionState,
|
|
193
|
+
lastPointCloudFrame,
|
|
194
|
+
lastBoundingBoxes,
|
|
195
|
+
start,
|
|
196
|
+
stop
|
|
197
|
+
} = useWebRTC({
|
|
198
|
+
signalingUrl: 'wss://example.com/signaling',
|
|
199
|
+
enablePointCloud: true,
|
|
200
|
+
enableDetections: true
|
|
201
|
+
}, {
|
|
202
|
+
onPointCloudFrame: (frame) => {
|
|
203
|
+
console.log(Received ${frame.points.length} points)
|
|
204
|
+
},
|
|
205
|
+
onBoundingBoxData: (boxes) => {
|
|
206
|
+
console.log(Received ${boxes.length} detections)
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
</script>
|
|
210
|
+
|
|
211
|
+
`
|
|
212
|
+
|
|
213
|
+
### Point Cloud Decoding
|
|
214
|
+
|
|
215
|
+
`vue
|
|
216
|
+
|
|
217
|
+
<script setup lang="ts">
|
|
218
|
+
import { usePointCloud } from 'vue-streaming'
|
|
219
|
+
|
|
220
|
+
const { decode, points, bounds, isDecoding } = usePointCloud({
|
|
221
|
+
format: 'auto',
|
|
222
|
+
maxPoints: 100000,
|
|
223
|
+
downsampleFactor: 2
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
// Decode point cloud data
|
|
227
|
+
const result = await decode(arrayBuffer)
|
|
228
|
+
console.log(Decoded ${result.points.length} points)
|
|
229
|
+
</script>
|
|
230
|
+
|
|
231
|
+
`
|
|
232
|
+
|
|
233
|
+
### Data Streaming
|
|
234
|
+
|
|
235
|
+
`vue
|
|
236
|
+
|
|
237
|
+
<script setup lang="ts">
|
|
238
|
+
import { useDataStream } from 'vue-streaming'
|
|
239
|
+
|
|
240
|
+
interface SensorData {
|
|
241
|
+
id: string
|
|
242
|
+
value: number
|
|
243
|
+
timestamp: number
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const { data, buffer, push, subscribe, stats } = useDataStream<SensorData>({
|
|
247
|
+
bufferSize: 1000,
|
|
248
|
+
deduplicate: true,
|
|
249
|
+
deduplicateKey: 'id',
|
|
250
|
+
throttleMs: 100
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
// Subscribe to data
|
|
254
|
+
subscribe((item) => console.log('New data:', item))
|
|
255
|
+
|
|
256
|
+
// Push data manually
|
|
257
|
+
push({ id: 'sensor-1', value: 42, timestamp: Date.now() })
|
|
258
|
+
</script>
|
|
259
|
+
|
|
260
|
+
`
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Components
|
|
265
|
+
|
|
266
|
+
### StreamViewer
|
|
267
|
+
|
|
268
|
+
Generic stream viewer for displaying real-time data:
|
|
269
|
+
|
|
270
|
+
`vue
|
|
271
|
+
<template>
|
|
272
|
+
<StreamViewer
|
|
273
|
+
:data="streamData"
|
|
274
|
+
:max-lines="100"
|
|
275
|
+
:auto-scroll="true"
|
|
276
|
+
:show-timestamps="true"
|
|
277
|
+
/>
|
|
278
|
+
</template>
|
|
279
|
+
`
|
|
280
|
+
|
|
281
|
+
### HLSPlayer
|
|
282
|
+
|
|
283
|
+
HLS video player with quality controls:
|
|
284
|
+
|
|
285
|
+
`vue
|
|
286
|
+
<template>
|
|
287
|
+
<HLSPlayer
|
|
288
|
+
src="https://example.com/stream.m3u8"
|
|
289
|
+
:auto-play="true"
|
|
290
|
+
:controls="true"
|
|
291
|
+
:low-latency="true"
|
|
292
|
+
@ready="onReady"
|
|
293
|
+
@level-change="onQualityChange"
|
|
294
|
+
/>
|
|
295
|
+
</template>
|
|
296
|
+
`
|
|
297
|
+
|
|
298
|
+
### PointCloudViewer
|
|
299
|
+
|
|
300
|
+
3D point cloud visualization (requires three.js):
|
|
301
|
+
|
|
302
|
+
`vue
|
|
303
|
+
<template>
|
|
304
|
+
<PointCloudViewer
|
|
305
|
+
:points="pointCloudData"
|
|
306
|
+
:point-size="0.02"
|
|
307
|
+
:auto-rotate="true"
|
|
308
|
+
:show-grid="true"
|
|
309
|
+
/>
|
|
310
|
+
</template>
|
|
311
|
+
`
|
|
312
|
+
|
|
313
|
+
### WebRTCViewer
|
|
314
|
+
|
|
315
|
+
WebRTC stream viewer with connection controls:
|
|
316
|
+
|
|
317
|
+
`vue
|
|
318
|
+
<template>
|
|
319
|
+
<WebRTCViewer
|
|
320
|
+
signaling-url="wss://example.com/signaling"
|
|
321
|
+
:enable-point-cloud="true"
|
|
322
|
+
:enable-detections="true"
|
|
323
|
+
:auto-connect="true"
|
|
324
|
+
@pointcloud="onPointCloud"
|
|
325
|
+
@detections="onDetections"
|
|
326
|
+
/>
|
|
327
|
+
</template>
|
|
328
|
+
`
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## API Reference
|
|
333
|
+
|
|
334
|
+
### useWebSocket
|
|
335
|
+
|
|
336
|
+
| Option | Type | Default | Description |
|
|
337
|
+
| ---------------------- | -------------------- | -------- | ---------------------------- |
|
|
338
|
+
| `url` | `string` | required | WebSocket URL |
|
|
339
|
+
| `protocols` | `string \| string[]` | - | Subprotocols |
|
|
340
|
+
| `autoConnect` | `boolean` | `true` | Auto-connect on mount |
|
|
341
|
+
| `autoReconnect` | `boolean` | `true` | Auto-reconnect on disconnect |
|
|
342
|
+
| `maxReconnectAttempts` | `number` | `5` | Max reconnection attempts |
|
|
343
|
+
| `reconnectDelay` | `number` | `1000` | Initial reconnect delay (ms) |
|
|
344
|
+
| `heartbeatInterval` | `number` | - | Heartbeat interval (ms) |
|
|
345
|
+
|
|
346
|
+
### useSocketIO
|
|
347
|
+
|
|
348
|
+
| Option | Type | Default | Description |
|
|
349
|
+
| ------------- | --------- | -------- | ------------------------ |
|
|
350
|
+
| `url` | `string` | required | Server URL |
|
|
351
|
+
| `options` | `object` | - | Socket.IO client options |
|
|
352
|
+
| `autoConnect` | `boolean` | `true` | Auto-connect on mount |
|
|
353
|
+
|
|
354
|
+
### useHLS
|
|
355
|
+
|
|
356
|
+
| Option | Type | Default | Description |
|
|
357
|
+
| ---------------- | --------- | -------- | ----------------------------- |
|
|
358
|
+
| `url` | `string` | required | HLS manifest URL |
|
|
359
|
+
| `autoPlay` | `boolean` | `true` | Auto-play on attach |
|
|
360
|
+
| `lowLatencyMode` | `boolean` | `false` | Enable low-latency mode |
|
|
361
|
+
| `startLevel` | `number` | `-1` | Initial quality (-1 for auto) |
|
|
362
|
+
|
|
363
|
+
### useLaravelEcho
|
|
364
|
+
|
|
365
|
+
| Option | Type | Default | Description |
|
|
366
|
+
| ------------- | ------------------------------------- | -------- | ---------------- |
|
|
367
|
+
| `broadcaster` | `'pusher' \| 'socket.io' \| 'reverb'` | required | Broadcaster type |
|
|
368
|
+
| `key` | `string` | - | Pusher app key |
|
|
369
|
+
| `cluster` | `string` | - | Pusher cluster |
|
|
370
|
+
| `wsHost` | `string` | - | WebSocket host |
|
|
371
|
+
| `wsPort` | `number` | - | WebSocket port |
|
|
372
|
+
|
|
373
|
+
### useWebRTC
|
|
374
|
+
|
|
375
|
+
| Option | Type | Default | Description |
|
|
376
|
+
| ------------------ | ---------------- | -------- | -------------------------- |
|
|
377
|
+
| `signalingUrl` | `string` | required | Signaling server URL |
|
|
378
|
+
| `iceServers` | `RTCIceServer[]` | STUN | ICE servers |
|
|
379
|
+
| `enablePointCloud` | `boolean` | `true` | Enable point cloud channel |
|
|
380
|
+
| `enableDetections` | `boolean` | `true` | Enable detection channel |
|
|
381
|
+
|
|
382
|
+
### usePointCloud
|
|
383
|
+
|
|
384
|
+
| Option | Type | Default | Description |
|
|
385
|
+
| ------------------ | ------------------ | -------- | --------------------- |
|
|
386
|
+
| `format` | `PointCloudFormat` | `'auto'` | Point cloud format |
|
|
387
|
+
| `maxPoints` | `number` | - | Max points to decode |
|
|
388
|
+
| `downsampleFactor` | `number` | `1` | Downsample factor |
|
|
389
|
+
| `dracoPath` | `string` | - | Path to DRACO decoder |
|
|
390
|
+
|
|
391
|
+
### useDataStream
|
|
392
|
+
|
|
393
|
+
| Option | Type | Default | Description |
|
|
394
|
+
| ------------- | --------- | ------- | ------------------------ |
|
|
395
|
+
| `bufferSize` | `number` | `1000` | Max buffer size |
|
|
396
|
+
| `throttleMs` | `number` | - | Throttle interval |
|
|
397
|
+
| `deduplicate` | `boolean` | `false` | Enable deduplication |
|
|
398
|
+
| `batchSize` | `number` | - | Batch size for callbacks |
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## Legacy Support
|
|
403
|
+
|
|
404
|
+
The package still exports the legacy `StreamPlayer` component for backward compatibility:
|
|
405
|
+
|
|
406
|
+
`vue
|
|
407
|
+
|
|
408
|
+
<script setup>
|
|
409
|
+
import { StreamPlayer } from 'vue-streaming'
|
|
410
|
+
</script>
|
|
411
|
+
|
|
412
|
+
<template>
|
|
413
|
+
<StreamPlayer
|
|
414
|
+
type="websocket"
|
|
415
|
+
:config="{ url: 'wss://example.com' }"
|
|
416
|
+
:auto-open="true"
|
|
417
|
+
/>
|
|
418
|
+
</template>
|
|
419
|
+
`
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## License
|
|
424
|
+
|
|
425
|
+
MIT (c) [Kerolos Zakaria](https://keroloszakaria.surge.sh)
|