wrplayer 1.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.
@@ -0,0 +1,378 @@
1
+ import { ref, onMounted, onUnmounted, watch, computed } from 'vue';
2
+ import WRPlayer from '../../core/WRPlayer.js';
3
+
4
+ const PTZ_EVENTS = [
5
+ 'ptz:move', 'ptz:zoom', 'ptz:focus', 'ptz:iris', 'ptz:speed:change',
6
+ 'ptz:preset:list', 'ptz:preset:saved', 'ptz:preset:called', 'ptz:preset:deleted',
7
+ 'ptz:cruise:started', 'ptz:cruise:stopped', 'ptz:cruise:speed:set',
8
+ 'ptz:scan:started', 'ptz:scan:stopped', 'ptz:scan:boundary:left', 'ptz:scan:boundary:right',
9
+ 'ptz:request:success', 'ptz:request:error'
10
+ ];
11
+
12
+ const VOICE_INTERCOM_EVENTS = [
13
+ 'voiceIntercom:statusChange', 'voiceIntercom:modeChange', 'voiceIntercom:error',
14
+ 'voiceIntercom:localStream', 'voiceIntercom:remoteStream'
15
+ ];
16
+
17
+ /**
18
+ * Vue 3 Composition API for WRPlayer with PTZ and Voice Intercom support
19
+ * @param {Object} config - Player configuration
20
+ * @returns {Object} Player instance and utilities
21
+ */
22
+ export function useWRPlayer(config) {
23
+ const elementRef = ref(null);
24
+ const player = ref(null);
25
+ const isReady = ref(false);
26
+ const error = ref(null);
27
+ const ptzAvailable = ref(false);
28
+ const voiceIntercomAvailable = ref(false);
29
+ const voiceIntercomStatus = ref(null);
30
+
31
+ const initPlayer = () => {
32
+ if (!elementRef.value || !config.url) return;
33
+
34
+ try {
35
+ const wrPlayer = new WRPlayer({
36
+ element: elementRef.value,
37
+ ...config
38
+ });
39
+
40
+ player.value = wrPlayer;
41
+ ptzAvailable.value = !!wrPlayer.ptz;
42
+ voiceIntercomAvailable.value = !!wrPlayer.voiceIntercom;
43
+
44
+ wrPlayer.on('ready', () => {
45
+ isReady.value = true;
46
+ error.value = null;
47
+ });
48
+
49
+ wrPlayer.on('error', (errorData) => {
50
+ error.value = errorData;
51
+ isReady.value = false;
52
+ });
53
+
54
+ if (wrPlayer.voiceIntercom) {
55
+ wrPlayer.on('voiceIntercom:statusChange', (data) => {
56
+ voiceIntercomStatus.value = data;
57
+ });
58
+ }
59
+
60
+ } catch (err) {
61
+ error.value = { type: 'init_error', details: err };
62
+ }
63
+ };
64
+
65
+ const destroyPlayer = () => {
66
+ if (player.value) {
67
+ player.value.stop();
68
+ player.value = null;
69
+ }
70
+ isReady.value = false;
71
+ error.value = null;
72
+ ptzAvailable.value = false;
73
+ voiceIntercomAvailable.value = false;
74
+ voiceIntercomStatus.value = null;
75
+ };
76
+
77
+ const play = () => {
78
+ if (player.value) {
79
+ player.value.play();
80
+ }
81
+ };
82
+
83
+ const pause = () => {
84
+ if (player.value) {
85
+ player.value.pause();
86
+ }
87
+ };
88
+
89
+ const stop = () => {
90
+ if (player.value) {
91
+ player.value.stop();
92
+ }
93
+ };
94
+
95
+ const ptz = computed(() => {
96
+ if (!ptzAvailable.value || !player.value?.ptz) return null;
97
+
98
+ return {
99
+ move: (direction, speed) => player.value.ptz.move(direction, speed),
100
+ zoom: (direction, speed) => player.value.ptz.zoom(direction, speed),
101
+ focus: (direction, speed) => player.value.ptz.focus(direction, speed),
102
+ iris: (direction, speed) => player.value.ptz.iris(direction, speed),
103
+ stop: () => player.value.ptz.stop(),
104
+ setSpeed: (speed) => player.value.ptz.setSpeed(speed),
105
+ getSpeed: () => player.value.ptz.getSpeed(),
106
+ preset: player.value.ptz.preset,
107
+ cruise: player.value.ptz.cruise,
108
+ scan: player.value.ptz.scan
109
+ };
110
+ });
111
+
112
+ const voiceIntercom = computed(() => {
113
+ if (!voiceIntercomAvailable.value || !player.value?.voiceIntercom) return null;
114
+
115
+ return {
116
+ start: (deviceId, channelId, mode) =>
117
+ player.value.voiceIntercom.startIntercom(deviceId, channelId, mode),
118
+ stop: () => player.value.voiceIntercom.stopIntercom(),
119
+ setMode: (mode) => player.value.voiceIntercom.setMode(mode),
120
+ getStatus: () => player.value.voiceIntercom.getStatus(),
121
+ status: voiceIntercomStatus.value
122
+ };
123
+ });
124
+
125
+ watch(
126
+ () => [config.url, config.type],
127
+ () => {
128
+ destroyPlayer();
129
+ if (config.url) {
130
+ initPlayer();
131
+ }
132
+ }
133
+ );
134
+
135
+ onMounted(() => {
136
+ if (config.url) {
137
+ initPlayer();
138
+ }
139
+ });
140
+
141
+ onUnmounted(() => {
142
+ destroyPlayer();
143
+ });
144
+
145
+ return {
146
+ elementRef,
147
+ player: computed(() => player.value),
148
+ isReady: computed(() => isReady.value),
149
+ error: computed(() => error.value),
150
+ ptzAvailable: computed(() => ptzAvailable.value),
151
+ voiceIntercomAvailable: computed(() => voiceIntercomAvailable.value),
152
+ voiceIntercomStatus: computed(() => voiceIntercomStatus.value),
153
+ play,
154
+ pause,
155
+ stop,
156
+ ptz,
157
+ voiceIntercom
158
+ };
159
+ }
160
+
161
+ /**
162
+ * Vue 3 Component for WRPlayer with PTZ and Voice Intercom support
163
+ */
164
+ export const WRPlayerComponent = {
165
+ name: 'WRPlayer',
166
+ props: {
167
+ config: {
168
+ type: Object,
169
+ required: true
170
+ },
171
+ className: {
172
+ type: String,
173
+ default: ''
174
+ }
175
+ },
176
+ emits: ['ready', 'error', 'ptz-event', 'voice-intercom-event'],
177
+ setup(props, { emit }) {
178
+ const {
179
+ elementRef,
180
+ player,
181
+ isReady,
182
+ error,
183
+ ptzAvailable,
184
+ voiceIntercomAvailable,
185
+ voiceIntercomStatus,
186
+ play,
187
+ pause,
188
+ stop,
189
+ ptz,
190
+ voiceIntercom
191
+ } = useWRPlayer(props.config);
192
+
193
+ watch(isReady, (ready) => {
194
+ if (ready) {
195
+ emit('ready', player.value);
196
+ }
197
+ });
198
+
199
+ watch(error, (err) => {
200
+ if (err) {
201
+ emit('error', err);
202
+ }
203
+ });
204
+
205
+ watch(player, (newPlayer, oldPlayer) => {
206
+ if (oldPlayer) {
207
+ PTZ_EVENTS.forEach(event => {
208
+ oldPlayer.off(event);
209
+ });
210
+ VOICE_INTERCOM_EVENTS.forEach(event => {
211
+ oldPlayer.off(event);
212
+ });
213
+ }
214
+
215
+ if (newPlayer) {
216
+ PTZ_EVENTS.forEach(event => {
217
+ newPlayer.on(event, (data) => {
218
+ emit('ptz-event', { event, data });
219
+ });
220
+ });
221
+
222
+ VOICE_INTERCOM_EVENTS.forEach(event => {
223
+ newPlayer.on(event, (data) => {
224
+ emit('voice-intercom-event', { event, data });
225
+ });
226
+ });
227
+ }
228
+ });
229
+
230
+ return {
231
+ elementRef,
232
+ player,
233
+ isReady,
234
+ error,
235
+ ptzAvailable,
236
+ voiceIntercomAvailable,
237
+ voiceIntercomStatus,
238
+ play,
239
+ pause,
240
+ stop,
241
+ ptz,
242
+ voiceIntercom
243
+ };
244
+ },
245
+ template: `
246
+ <video
247
+ ref="elementRef"
248
+ :class="className"
249
+ />
250
+ `
251
+ };
252
+
253
+ // Vue 2 compatibility
254
+ export const WRPlayerVue2 = {
255
+ name: 'WRPlayer',
256
+ props: {
257
+ config: {
258
+ type: Object,
259
+ required: true
260
+ },
261
+ className: {
262
+ type: String,
263
+ default: ''
264
+ }
265
+ },
266
+ data() {
267
+ return {
268
+ player: null,
269
+ isReady: false,
270
+ error: null,
271
+ ptzAvailable: false
272
+ };
273
+ },
274
+ computed: {
275
+ ptz() {
276
+ if (!this.ptzAvailable || !this.player?.ptz) return null;
277
+
278
+ return {
279
+ move: (direction, speed) => this.player.ptz.move(direction, speed),
280
+ zoom: (direction, speed) => this.player.ptz.zoom(direction, speed),
281
+ focus: (direction, speed) => this.player.ptz.focus(direction, speed),
282
+ iris: (direction, speed) => this.player.ptz.iris(direction, speed),
283
+ stop: () => this.player.ptz.stop(),
284
+ setSpeed: (speed) => this.player.ptz.setSpeed(speed),
285
+ getSpeed: () => this.player.ptz.getSpeed(),
286
+ preset: this.player.ptz.preset,
287
+ cruise: this.player.ptz.cruise,
288
+ scan: this.player.ptz.scan
289
+ };
290
+ }
291
+ },
292
+ watch: {
293
+ 'config.url'() {
294
+ this.initPlayer();
295
+ }
296
+ },
297
+ mounted() {
298
+ this.initPlayer();
299
+ },
300
+ beforeDestroy() {
301
+ this.destroyPlayer();
302
+ },
303
+ methods: {
304
+ initPlayer() {
305
+ this.destroyPlayer();
306
+
307
+ if (!this.config.url) return;
308
+
309
+ try {
310
+ const player = new WRPlayer({
311
+ element: this.$refs.video,
312
+ ...this.config
313
+ });
314
+
315
+ this.player = player;
316
+ this.ptzAvailable = !!player.ptz;
317
+
318
+ player.on('ready', () => {
319
+ this.isReady = true;
320
+ this.error = null;
321
+ this.$emit('ready', player);
322
+ });
323
+
324
+ player.on('error', (errorData) => {
325
+ this.error = errorData;
326
+ this.isReady = false;
327
+ this.$emit('error', errorData);
328
+ });
329
+
330
+ PTZ_EVENTS.forEach(event => {
331
+ player.on(event, (data) => {
332
+ this.$emit('ptz-event', { event, data });
333
+ });
334
+ });
335
+
336
+ } catch (err) {
337
+ this.error = { type: 'init_error', details: err };
338
+ this.$emit('error', this.error);
339
+ }
340
+ },
341
+
342
+ destroyPlayer() {
343
+ if (this.player) {
344
+ this.player.stop();
345
+ this.player = null;
346
+ }
347
+ this.isReady = false;
348
+ this.error = null;
349
+ this.ptzAvailable = false;
350
+ },
351
+
352
+ play() {
353
+ if (this.player) {
354
+ this.player.play();
355
+ }
356
+ },
357
+
358
+ pause() {
359
+ if (this.player) {
360
+ this.player.pause();
361
+ }
362
+ },
363
+
364
+ stop() {
365
+ if (this.player) {
366
+ this.player.stop();
367
+ }
368
+ }
369
+ },
370
+ template: `
371
+ <video
372
+ ref="video"
373
+ :class="className"
374
+ />
375
+ `
376
+ };
377
+
378
+ export default { useWRPlayer, WRPlayerComponent, WRPlayerVue2 };