@vanwei-wcs/video-player-v3 0.1.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 ADDED
@@ -0,0 +1,261 @@
1
+ # WwVideoPlayer 视频播放器组件
2
+
3
+ 一个基于 Vue 3 的视频播放器组件,支持 H.264/H.265 视频播放、云台控制和实时流播放。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install ww-video-player
9
+ ```
10
+
11
+ ## 基础用法
12
+
13
+ ```vue
14
+ <template>
15
+ <WwVideoPlayer
16
+ ref="videoPlayerRef"
17
+ :options="options"
18
+ :is-live="true"
19
+ :debug="false"
20
+ :show-p-t-z="true"
21
+ :show-controller="true"
22
+ @stop-video="onStopVideo"
23
+ @quality-change="onQualityChange"
24
+ />
25
+ </template>
26
+
27
+ <script setup lang="ts">
28
+ import { ref } from 'vue'
29
+ import { WwVideoPlayer } from 'ww-video-player'
30
+ import type { VideoQuality } from 'ww-video-player'
31
+
32
+ const videoPlayerRef = ref<InstanceType<typeof WwVideoPlayer> | null>(null)
33
+
34
+ const options = {
35
+ debug: false,
36
+ mode: 'video',
37
+ baseLibPath: '/js/h265/',
38
+ }
39
+
40
+ // 播放视频
41
+ const play = async () => {
42
+ await videoPlayerRef.value?.openVideo({
43
+ url: 'ws://example.com/video',
44
+ token: 'optional-token'
45
+ })
46
+ }
47
+
48
+ // 关闭视频
49
+ const close = async () => {
50
+ await videoPlayerRef.value?.closeVideo()
51
+ }
52
+ </script>
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Props 属性
58
+
59
+ | 属性名 | 类型 | 默认值 | 说明 |
60
+ |--------|------|--------|------|
61
+ | `debug` | `boolean` | `false` | 是否开启调试模式 |
62
+ | `isLive` | `boolean` | `true` | 是否为直播模式 |
63
+ | `options` | `PlayerOptions` | 见下方 | 播放器配置选项 |
64
+ | `showPTZ` | `boolean` | `false` | 是否显示云台控制 |
65
+ | `showController` | `boolean` | `false` | 是否显示播放控制器 |
66
+
67
+ ### PlayerOptions 配置
68
+
69
+ ```ts
70
+ interface PlayerOptions {
71
+ debug: boolean // 是否调试模式
72
+ mode: 'video' | 'audio' // 播放模式
73
+ baseLibPath: string // 解码器库文件路径
74
+ decoderLogLevel?: number // 解码器日志级别
75
+ }
76
+ ```
77
+
78
+ 默认值:
79
+ ```ts
80
+ {
81
+ debug: false,
82
+ mode: 'video',
83
+ baseLibPath: '/lib/',
84
+ decoderLogLevel: 0
85
+ }
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Events 事件
91
+
92
+ | 事件名 | 参数 | 说明 |
93
+ |--------|------|------|
94
+ | `stop-video` | - | 视频停止时触发 |
95
+ | `quality-change` | `quality: VideoQuality` | 清晰度变化时触发 |
96
+ | `change-play-speed` | `speed: number` | 播放速度变化时触发 |
97
+ | `control-talk` | `status: boolean` | 对讲状态变化时触发 |
98
+ | `lock-ptz` | `status: boolean` | 云台锁定状态变化时触发 |
99
+ | `do-zoom` | `command: PTZZoomCommand` | 云台变倍指令触发 |
100
+ | `move-to-direction` | `direction: PTZDirection` | 云台方向移动指令触发 |
101
+ | `error` | `error: Error, detail?, info?` | 发生错误时触发 |
102
+ | `video-status-change` | `status: number` | 视频状态变化时触发 |
103
+ | `sei-info` | `objects: unknown[]` | SEI 信息触发 |
104
+
105
+ ---
106
+
107
+ ## Expose 方法
108
+
109
+ 通过 `ref` 调用组件暴露的方法:
110
+
111
+ | 方法名 | 参数 | 返回值 | 说明 |
112
+ |--------|------|--------|------|
113
+ | `openVideo` | `video: { url: string; token?: string }` | `Promise<void>` | 打开并播放视频 |
114
+ | `closeVideo` | - | `Promise<void>` | 关闭视频 |
115
+ | `captureVideo` | - | `void` | 截图当前画面 |
116
+ | `changeQuality` | `quality: VideoQuality` | `void` | 切换清晰度 |
117
+
118
+ ### 方法示例
119
+
120
+ ```ts
121
+ // 打开视频
122
+ await videoPlayerRef.value?.openVideo({
123
+ url: 'ws://example.com/stream',
124
+ token: 'your-token' // 可选
125
+ })
126
+
127
+ // 关闭视频
128
+ await videoPlayerRef.value?.closeVideo()
129
+
130
+ // 截图
131
+ videoPlayerRef.value?.captureVideo()
132
+
133
+ // 切换清晰度 (0: 高清, 1: 标清, 2: 流畅)
134
+ videoPlayerRef.value?.changeQuality(1)
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Types 类型定义
140
+
141
+ ### VideoQuality 视频清晰度
142
+
143
+ ```ts
144
+ type VideoQuality = 0 | 1 | 2
145
+ // 0: 高清
146
+ // 1: 标清
147
+ // 2: 流畅
148
+ ```
149
+
150
+ ### PTZDirection 云台方向
151
+
152
+ ```ts
153
+ type PTZDirection =
154
+ | 'tilt_up' // 上
155
+ | 'up_right' // 右上
156
+ | 'pan_right' // 右
157
+ | 'down_right' // 右下
158
+ | 'tilt_down' // 下
159
+ | 'down_left' // 左下
160
+ | 'pan_left' // 左
161
+ | 'up_left' // 左上
162
+ ```
163
+
164
+ ### PTZZoomCommand 云台变倍指令
165
+
166
+ ```ts
167
+ type PTZZoomCommand =
168
+ | 'zoom_in' // 放大
169
+ | 'zoom_out' // 缩小
170
+ | 'focus_in' // 聚焦近
171
+ | 'focus_out' // 聚焦远
172
+ | 'iris_up' // 光圈增大
173
+ | 'iris_down' // 光圈减小
174
+ ```
175
+
176
+ ### VideoStatus 视频状态
177
+
178
+ ```ts
179
+ const VideoStatus = {
180
+ vConnect: 0, // 开始连接
181
+ vStart: 1, // 开始播放
182
+ vPlay: 2, // 正在播放
183
+ vPause: 3, // 暂停
184
+ vStop: 4 // 停止
185
+ }
186
+ ```
187
+
188
+ ---
189
+
190
+ ## 完整示例
191
+
192
+ ```vue
193
+ <template>
194
+ <div class="app-container">
195
+ <button @click="openVideo">播放</button>
196
+ <button @click="changeQuality(0)">高清</button>
197
+ <button @click="changeQuality(1)">标清</button>
198
+ <button @click="changeQuality(2)">流畅</button>
199
+
200
+ <div class="player-wrapper">
201
+ <WwVideoPlayer
202
+ ref="videoPlayerRef"
203
+ :options="options"
204
+ :is-live="true"
205
+ :show-p-t-z="true"
206
+ :show-controller="true"
207
+ @stop-video="onStopVideo"
208
+ @quality-change="onQualityChange"
209
+ @move-to-direction="onMoveToDirection"
210
+ @do-zoom="onDoZoom"
211
+ />
212
+ </div>
213
+ </div>
214
+ </template>
215
+
216
+ <script setup lang="ts">
217
+ import { ref } from 'vue'
218
+ import { WwVideoPlayer } from 'ww-video-player'
219
+ import type { VideoQuality, PTZDirection, PTZZoomCommand } from 'ww-video-player'
220
+
221
+ interface VideoPlayerExpose {
222
+ openVideo: (video: { url: string; token?: string }) => Promise<void>
223
+ closeVideo: () => Promise<void>
224
+ captureVideo: () => void
225
+ changeQuality: (quality: VideoQuality) => void
226
+ }
227
+
228
+ const videoPlayerRef = ref<VideoPlayerExpose | null>(null)
229
+
230
+ const options = {
231
+ debug: false,
232
+ mode: 'video' as const,
233
+ baseLibPath: '/js/h265/',
234
+ }
235
+
236
+ // 播放视频
237
+ const openVideo = async () => {
238
+ await videoPlayerRef.value?.openVideo({
239
+ url: 'ws://example.com/stream'
240
+ })
241
+ }
242
+
243
+ // 切换清晰度
244
+ const changeQuality = (quality: VideoQuality) => {
245
+ videoPlayerRef.value?.changeQuality(quality)
246
+ }
247
+
248
+ // 事件处理
249
+ const onStopVideo = () => console.log('视频已停止')
250
+ const onQualityChange = (q: VideoQuality) => console.log('清晰度:', q)
251
+ const onMoveToDirection = (d: PTZDirection) => console.log('云台方向:', d)
252
+ const onDoZoom = (c: PTZZoomCommand) => console.log('变倍:', c)
253
+ </script>
254
+
255
+ <style>
256
+ .player-wrapper {
257
+ width: 600px;
258
+ height: 400px;
259
+ }
260
+ </style>
261
+ ```
package/dist/README.md ADDED
@@ -0,0 +1,261 @@
1
+ # WwVideoPlayer 视频播放器组件
2
+
3
+ 一个基于 Vue 3 的视频播放器组件,支持 H.264/H.265 视频播放、云台控制和实时流播放。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install ww-video-player
9
+ ```
10
+
11
+ ## 基础用法
12
+
13
+ ```vue
14
+ <template>
15
+ <WwVideoPlayer
16
+ ref="videoPlayerRef"
17
+ :options="options"
18
+ :is-live="true"
19
+ :debug="false"
20
+ :show-p-t-z="true"
21
+ :show-controller="true"
22
+ @stop-video="onStopVideo"
23
+ @quality-change="onQualityChange"
24
+ />
25
+ </template>
26
+
27
+ <script setup lang="ts">
28
+ import { ref } from 'vue'
29
+ import { WwVideoPlayer } from 'ww-video-player'
30
+ import type { VideoQuality } from 'ww-video-player'
31
+
32
+ const videoPlayerRef = ref<InstanceType<typeof WwVideoPlayer> | null>(null)
33
+
34
+ const options = {
35
+ debug: false,
36
+ mode: 'video',
37
+ baseLibPath: '/js/h265/',
38
+ }
39
+
40
+ // 播放视频
41
+ const play = async () => {
42
+ await videoPlayerRef.value?.openVideo({
43
+ url: 'ws://example.com/video',
44
+ token: 'optional-token'
45
+ })
46
+ }
47
+
48
+ // 关闭视频
49
+ const close = async () => {
50
+ await videoPlayerRef.value?.closeVideo()
51
+ }
52
+ </script>
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Props 属性
58
+
59
+ | 属性名 | 类型 | 默认值 | 说明 |
60
+ |--------|------|--------|------|
61
+ | `debug` | `boolean` | `false` | 是否开启调试模式 |
62
+ | `isLive` | `boolean` | `true` | 是否为直播模式 |
63
+ | `options` | `PlayerOptions` | 见下方 | 播放器配置选项 |
64
+ | `showPTZ` | `boolean` | `false` | 是否显示云台控制 |
65
+ | `showController` | `boolean` | `false` | 是否显示播放控制器 |
66
+
67
+ ### PlayerOptions 配置
68
+
69
+ ```ts
70
+ interface PlayerOptions {
71
+ debug: boolean // 是否调试模式
72
+ mode: 'video' | 'audio' // 播放模式
73
+ baseLibPath: string // 解码器库文件路径
74
+ decoderLogLevel?: number // 解码器日志级别
75
+ }
76
+ ```
77
+
78
+ 默认值:
79
+ ```ts
80
+ {
81
+ debug: false,
82
+ mode: 'video',
83
+ baseLibPath: '/lib/',
84
+ decoderLogLevel: 0
85
+ }
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Events 事件
91
+
92
+ | 事件名 | 参数 | 说明 |
93
+ |--------|------|------|
94
+ | `stop-video` | - | 视频停止时触发 |
95
+ | `quality-change` | `quality: VideoQuality` | 清晰度变化时触发 |
96
+ | `change-play-speed` | `speed: number` | 播放速度变化时触发 |
97
+ | `control-talk` | `status: boolean` | 对讲状态变化时触发 |
98
+ | `lock-ptz` | `status: boolean` | 云台锁定状态变化时触发 |
99
+ | `do-zoom` | `command: PTZZoomCommand` | 云台变倍指令触发 |
100
+ | `move-to-direction` | `direction: PTZDirection` | 云台方向移动指令触发 |
101
+ | `error` | `error: Error, detail?, info?` | 发生错误时触发 |
102
+ | `video-status-change` | `status: number` | 视频状态变化时触发 |
103
+ | `sei-info` | `objects: unknown[]` | SEI 信息触发 |
104
+
105
+ ---
106
+
107
+ ## Expose 方法
108
+
109
+ 通过 `ref` 调用组件暴露的方法:
110
+
111
+ | 方法名 | 参数 | 返回值 | 说明 |
112
+ |--------|------|--------|------|
113
+ | `openVideo` | `video: { url: string; token?: string }` | `Promise<void>` | 打开并播放视频 |
114
+ | `closeVideo` | - | `Promise<void>` | 关闭视频 |
115
+ | `captureVideo` | - | `void` | 截图当前画面 |
116
+ | `changeQuality` | `quality: VideoQuality` | `void` | 切换清晰度 |
117
+
118
+ ### 方法示例
119
+
120
+ ```ts
121
+ // 打开视频
122
+ await videoPlayerRef.value?.openVideo({
123
+ url: 'ws://example.com/stream',
124
+ token: 'your-token' // 可选
125
+ })
126
+
127
+ // 关闭视频
128
+ await videoPlayerRef.value?.closeVideo()
129
+
130
+ // 截图
131
+ videoPlayerRef.value?.captureVideo()
132
+
133
+ // 切换清晰度 (0: 高清, 1: 标清, 2: 流畅)
134
+ videoPlayerRef.value?.changeQuality(1)
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Types 类型定义
140
+
141
+ ### VideoQuality 视频清晰度
142
+
143
+ ```ts
144
+ type VideoQuality = 0 | 1 | 2
145
+ // 0: 高清
146
+ // 1: 标清
147
+ // 2: 流畅
148
+ ```
149
+
150
+ ### PTZDirection 云台方向
151
+
152
+ ```ts
153
+ type PTZDirection =
154
+ | 'tilt_up' // 上
155
+ | 'up_right' // 右上
156
+ | 'pan_right' // 右
157
+ | 'down_right' // 右下
158
+ | 'tilt_down' // 下
159
+ | 'down_left' // 左下
160
+ | 'pan_left' // 左
161
+ | 'up_left' // 左上
162
+ ```
163
+
164
+ ### PTZZoomCommand 云台变倍指令
165
+
166
+ ```ts
167
+ type PTZZoomCommand =
168
+ | 'zoom_in' // 放大
169
+ | 'zoom_out' // 缩小
170
+ | 'focus_in' // 聚焦近
171
+ | 'focus_out' // 聚焦远
172
+ | 'iris_up' // 光圈增大
173
+ | 'iris_down' // 光圈减小
174
+ ```
175
+
176
+ ### VideoStatus 视频状态
177
+
178
+ ```ts
179
+ const VideoStatus = {
180
+ vConnect: 0, // 开始连接
181
+ vStart: 1, // 开始播放
182
+ vPlay: 2, // 正在播放
183
+ vPause: 3, // 暂停
184
+ vStop: 4 // 停止
185
+ }
186
+ ```
187
+
188
+ ---
189
+
190
+ ## 完整示例
191
+
192
+ ```vue
193
+ <template>
194
+ <div class="app-container">
195
+ <button @click="openVideo">播放</button>
196
+ <button @click="changeQuality(0)">高清</button>
197
+ <button @click="changeQuality(1)">标清</button>
198
+ <button @click="changeQuality(2)">流畅</button>
199
+
200
+ <div class="player-wrapper">
201
+ <WwVideoPlayer
202
+ ref="videoPlayerRef"
203
+ :options="options"
204
+ :is-live="true"
205
+ :show-p-t-z="true"
206
+ :show-controller="true"
207
+ @stop-video="onStopVideo"
208
+ @quality-change="onQualityChange"
209
+ @move-to-direction="onMoveToDirection"
210
+ @do-zoom="onDoZoom"
211
+ />
212
+ </div>
213
+ </div>
214
+ </template>
215
+
216
+ <script setup lang="ts">
217
+ import { ref } from 'vue'
218
+ import { WwVideoPlayer } from 'ww-video-player'
219
+ import type { VideoQuality, PTZDirection, PTZZoomCommand } from 'ww-video-player'
220
+
221
+ interface VideoPlayerExpose {
222
+ openVideo: (video: { url: string; token?: string }) => Promise<void>
223
+ closeVideo: () => Promise<void>
224
+ captureVideo: () => void
225
+ changeQuality: (quality: VideoQuality) => void
226
+ }
227
+
228
+ const videoPlayerRef = ref<VideoPlayerExpose | null>(null)
229
+
230
+ const options = {
231
+ debug: false,
232
+ mode: 'video' as const,
233
+ baseLibPath: '/js/h265/',
234
+ }
235
+
236
+ // 播放视频
237
+ const openVideo = async () => {
238
+ await videoPlayerRef.value?.openVideo({
239
+ url: 'ws://example.com/stream'
240
+ })
241
+ }
242
+
243
+ // 切换清晰度
244
+ const changeQuality = (quality: VideoQuality) => {
245
+ videoPlayerRef.value?.changeQuality(quality)
246
+ }
247
+
248
+ // 事件处理
249
+ const onStopVideo = () => console.log('视频已停止')
250
+ const onQualityChange = (q: VideoQuality) => console.log('清晰度:', q)
251
+ const onMoveToDirection = (d: PTZDirection) => console.log('云台方向:', d)
252
+ const onDoZoom = (c: PTZZoomCommand) => console.log('变倍:', c)
253
+ </script>
254
+
255
+ <style>
256
+ .player-wrapper {
257
+ width: 600px;
258
+ height: 400px;
259
+ }
260
+ </style>
261
+ ```
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@vanwei-wcs/video-player-v3",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "video-player-v3.umd.cjs",
6
+ "module": "video-player-v3.js",
7
+ "types": "types/index.d.ts",
8
+ "style": "style.css",
9
+ "sideEffects": [
10
+ "**/*.css"
11
+ ],
12
+ "exports": {
13
+ ".": {
14
+ "import": "./video-player-v3.js",
15
+ "require": "./video-player-v3.umd.cjs",
16
+ "types": "./types/index.d.ts"
17
+ },
18
+ "./style.css": "./style.css"
19
+ }
20
+ }
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ .styled-checkbox[data-v-d478ce3d]{vertical-align:top;cursor:pointer;height:100%}.wwav-player__ptz-message[data-v-97aecee1]{z-index:100;border-radius:4px;padding:8px 16px;font-size:14px;position:absolute;top:10px;left:50%;transform:translate(-50%)}.wwav-player__ptz-message.success[data-v-97aecee1]{color:#fff;background:#67c23a}.wwav-player__ptz-message.error[data-v-97aecee1]{color:#fff;background:#f56c6c}.wwav-player__ptz-message.info[data-v-97aecee1]{color:#fff;background:#909399}.fade-enter-active[data-v-97aecee1],.fade-leave-active[data-v-97aecee1]{transition:opacity .3s}.fade-enter-from[data-v-97aecee1],.fade-leave-to[data-v-97aecee1]{opacity:0}.wwav-player__ptz__direction{opacity:.55;box-sizing:border-box;z-index:1;background:radial-gradient(circle,#0000 0 0,#000 100%);border:2px solid #fff;border-radius:50%;width:144px;height:144px;position:absolute;bottom:3.5em;left:1em;overflow:hidden}.wwav-player__ptz__direction-content{background:0 0;width:95px;height:95px}.wwav-player__ptz__direction-circle-border{border:1px solid #ffffff1a;border-radius:50%;width:80px;height:80px}.wwav-player__ptz__direction-circle{background:#fff6;border:1px solid #ffffff4d;border-radius:50%;width:48px;height:48px}.wwav-player__ptz__direction-triangle{transform-origin:50%;cursor:pointer;opacity:.7;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAwElEQVQ4T5XSTUqCURSA4edOgowoTaIlCBUEDgIHQSC6DxfXAkKl6G8RbaFxKyiufHEUNX/ud0dncN/nTE6CnPMThtVc8H4wwSjlnJv4LojWv0xSbP7EVU3gdx538IGLOsBfHNsv8Y7zUmARB3AdQLsEWIkDuMEbWvuAf3EAXbzidBewMQ7gFs842QZsjQPooTqg403AzjiAO0xxtA7sjQO4xxiNZaAoDqCPRxzOgeI4gAEecIaXWnEAB9UVppS+Zn2ZQFj4MpGPAAAAAElFTkSuQmCC);width:15px;height:15px;position:absolute}.wwav-player__ptz__direction-triangle.active,.wwav-player__ptz__direction-triangle:hover{opacity:1}.wwav-player__ptz__direction-triangle:first-child{top:-10px;left:50%;transform:translate(-50%)rotate(-45deg)}.wwav-player__ptz__direction-triangle:nth-child(3){top:50%;right:-10px;transform:translateY(-50%)rotate(45deg)}.wwav-player__ptz__direction-triangle:nth-child(5){bottom:-10px;left:50%;transform:translate(-50%)rotate(135deg)}.wwav-player__ptz__direction-triangle:nth-child(7){top:50%;left:-10px;transform:translateY(-50%)rotate(225deg)}.wwav-player__ptz__direction-triangle:nth-child(2){top:6px;right:6px}.wwav-player__ptz__direction-triangle:nth-child(4){bottom:6px;right:6px;transform:rotate(90deg)}.wwav-player__ptz__direction-triangle:nth-child(6){bottom:6px;left:6px;transform:rotate(180deg)}.wwav-player__ptz__direction-triangle:nth-child(8){top:6px;left:6px;transform:rotate(270deg)}.wwav-player__ptz__operation{text-align:center;-webkit-user-select:none;user-select:none;z-index:1;padding:1em;position:absolute;bottom:3em;left:50%;transform:translate(-50%)}.wwav-player__ptz__operation-button{vertical-align:top;box-sizing:border-box;cursor:pointer;background-color:#0000004d;border:1px solid #0000;border-radius:50%;width:48px;height:48px;margin:0 15px;padding:0;display:inline-block;position:relative}.wwav-player__ptz__operation-button:focus,.wwav-player__ptz__operation-button:hover{border-color:#fffc}.wwav-player__ptz__operation-button img{width:100%;height:100%}.wwav-player__ptz__operation-button .image{box-sizing:border-box;width:100%;height:100%;padding:8px}.wwav-player__ptz__operation-button-disable{color:#333;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE8AAAAlCAYAAAADW7S6AAABkElEQVRoQ+3ar0ssURjG8e8DBhE0mk1aTCLY/AuUq8liFYwigota7w/hcrnNYhWMgv4DmgXBYjBazIprklfOsrtMWFD3LQd8JuzCcJ5h+MwzZ8I5ontExBKwDSwAY73z/u8LPAPXwD9JF+Wsyk9E/AT2DPVpgV+S9hURP4CzT8c8sCewUvAugUWbfFngquC9eI77MlwJtAteDBV1COMlSmA84yUEElE3z3gJgUTUzTNeQiARdfOMlxBIRN084yUEElE3z3gJgUTUzTNeQiARdfOMlxBIRN084yUEEtHSvCdgPHGN7xrtLAB56XG4x99ZevSi93B4q73tFr+B1nDX+JapQ0mtDl45ImIZ2AHmvQg+sBDt7kafv5LOy4g+Xg39iYhZ4AYYGXA/b8CcpNsa7rU6vO4bcARsDgA6lrRRC1yteJPAPTDRgCp746YlPRrvA4GI2AX+NIYdSCp7CKs6qprzGh+vUeAOmAIegBlJr1XJ1fbBaOJExBpwCqxLOqkNrso5r9G+8lb8B7YkVbkN7h0eRanPahw2mAAAAABJRU5ErkJggg==) no-repeat;width:80px;height:40px;font-family:PingFang SC;font-size:16px;font-weight:400;line-height:31px;transition:display .5s ease-in;display:none;position:absolute;top:-40px;left:-17px}.wwav-player__ptz__operation-button.isLocked{background-color:#67c23a80;border-color:#67c23a}.wwav-player__ptz__operation-button.isLocked:focus,.wwav-player__ptz__operation-button.isLocked:hover{border-color:#67c23a}.wwav-player__ptz__operation-popper{color:#ddd;width:40px;cursor:unset;text-align:center;background-color:#000000b3;border-radius:5px;display:none;position:absolute;top:-124px;left:50%;transform:translate(-50%)}.wwav-player__ptz__operation-popper-show{display:block}.wwav-player__ptz__operation-popper-icon{box-sizing:border-box;color:#bbb;cursor:pointer;width:40px;height:40px;padding:8px;line-height:40px}.wwav-player__ptz__operation-popper-icon:focus,.wwav-player__ptz__operation-popper-icon:hover{color:#fff;background-color:#000c;border-radius:5px}.wwav-player__ptz__operation-popper-icon svg{fill:currentColor;vertical-align:middle;width:16px;height:16px}.wwav-player__ptz__operation-popper span{color:#ddd;height:40px;font-size:12px;line-height:40px;display:block}.wwav-player__ptz__message{text-align:center;color:#fff;background-color:#3339;border:1px solid;border-radius:5px;width:400px;padding:10px;line-height:18px;position:absolute;bottom:120px;left:50%;transform:translate(-50%)}.wwav-player__ptz__message.error{color:#f56c6c;border-color:#fde2e2}.wwav-player__ptz__message.success{color:#67c23a;border-color:#e1f3d8}.wwav-player-rotate{animation:1.5s linear infinite wwav-player-rotating}@keyframes wwav-player-rotating{0%{transform:rotate(0)}to{transform:rotate(-1turn)}}.wwav-player__common-icon,.wwav-player__common-span{color:#afb9bc;text-align:center;cursor:pointer;z-index:2;height:100%;margin:0 .5em;line-height:2.55em;transition:all .1s;display:inline-block}.wwav-player__common-icon:hover,.wwav-player__common-span:hover{color:#fff}.wwav-player__common-icon.hidden,.wwav-player__common-span.hidden{opacity:0;z-index:1}.wwav-player__common-icon{text-shadow:1px 1px 1px #000c;width:1.5em;margin:0 .3em}.wwav-player__common-icon.active{color:#67c23a}.wwav-player__svg-icon{fill:currentColor;width:13px;height:13px}.wwav-player__content{width:100%;height:100%}.wwav-player__header{z-index:9;-webkit-user-select:none;user-select:none;background:linear-gradient(#343b4acc 0,#16181dcc);width:100%;height:2.2em;padding-bottom:1px;transition:bottom .3s ease-out;position:absolute;top:-2.2em;left:0}.wwav-player__header--device-name{vertical-align:top;width:auto;margin:0 0 0 1em;line-height:2.3em;position:relative}.wwav-player__footer{z-index:10;-webkit-user-select:none;user-select:none;background:linear-gradient(#343b4acc 0,#16181dcc);width:100%;height:2.2em;padding-bottom:1px;transition:bottom .3s ease-out;position:absolute;bottom:-2.2em;left:0}.wwav-player__footer__pop{opacity:0;background:#2d3443;border:1px solid #404f6f;border-radius:3px;width:auto;margin:0;padding:6px 0;transition:opacity .5s;position:absolute;bottom:-99em}.wwav-player__footer__pop.show{opacity:1;bottom:2.4em}.wwav-player__footer--stop{width:2.2em;margin:0;position:relative;top:0;left:0}.wwav-player__footer--stop:after{content:"";background-color:#fff3;width:1px;height:66%;position:absolute;inset:17% 0 auto auto}.wwav-player__footer--fullscreen{width:2.2em;margin:0;position:absolute;top:0;right:0}.wwav-player__footer--fullscreen:after{content:"";background-color:#fff3;width:1px;height:66%;position:absolute;inset:17% auto auto 0}.wwav-player__footer--left{width:auto;height:100%;position:absolute;top:0;left:2.7em}.wwav-player__footer--play{vertical-align:top;margin:0}.wwav-player__footer--speed{vertical-align:top;width:2em;margin:0;line-height:2.3em;position:relative}.wwav-player__footer--speed>div{width:100%;height:100%;position:relative;top:0;left:0}.wwav-player__footer--speed-pop{width:7em;font-size:12px;left:-2em}.wwav-player__footer--speed-pop--item{white-space:nowrap;text-overflow:ellipsis;color:#8191a9;box-sizing:border-box;cursor:pointer;text-align:center;background:#2d3443;height:2em;padding:0 10px;line-height:2.2em;position:relative;overflow:hidden}.wwav-player__footer--speed-pop--item i{width:1.2em;margin:0;position:absolute}.wwav-player__footer--speed-pop--item i:first-child{left:.5em}.wwav-player__footer--speed-pop--item i:last-child{right:.5em}.wwav-player__footer--ai,.wwav-player__footer--capture,.wwav-player__footer--ptz{vertical-align:top}.wwav-player__footer--right{width:auto;height:100%;position:absolute;top:0;right:2.7em}.wwav-player__footer--net-speed{cursor:auto;vertical-align:top;width:4.5em;margin:0;line-height:2.3em;overflow:hidden}.wwav-player__footer--net-speed:hover{color:#afb9bc}.wwav-player__footer--net-speed span{font-size:.8em}.wwav-player__footer--info{vertical-align:top;position:relative}.wwav-player__footer--info-pop{width:11em;font-size:12px;left:-5.5em}.wwav-player__footer--info-pop--item{white-space:nowrap;text-overflow:ellipsis;color:#8191a9;box-sizing:border-box;cursor:pointer;text-align:left;background:#2d3443;height:2em;padding:0 10px;line-height:2em;overflow:hidden}.wwav-player__footer--quality{vertical-align:top;width:auto;margin:0;line-height:2.4em;position:relative}.wwav-player__footer--quality-select{width:4em;left:-1em}.wwav-player__footer--quality-select--item{white-space:nowrap;text-overflow:ellipsis;color:#8191a9;box-sizing:border-box;cursor:pointer;text-align:center;background:#2d3443;height:2em;padding:0 10px;line-height:2em;overflow:hidden}.wwav-player__footer--quality-select--item:hover{color:#4b99e7}.wwav-player__footer--quality-select--item.active{color:#409eff}.wwav-player__footer--setting-pop{cursor:default;width:11em;font-size:12px;left:-4em}.wwav-player__footer--setting-pop--item{white-space:nowrap;text-overflow:ellipsis;color:#8191a9;box-sizing:border-box;text-align:left;background:#2d3443;height:2em;padding:0 10px;line-height:2em;overflow:hidden}.wwav-player__name{color:#afb9bc;z-index:9;-webkit-user-select:none;user-select:none;background:linear-gradient(#343b4acc 0,#16181dcc);justify-content:space-between;align-items:center;width:100%;height:2.2em;padding:0 .5em;transition:top .3s ease-out;display:flex;position:absolute;top:-2.2em;left:0}.wwav-player__name span{z-index:10}.wwav-player__watermark{z-index:8;width:100%;height:100%;position:absolute}.wwav-player__watermark span{color:#fff;font-size:16px;font-weight:600}.wwav-player.active .wwav-player__header,.wwav-player:hover .wwav-player__header,.wwav-player:hover .wwav-player__name{transition:top 50ms ease-out;top:0}.wwav-player.active .wwav-player__footer,.wwav-player:hover .wwav-player__footer{transition:top 50ms ease-out;bottom:0}.wwav-player-center-middle{position:absolute;top:50%;left:50%;transform:translate(-50%)translateY(-50%)}.wwav-player__el-input{min-width:0;height:28px;font-size:12px;line-height:28px;display:inline-block;position:relative}.wwav-player__el-input__inner{-webkit-appearance:none;box-sizing:border-box;color:#eee;font-size:inherit;caret-color:#05d380;background-color:#aaaaaa80;background-image:none;border:none;border-radius:4px;outline:none;width:100%;height:28px;padding:0 10px;font-family:PingFang SC;font-weight:400;line-height:28px;display:inline-block}.wwav-player__el-input__inner::-webkit-input-placeholder{color:#bbb;font-size:14px}.wwav-player__ptz{z-index:9;box-sizing:border-box;background-color:#0000;border:none;width:100%;height:100%;margin:0;padding:0;font-size:16px;display:inline-block;position:absolute;top:0;left:0}.wwav-player__ptz-status-label{color:#fff;background-color:#0006;border:none;border-radius:3px;width:auto;padding:10px 19px;font-family:PingFang SC;font-size:27px;font-weight:400;position:absolute;top:1.8em;left:1em}.wcs-wwav-base-video__content{cursor:pointer;object-fit:fill;width:100%!important;height:100%!important}.wcs-wwav-base-video{width:100%;height:100%;position:relative}.wcs-wwav-base-video .wcs-wwav-base-video__content{cursor:pointer;object-fit:fill;width:100%!important;height:100%!important}.wcs-wwav-base-video canvas{cursor:pointer;object-fit:fill;width:100%;height:100%;display:none}.base-content{width:300px;height:300px;position:relative}.wcs-wwav-base-video__content[data-v-c3dbeeea]{cursor:pointer;object-fit:fill;width:100%!important;height:100%!important}.wcs-wwav-base-video[data-v-c3dbeeea]{width:100%;height:100%;position:relative}.wcs-wwav-base-video .wcs-wwav-base-video__content[data-v-c3dbeeea]{cursor:pointer;object-fit:fill;width:100%!important;height:100%!important}.wcs-wwav-base-video canvas[data-v-c3dbeeea]{cursor:pointer;object-fit:fill;width:100%;height:100%;display:none}.base-content[data-v-c3dbeeea]{width:100%;height:100%;position:relative;overflow:hidden}