virtual-human-cf 1.2.0 → 1.4.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 +125 -65
- package/dist/api/request.d.ts +2 -0
- package/dist/api/screen.d.ts +13 -0
- package/dist/components/VirtualHumanEventAdapter.vue.d.ts +7 -3
- package/dist/style.css +1 -1
- package/dist/virtual-human-cf.es.js +2075 -133
- package/dist/virtual-human-cf.umd.js +6 -1
- package/package.json +6 -2
- package/src/api/request.ts +22 -0
- package/src/api/screen.ts +36 -0
- package/src/components/VirtualHumanEventAdapter.vue +109 -7
- package/src/components/VirtualHumanPersona.vue +3 -0
- package/tsconfig.json +6 -2
- package/vite.config.ts +6 -1
package/README.md
CHANGED
|
@@ -12,26 +12,52 @@
|
|
|
12
12
|
- 响应式设计
|
|
13
13
|
|
|
14
14
|
## 更新日志
|
|
15
|
-
### 1.2.0
|
|
16
|
-
- 新增VirtualHumanEventAdapter组件controlEvent事件,用于数字人播放周期控制指令通知
|
|
17
|
-
```javascript
|
|
18
|
-
<VirtualHumanEventAdapter
|
|
19
|
-
v-if="activeScreenClientId"
|
|
20
|
-
@controlEvent="onControlEvent"
|
|
21
|
-
/>
|
|
22
|
-
const onControlEvent = (event) => {
|
|
23
|
-
console.log(event);
|
|
24
|
-
// play 初次开始播放
|
|
25
|
-
// resume 恢复播放
|
|
26
|
-
// pause 暂停播放
|
|
27
|
-
// stop 停止播放
|
|
28
|
-
// tts_complete 文本转语音完成,不代表本地播放完成
|
|
29
|
-
}
|
|
30
|
-
```
|
|
31
15
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
16
|
+
### 1.4.0
|
|
17
|
+
|
|
18
|
+
- 新增VirtualHumanEventAdapter组件对外暴露pause、resume、stop方法
|
|
19
|
+
|
|
20
|
+
```javascript
|
|
21
|
+
<VirtualHumanEventAdapter
|
|
22
|
+
v-if="activeScreenClientId"
|
|
23
|
+
@controlEvent="onControlEvent"
|
|
24
|
+
ref="adapterRef"
|
|
25
|
+
/>
|
|
26
|
+
const adapterRef = ref(null);
|
|
27
|
+
|
|
28
|
+
// 底部有使用demo,这里不重复
|
|
29
|
+
// 暂停播放
|
|
30
|
+
adapterRef.value.pause().then(() => {}).catch(() => {});
|
|
31
|
+
// 恢复播放
|
|
32
|
+
adapterRef.value.resume().then(() => {}).catch(() => {});
|
|
33
|
+
// 停止播放
|
|
34
|
+
adapterRef.value.stop().then(() => {}).catch(() => {});
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 1.2.0
|
|
39
|
+
|
|
40
|
+
- 新增VirtualHumanEventAdapter组件controlEvent事件,用于数字人播放周期控制指令通知
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
<VirtualHumanEventAdapter
|
|
44
|
+
v-if="activeScreenClientId"
|
|
45
|
+
@controlEvent="onControlEvent"
|
|
46
|
+
/>
|
|
47
|
+
const onControlEvent = (event) => {
|
|
48
|
+
console.log(event);
|
|
49
|
+
// play 初次开始播放
|
|
50
|
+
// resume 恢复播放
|
|
51
|
+
// pause 暂停播放
|
|
52
|
+
// stop 停止播放
|
|
53
|
+
// tts_complete 文本转语音完成,不代表本地播放完成
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 1.0.10
|
|
58
|
+
|
|
59
|
+
- 新增VirtualHumanPersona组件styles属性,用于控制视频容器 宽高 绝对定位位置等
|
|
60
|
+
|
|
35
61
|
## 安装
|
|
36
62
|
|
|
37
63
|
```bash
|
|
@@ -43,9 +69,9 @@ npm install virtual-human-cf
|
|
|
43
69
|
### 全局注册
|
|
44
70
|
|
|
45
71
|
```javascript
|
|
46
|
-
import { createApp } from
|
|
47
|
-
import App from
|
|
48
|
-
import VirtualHumanCF from
|
|
72
|
+
import { createApp } from "vue";
|
|
73
|
+
import App from "./App.vue";
|
|
74
|
+
import VirtualHumanCF from "virtual-human-cf";
|
|
49
75
|
|
|
50
76
|
const app = createApp(App);
|
|
51
77
|
app.use(VirtualHumanCF);
|
|
@@ -54,7 +80,10 @@ app.use(VirtualHumanCF);
|
|
|
54
80
|
### 按需导入
|
|
55
81
|
|
|
56
82
|
```javascript
|
|
57
|
-
import {
|
|
83
|
+
import {
|
|
84
|
+
VirtualHumanPersona,
|
|
85
|
+
VirtualHumanEventAdapter,
|
|
86
|
+
} from "virtual-human-cf";
|
|
58
87
|
```
|
|
59
88
|
|
|
60
89
|
## 组件说明
|
|
@@ -65,24 +94,24 @@ import { VirtualHumanPersona, VirtualHumanEventAdapter } from 'virtual-human-cf'
|
|
|
65
94
|
|
|
66
95
|
#### Props
|
|
67
96
|
|
|
68
|
-
| 属性
|
|
69
|
-
|
|
70
|
-
| videoSrc
|
|
71
|
-
| visible
|
|
72
|
-
| isPlaying
|
|
73
|
-
| muted
|
|
74
|
-
| isDark
|
|
75
|
-
| screenClientId | String
|
|
76
|
-
| wsUrl
|
|
77
|
-
| styles
|
|
97
|
+
| 属性 | 类型 | 默认值 | 必填 | 说明 |
|
|
98
|
+
| -------------- | ------- | ------ | ---- | ------------------------------------------------- |
|
|
99
|
+
| videoSrc | String | - | 是 | 视频源 URL |
|
|
100
|
+
| visible | Boolean | true | 否 | 是否可见 |
|
|
101
|
+
| isPlaying | Boolean | false | 否 | 是否正在播放 |
|
|
102
|
+
| muted | Boolean | true | 否 | 是否静音 |
|
|
103
|
+
| isDark | Boolean | false | 否 | 是否暗黑模式 |
|
|
104
|
+
| screenClientId | String | - | 否 | 屏幕客户端 ID |
|
|
105
|
+
| wsUrl | String | - | 否 | WebSocket 连接地址 |
|
|
106
|
+
| styles | Object | - | 否 | 组件样式,包含 width、height、left、bottom 等属性 |
|
|
78
107
|
|
|
79
108
|
#### Events
|
|
80
109
|
|
|
81
|
-
| 事件名
|
|
82
|
-
|
|
110
|
+
| 事件名 | 说明 | 回调参数 |
|
|
111
|
+
| ---------------- | ------------ | ----------------- |
|
|
83
112
|
| update:isPlaying | 播放状态变更 | 播放状态(Boolean) |
|
|
84
|
-
| update:visible
|
|
85
|
-
| ended
|
|
113
|
+
| update:visible | 可见性变更 | 可见状态(Boolean) |
|
|
114
|
+
| ended | 播放结束 | - |
|
|
86
115
|
|
|
87
116
|
#### 示例
|
|
88
117
|
|
|
@@ -102,25 +131,25 @@ import { VirtualHumanPersona, VirtualHumanEventAdapter } from 'virtual-human-cf'
|
|
|
102
131
|
</template>
|
|
103
132
|
|
|
104
133
|
<script setup>
|
|
105
|
-
import { ref } from
|
|
106
|
-
import { VirtualHumanPersona } from
|
|
134
|
+
import { ref } from "vue";
|
|
135
|
+
import { VirtualHumanPersona } from "virtual-human-cf";
|
|
107
136
|
|
|
108
|
-
const videoUrl = ref(
|
|
137
|
+
const videoUrl = ref("https://example.com/video.mp4");
|
|
109
138
|
const playing = ref(false);
|
|
110
|
-
const clientId = ref(
|
|
111
|
-
const websocketUrl = ref(
|
|
139
|
+
const clientId = ref("screen-123");
|
|
140
|
+
const websocketUrl = ref("ws://localhost:8080/ws");
|
|
112
141
|
const styles = ref({
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
})
|
|
142
|
+
width: "400px",
|
|
143
|
+
height: "500px",
|
|
144
|
+
left: "16px",
|
|
145
|
+
bottom: "16px",
|
|
146
|
+
});
|
|
118
147
|
const onPlayingChange = (isPlaying) => {
|
|
119
|
-
console.log(
|
|
148
|
+
console.log("播放状态改变:", isPlaying);
|
|
120
149
|
};
|
|
121
150
|
|
|
122
151
|
const onEnded = () => {
|
|
123
|
-
console.log(
|
|
152
|
+
console.log("播放结束");
|
|
124
153
|
};
|
|
125
154
|
</script>
|
|
126
155
|
```
|
|
@@ -131,27 +160,35 @@ const onEnded = () => {
|
|
|
131
160
|
|
|
132
161
|
#### Props
|
|
133
162
|
|
|
134
|
-
| 属性
|
|
135
|
-
|
|
136
|
-
| screenClientId | String | -
|
|
137
|
-
| wsUrl
|
|
163
|
+
| 属性 | 类型 | 默认值 | 必填 | 说明 |
|
|
164
|
+
| -------------- | ------ | ------ | ---- | ------------------ |
|
|
165
|
+
| screenClientId | String | - | 是 | 屏幕客户端 ID |
|
|
166
|
+
| wsUrl | String | - | 是 | WebSocket 连接地址 |
|
|
138
167
|
|
|
139
168
|
#### Events
|
|
140
169
|
|
|
141
|
-
| 事件名
|
|
142
|
-
|
|
143
|
-
| connected
|
|
144
|
-
| eventNotifaction | 自定义事件接收器
|
|
145
|
-
| end
|
|
146
|
-
| pause
|
|
147
|
-
| error
|
|
148
|
-
| playComplete
|
|
149
|
-
| controlEvent
|
|
170
|
+
| 事件名 | 说明 | 回调参数 |
|
|
171
|
+
| ---------------- | ------------------------------------ | -------- |
|
|
172
|
+
| connected | WebSocket 连接成功 | - |
|
|
173
|
+
| eventNotifaction | 自定义事件接收器 | 载荷数据 |
|
|
174
|
+
| end | 数字人对话结束 | 载荷数据 |
|
|
175
|
+
| pause | 暂停播放 | 载荷数据 |
|
|
176
|
+
| error | 错误事件 | 错误信息 |
|
|
177
|
+
| playComplete | 播放完成,数字人对话结束,关闭数字人 | - |
|
|
178
|
+
| controlEvent | 数字人控制事件 | 载荷数据 |
|
|
179
|
+
|
|
180
|
+
#### refs
|
|
181
|
+
|
|
182
|
+
| 方法名 | 说明 | 回调参数 |
|
|
183
|
+
| ------ | -------- | -------- |
|
|
184
|
+
| pause | 暂停播放 |Promise<boolean> |
|
|
185
|
+
| resume | 恢复播放 |Promise<boolean> |
|
|
186
|
+
| stop | 停止播放 |Promise<boolean> |
|
|
150
187
|
|
|
151
188
|
```js
|
|
152
189
|
// eventNotifaction 载荷数据
|
|
153
190
|
{
|
|
154
|
-
|
|
191
|
+
|
|
155
192
|
"type": "send_event",
|
|
156
193
|
// 自定义事件名称
|
|
157
194
|
"event": "heightlight",
|
|
@@ -182,6 +219,7 @@ tts_complete 文本转语音完成,不代表本地播放完成
|
|
|
182
219
|
@controlEvent="onControlEvent"
|
|
183
220
|
@end="onEnd"
|
|
184
221
|
@error="onError"
|
|
222
|
+
ref="adapterRef"
|
|
185
223
|
>
|
|
186
224
|
<div>其他内容</div>
|
|
187
225
|
</VirtualHumanEventAdapter>
|
|
@@ -212,6 +250,28 @@ const onEnd = (payload) => {
|
|
|
212
250
|
const onError = (error) => {
|
|
213
251
|
console.error('错误:', error);
|
|
214
252
|
};
|
|
253
|
+
|
|
254
|
+
const adapterRef = ref(null);
|
|
255
|
+
const controlFunc = () => {
|
|
256
|
+
// 暂停播放
|
|
257
|
+
adapterRef.value.pause().then(res => {
|
|
258
|
+
// res boolean true 暂停成功 false 暂停失败
|
|
259
|
+
}).catch((error) => {
|
|
260
|
+
console.error('暂停播放失败:', error);
|
|
261
|
+
});
|
|
262
|
+
// 恢复播放
|
|
263
|
+
adapterRef.value.resume().then(res => {
|
|
264
|
+
// res boolean true 恢复成功 false 恢复失败
|
|
265
|
+
}).catch((error) => {
|
|
266
|
+
console.error('恢复播放失败:', error);
|
|
267
|
+
});
|
|
268
|
+
// 停止播放
|
|
269
|
+
adapterRef.value.stop().then(res => {
|
|
270
|
+
// res boolean true 停止成功 false 停止失败
|
|
271
|
+
}).catch((error) => {
|
|
272
|
+
console.error('停止播放失败:', error);
|
|
273
|
+
});
|
|
274
|
+
}
|
|
215
275
|
</script>
|
|
216
276
|
```
|
|
217
277
|
|
|
@@ -235,7 +295,7 @@ const onError = (error) => {
|
|
|
235
295
|
@update:visible="onPersonaVisibleUpdate"
|
|
236
296
|
@ended="onVideoEnded"
|
|
237
297
|
/>
|
|
238
|
-
|
|
298
|
+
|
|
239
299
|
<VirtualHumanEventAdapter
|
|
240
300
|
:screen-client-id="activeScreenClientId"
|
|
241
301
|
:ws-url="websocketUrl"
|
|
@@ -315,4 +375,4 @@ npm run build
|
|
|
315
375
|
|
|
316
376
|
## 许可证
|
|
317
377
|
|
|
318
|
-
MIT
|
|
378
|
+
MIT
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ScreenConfig {
|
|
2
|
+
id?: number;
|
|
3
|
+
name: string;
|
|
4
|
+
screenClientId: string;
|
|
5
|
+
createTime?: string;
|
|
6
|
+
updateTime?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const getScreenList: () => Promise<ScreenConfig[]>;
|
|
9
|
+
export declare const getScreenById: (id: number) => Promise<ScreenConfig>;
|
|
10
|
+
export declare const createScreen: (data: ScreenConfig) => Promise<boolean>;
|
|
11
|
+
export declare const updateScreen: (id: number, data: ScreenConfig) => Promise<boolean>;
|
|
12
|
+
export declare const deleteScreen: (id: number) => Promise<boolean>;
|
|
13
|
+
export declare const controlScreen: (screenClientId: string, action: "play" | "pause" | "stop" | "resume") => Promise<boolean>;
|
|
@@ -10,9 +10,13 @@ declare const __VLS_component: import('vue').DefineComponent<import('vue').Extra
|
|
|
10
10
|
type: StringConstructor;
|
|
11
11
|
required: true;
|
|
12
12
|
};
|
|
13
|
-
}>, {
|
|
14
|
-
|
|
13
|
+
}>, {
|
|
14
|
+
pause: () => Promise<boolean>;
|
|
15
|
+
resume: () => Promise<boolean>;
|
|
16
|
+
stop: () => Promise<boolean>;
|
|
17
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
15
18
|
pause: (...args: any[]) => void;
|
|
19
|
+
error: (...args: any[]) => void;
|
|
16
20
|
eventNotifaction: (...args: any[]) => void;
|
|
17
21
|
controlEvent: (...args: any[]) => void;
|
|
18
22
|
end: (...args: any[]) => void;
|
|
@@ -28,8 +32,8 @@ declare const __VLS_component: import('vue').DefineComponent<import('vue').Extra
|
|
|
28
32
|
required: true;
|
|
29
33
|
};
|
|
30
34
|
}>> & Readonly<{
|
|
31
|
-
onError?: ((...args: any[]) => any) | undefined;
|
|
32
35
|
onPause?: ((...args: any[]) => any) | undefined;
|
|
36
|
+
onError?: ((...args: any[]) => any) | undefined;
|
|
33
37
|
onEventNotifaction?: ((...args: any[]) => any) | undefined;
|
|
34
38
|
onControlEvent?: ((...args: any[]) => any) | undefined;
|
|
35
39
|
onEnd?: ((...args: any[]) => any) | undefined;
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.fade-enter-active[data-v-
|
|
1
|
+
.fade-enter-active[data-v-02ec3645],.fade-leave-active[data-v-02ec3645]{transition:opacity .5s ease,transform .5s ease}.fade-enter-from[data-v-02ec3645],.fade-leave-to[data-v-02ec3645]{opacity:0;transform:translateY(10px)}.virtual-human-container[data-v-02ec3645]{position:fixed;z-index:2147483647;overflow:visible}.video-wrapper[data-v-02ec3645]{position:relative;width:100%;height:100%;border-radius:1rem;overflow:hidden;box-shadow:0 10px 25px #0000001a;background:#fff;border:2px solid transparent;transition:background-color .3s ease,box-shadow .3s ease,border-color .3s ease}.video-wrapper[data-v-02ec3645]:hover{border-color:#409eff}.virtual-human-container.is-dark .video-wrapper[data-v-02ec3645]{background:#1f2937;box-shadow:0 10px 25px #00000080}.persona-video[data-v-02ec3645]{width:100%;height:100%;object-fit:cover;transform-origin:center;transition:transform .1s ease-out}.resize-handle[data-v-02ec3645]{position:absolute;width:20px;height:20px;background:#00000080;border:2px solid rgba(255,255,255,.8);border-radius:4px;cursor:pointer;z-index:20;opacity:0;pointer-events:none;transition:opacity .3s ease,background .2s,border-color .2s}.video-wrapper:hover .resize-handle[data-v-02ec3645]{opacity:1;pointer-events:auto}.resize-handle[data-v-02ec3645]:hover{background:#000000b3;border-color:#fff}.resize-handle.top-left[data-v-02ec3645]{top:10px;left:10px;cursor:nwse-resize}.resize-handle.top-right[data-v-02ec3645]{top:10px;right:10px;cursor:nesw-resize}.resize-handle.bottom-left[data-v-02ec3645]{bottom:10px;left:10px;cursor:nesw-resize}.resize-handle.bottom-right[data-v-02ec3645]{bottom:10px;right:10px;cursor:nwse-resize}.overlay[data-v-02ec3645]{position:absolute;top:1rem;right:1rem;z-index:10}.status-badge[data-v-02ec3645]{display:flex;align-items:center;gap:.5rem;padding:.25rem .75rem;border-radius:9999px;font-size:.75rem;font-weight:500;color:#fff;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.status-badge.paused[data-v-02ec3645]{background:#ef4444cc}.status-badge.playing[data-v-02ec3645]{background:#22c55ecc}.dot[data-v-02ec3645]{width:6px;height:6px;border-radius:50%;background-color:#fff}@keyframes pulse-02ec3645{0%,to{opacity:1}50%{opacity:.5}}.animate-pulse[data-v-02ec3645]{animation:pulse-02ec3645 2s cubic-bezier(.4,0,.6,1) infinite}
|