@scienjoy/sj-ai-plus 1.0.6 → 1.0.8
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/package.json +1 -1
- package/ui/es/packages/components/src/sjDigitalHumanAssistant/src/index.vue.ts +2 -2
- package/ui/es/packages/components/src/sjDigitalHumanAssistant/src/index.vue2.ts +317 -315
- package/ui/es/packages/components/src/utils/videoBackgroundRemoval.ts +114 -142
- package/ui/es/sj-ai-plus.css +1 -1
- package/ui/lib/packages/components/src/sjDigitalHumanAssistant/src/index.vue.ts +1 -1
- package/ui/lib/packages/components/src/sjDigitalHumanAssistant/src/index.vue2.ts +1 -1
- package/ui/lib/packages/components/src/utils/videoBackgroundRemoval.ts +10 -13
- package/ui/lib/sj-ai-plus.css +1 -1
|
@@ -1,27 +1,29 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
const
|
|
1
|
+
import { defineComponent as Se, useCssVars as Ye, ref as u, reactive as Be, computed as Te, watch as P, nextTick as y, onMounted as Ue, onUnmounted as Oe, resolveDirective as je, openBlock as k, createElementBlock as D, normalizeStyle as ke, withDirectives as w, createElementVNode as n, vShow as g, normalizeClass as J, toDisplayString as ae, withModifiers as se, renderSlot as le, createCommentVNode as $, createBlock as Ge, Teleport as ze } from "vue";
|
|
2
|
+
import ce from "../../utils/api.ts";
|
|
3
|
+
import q from "../../utils/utils.ts";
|
|
4
|
+
import Fe from "../../utils/videoBackgroundRemoval.ts";
|
|
5
|
+
const Ae = { class: "digital-human-assistant" }, Ne = { class: "placeholder left-placeholder" }, Je = { class: "placeholder right-placeholder" }, qe = { class: "window-header-left" }, Ke = { class: "window-title-text" }, Qe = { class: "window-header-btns" }, Ze = { class: "disconnect-btn" }, et = {
|
|
6
6
|
class: "connect-btn",
|
|
7
7
|
disabled: ""
|
|
8
|
-
},
|
|
8
|
+
}, tt = { class: "connect-btn" }, nt = { class: "window-content" }, ot = { class: "main-content-inner" }, it = { class: "window-header-left" }, at = { class: "window-title-text" }, st = { class: "window-header-btns" }, lt = { class: "disconnect-btn" }, ct = {
|
|
9
9
|
class: "connect-btn",
|
|
10
10
|
disabled: ""
|
|
11
|
-
},
|
|
11
|
+
}, dt = { class: "connect-btn" }, ut = { class: "window-content" }, rt = { class: "window-header-left" }, vt = { class: "window-title-text" }, ft = { class: "window-header-btns" }, ht = { class: "disconnect-btn" }, wt = {
|
|
12
12
|
class: "connect-btn",
|
|
13
13
|
disabled: ""
|
|
14
|
-
},
|
|
14
|
+
}, gt = { class: "connect-btn" }, mt = { class: "window-content" }, pt = {
|
|
15
|
+
key: 0,
|
|
16
|
+
class: "digital-video-loading"
|
|
17
|
+
}, bt = Se({
|
|
15
18
|
name: "SjDigitalHumanAssistant"
|
|
16
|
-
}),
|
|
17
|
-
...
|
|
19
|
+
}), Tt = /* @__PURE__ */ Se({
|
|
20
|
+
...bt,
|
|
18
21
|
props: {
|
|
19
22
|
windowWidth: { default: 320 },
|
|
20
23
|
windowHeight: { default: 467 },
|
|
21
24
|
windowTitle: { default: "数字人助手" },
|
|
22
25
|
sidebarWidth: { default: "25%" },
|
|
23
|
-
|
|
24
|
-
sidebarRightTitle: { default: "右侧业务区" },
|
|
26
|
+
sidebarBgColor: { default: "#ffffff" },
|
|
25
27
|
edgeThreshold: { default: 10 },
|
|
26
28
|
dragThreshold: { default: 8 },
|
|
27
29
|
defaultStickSide: { default: "" },
|
|
@@ -30,440 +32,439 @@ const Ue = { class: "digital-human-assistant" }, ze = { class: "placeholder left
|
|
|
30
32
|
maxReconnectTimes: { default: 10 },
|
|
31
33
|
baseUrl: { default: "" }
|
|
32
34
|
},
|
|
33
|
-
setup(
|
|
34
|
-
|
|
35
|
+
setup(V, { expose: Ee }) {
|
|
36
|
+
Ye((e) => ({
|
|
37
|
+
v4920a482: e.sidebarBgColor
|
|
38
|
+
}));
|
|
39
|
+
const i = V, de = u(null), ue = u(null), s = u(null), o = u(null), re = u(null), ve = u(null), fe = u(null), X = u(null), r = Fe(), S = u(!1), l = u(!1), f = u(!1), E = u(!1), he = u(!0), Y = u(!1), h = u(i.defaultStickSide), B = u(!1), R = u(!1), x = u(!1), K = u(!1), Q = u(!1);
|
|
40
|
+
let d = null, m = "";
|
|
41
|
+
const U = u(null), p = u(0), O = u(!1), M = u(!1), v = Be({
|
|
35
42
|
x: 0,
|
|
36
43
|
y: 0,
|
|
37
44
|
offsetX: 0,
|
|
38
45
|
offsetY: 0
|
|
39
|
-
}),
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"--
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
}, ve = () => {
|
|
58
|
-
switch (v.value) {
|
|
46
|
+
}), xe = Te(() => ({
|
|
47
|
+
"--sidebar-width": i.sidebarWidth,
|
|
48
|
+
"--window-width": `${i.windowWidth}px`,
|
|
49
|
+
"--window-height": `${i.windowHeight}px`
|
|
50
|
+
})), Me = Te(() => ({
|
|
51
|
+
left: `${v.x}px`,
|
|
52
|
+
top: `${v.y}px`,
|
|
53
|
+
width: `${i.windowWidth}px`,
|
|
54
|
+
height: `${i.windowHeight}px`,
|
|
55
|
+
zIndex: B.value || x.value ? 9999 : 1e3
|
|
56
|
+
})), Le = (e) => {
|
|
57
|
+
!e && s.value ? (O.value = !1, p.value = 0, Re()) : e ? (O.value = !0, Ve()) : console.warn("❌ 自动连接超时:video元素未挂载"), he.value = e;
|
|
58
|
+
}, j = (e) => {
|
|
59
|
+
Le(!e), Y.value = e, e && l.value ? y(() => b()) : e || (E.value = !1);
|
|
60
|
+
}, He = () => {
|
|
61
|
+
j(!0);
|
|
62
|
+
}, we = () => {
|
|
63
|
+
switch (h.value) {
|
|
59
64
|
case "left":
|
|
60
|
-
return
|
|
65
|
+
return ve.value ?? X.value;
|
|
61
66
|
case "right":
|
|
62
|
-
return
|
|
67
|
+
return fe.value ?? X.value;
|
|
63
68
|
default:
|
|
64
|
-
return
|
|
69
|
+
return re.value ?? X.value;
|
|
65
70
|
}
|
|
66
|
-
},
|
|
71
|
+
}, G = () => ue.value?.getBoundingClientRect() || {
|
|
67
72
|
width: 0,
|
|
68
73
|
height: 0,
|
|
69
74
|
left: 0,
|
|
70
75
|
right: 0,
|
|
71
76
|
top: 0,
|
|
72
77
|
bottom: 0
|
|
73
|
-
},
|
|
78
|
+
}, ge = () => de.value?.getBoundingClientRect() || {
|
|
74
79
|
width: 0,
|
|
75
80
|
height: 0,
|
|
76
81
|
left: 0,
|
|
77
82
|
right: 0,
|
|
78
83
|
top: 0,
|
|
79
84
|
bottom: 0
|
|
80
|
-
},
|
|
81
|
-
const
|
|
85
|
+
}, Z = (e, t) => {
|
|
86
|
+
const c = window.innerWidth || document.documentElement.clientWidth, a = window.innerHeight || document.documentElement.clientHeight;
|
|
82
87
|
return {
|
|
83
|
-
x: Math.max(0, Math.min(
|
|
84
|
-
y: Math.max(0, Math.min(
|
|
88
|
+
x: Math.max(0, Math.min(e, c - i.windowWidth)),
|
|
89
|
+
y: Math.max(0, Math.min(t, a - i.windowHeight))
|
|
85
90
|
};
|
|
86
|
-
},
|
|
87
|
-
const
|
|
88
|
-
return
|
|
89
|
-
},
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
},
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
},
|
|
96
|
-
|
|
97
|
-
},
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
},
|
|
91
|
+
}, me = () => {
|
|
92
|
+
const e = window.innerWidth || document.documentElement.clientWidth, t = window.innerHeight || document.documentElement.clientHeight, c = e - i.windowWidth - 10, a = t - i.windowHeight - 10;
|
|
93
|
+
return Z(c, a);
|
|
94
|
+
}, pe = () => {
|
|
95
|
+
const e = G(), t = ge();
|
|
96
|
+
K.value = t.left <= e.left + i.edgeThreshold, Q.value = t.right >= e.right - i.edgeThreshold;
|
|
97
|
+
}, be = () => {
|
|
98
|
+
const e = G(), t = ge(), c = t.left <= e.left + i.edgeThreshold ? "left" : t.right >= e.right - i.edgeThreshold ? "right" : "";
|
|
99
|
+
c !== h.value && (h.value = c, s.value && (s.value.volume = c ? 0.5 : 1), H(), b()), K.value = Q.value = !1;
|
|
100
|
+
}, Ie = () => {
|
|
101
|
+
E.value = !0;
|
|
102
|
+
}, Pe = () => {
|
|
103
|
+
E.value = !1;
|
|
104
|
+
}, De = (e) => {
|
|
105
|
+
B.value = !0, v.offsetX = e.clientX - v.x, v.offsetY = e.clientY - v.y, document.addEventListener("mousemove", ee), document.addEventListener("mouseup", te);
|
|
106
|
+
}, ee = (e) => {
|
|
107
|
+
if (!B.value) return;
|
|
108
|
+
const t = G(), { x: c, y: a } = Z(e.clientX - t.left - v.offsetX, e.clientY - t.top - v.offsetY);
|
|
109
|
+
v.x = c, v.y = a, pe();
|
|
110
|
+
}, te = () => {
|
|
111
|
+
be(), B.value = !1, document.removeEventListener("mousemove", ee), document.removeEventListener("mouseup", te);
|
|
112
|
+
}, ye = (e, t) => {
|
|
113
|
+
R.value = !0, v.offsetX = t.clientX - (t.clientX - i.windowWidth / 2), v.offsetY = t.clientY - (t.clientY - 20), document.addEventListener("mousemove", z);
|
|
114
|
+
}, z = (e) => {
|
|
106
115
|
if (!R.value) return;
|
|
107
|
-
const
|
|
108
|
-
(
|
|
109
|
-
},
|
|
110
|
-
if (!
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
},
|
|
116
|
-
R.value && !
|
|
117
|
-
},
|
|
118
|
-
if (!
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
text: t,
|
|
116
|
+
const t = Math.abs(e.movementX), c = Math.abs(e.movementY);
|
|
117
|
+
(t > i.dragThreshold || c > i.dragThreshold) && (x.value = !0, h.value = "", document.removeEventListener("mousemove", z), document.addEventListener("mousemove", ne), document.addEventListener("mouseup", oe));
|
|
118
|
+
}, ne = (e) => {
|
|
119
|
+
if (!x.value) return;
|
|
120
|
+
const t = G(), { x: c, y: a } = Z(e.clientX - t.left - v.offsetX, e.clientY - t.top - v.offsetY);
|
|
121
|
+
v.x = c, v.y = a, pe();
|
|
122
|
+
}, oe = () => {
|
|
123
|
+
be(), R.value = x.value = !1, document.removeEventListener("mousemove", ne), document.removeEventListener("mouseup", oe);
|
|
124
|
+
}, F = () => {
|
|
125
|
+
R.value && !x.value && (R.value = !1, document.removeEventListener("mousemove", z));
|
|
126
|
+
}, ie = async (e) => {
|
|
127
|
+
if (!l.value || !m) return;
|
|
128
|
+
console.log("✅ 准备播放文本:", e);
|
|
129
|
+
const t = {
|
|
130
|
+
text: e,
|
|
123
131
|
type: "echo",
|
|
124
132
|
interrupt: !0,
|
|
125
|
-
sessionid: parseInt(
|
|
133
|
+
sessionid: parseInt(m)
|
|
126
134
|
};
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}).catch((
|
|
130
|
-
console.
|
|
135
|
+
ce.digitalHumanChat(i.baseUrl, t).then((c) => {
|
|
136
|
+
c && Number(c.code) === 0 && console.log("✅ 播放指令发送成功");
|
|
137
|
+
}).catch((c) => {
|
|
138
|
+
console.error("❌ 播放指令发送失败:", c);
|
|
131
139
|
});
|
|
132
|
-
},
|
|
133
|
-
if (!
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}).catch((e) => {
|
|
140
|
-
console.log("api.digitalHumanInterruptTalk:", e);
|
|
140
|
+
}, L = async () => {
|
|
141
|
+
if (!l.value || !m) return;
|
|
142
|
+
const e = { sessionid: parseInt(m) };
|
|
143
|
+
ce.digitalHumanInterruptTalk(i.baseUrl, e).then((t) => {
|
|
144
|
+
t && Number(t.code) === 0 && console.log("✅ 对话已打断");
|
|
145
|
+
}).catch((t) => {
|
|
146
|
+
console.error("❌ 打断对话失败:", t);
|
|
141
147
|
});
|
|
142
|
-
},
|
|
143
|
-
|
|
144
|
-
},
|
|
145
|
-
if (!
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
if (
|
|
149
|
-
const
|
|
150
|
-
|
|
148
|
+
}, T = () => {
|
|
149
|
+
U.value && (clearTimeout(U.value), U.value = null), M.value = !1, console.log("✅ 重连定时器已清除");
|
|
150
|
+
}, H = (e = !1) => {
|
|
151
|
+
if (!o.value) return;
|
|
152
|
+
e || r.stopProcessing();
|
|
153
|
+
const t = o.value.getContext("2d");
|
|
154
|
+
if (t && (t.clearRect(0, 0, o.value.width, o.value.height), !e)) {
|
|
155
|
+
const c = o.value.width, a = o.value.height;
|
|
156
|
+
o.value.width = c, o.value.height = a;
|
|
151
157
|
}
|
|
152
|
-
|
|
153
|
-
},
|
|
154
|
-
if (!
|
|
155
|
-
await
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
a.value.width = Math.floor(T * Re), a.value.height = Math.floor(k * Re), a.value.style.display = "block", a.value.style.objectFit = "contain", v.value === "" ? (a.value.style.width = `${T}px`, a.value.style.height = `${k}px`, a.value.style.marginLeft = `${(U - T) / 2}px`, a.value.style.marginTop = `${(z - k) / 2}px`) : (a.value.style.width = "100%", a.value.style.height = "100%", a.value.style.marginLeft = "0", a.value.style.marginTop = "0"), console.log("Canvas适配完成:", {
|
|
173
|
-
mode: v.value || "浮动",
|
|
174
|
-
container: { width: U, height: z },
|
|
175
|
-
canvas: { drawWidth: T, drawHeight: k, physicalWidth: a.value.width, physicalHeight: a.value.height }
|
|
176
|
-
}), t || (p.videoRef.value = u.value, p.canvasRef.value = a.value, await p.processVideo());
|
|
177
|
-
}, W = () => {
|
|
178
|
-
if (I.value || c.value || h.value || L.value) {
|
|
179
|
-
console.log("重连条件不满足:手动断开/已连接/正在连接/正在冷却");
|
|
158
|
+
o.value && !e && (o.value.style.width = "", o.value.style.height = "", h.value === "" && (o.value.style.marginLeft = "", o.value.style.marginTop = ""));
|
|
159
|
+
}, b = async (e = !1) => {
|
|
160
|
+
if (!s.value || !o.value || !S.value || !l.value) return;
|
|
161
|
+
await y();
|
|
162
|
+
const t = s.value.videoWidth || i.windowWidth, c = s.value.videoHeight || i.windowHeight, a = t / c;
|
|
163
|
+
let C;
|
|
164
|
+
const _e = we();
|
|
165
|
+
_e ? C = _e.getBoundingClientRect() : C = { width: 0, height: 0, left: 0, top: 0, right: 0, bottom: 0 };
|
|
166
|
+
const A = C.width || (h.value ? 300 : i.windowWidth), N = C.height || (h.value ? window.innerHeight - 40 : i.windowHeight), Xe = A / N;
|
|
167
|
+
let _, W;
|
|
168
|
+
Xe > a ? (W = N, _ = W * a) : (_ = A, W = _ / a);
|
|
169
|
+
const We = window.devicePixelRatio || 1;
|
|
170
|
+
o.value.width = Math.floor(_ * We), o.value.height = Math.floor(W * We), o.value.style.display = "block", o.value.style.objectFit = "contain", h.value === "" ? (o.value.style.width = `${_}px`, o.value.style.height = `${W}px`, o.value.style.marginLeft = `${(A - _) / 2}px`, o.value.style.marginTop = `${(N - W) / 2}px`) : (o.value.style.width = "100%", o.value.style.height = "100%", o.value.style.marginLeft = "0", o.value.style.marginTop = "0"), console.log("✅ Canvas适配完成:", {
|
|
171
|
+
mode: h.value || "浮动",
|
|
172
|
+
container: { width: A, height: N },
|
|
173
|
+
canvas: { drawWidth: _, drawHeight: W }
|
|
174
|
+
}), e || (r.videoRef.value = s.value, r.canvasRef.value = o.value, await r.processVideo()), !r.isInitSuccess.value && l.value && (console.log("🔄 检测到WebGPU未初始化,触发手动重连"), await r.reInitWebGPU() && await r.processVideo());
|
|
175
|
+
}, I = () => {
|
|
176
|
+
if (O.value || l.value || f.value || M.value) {
|
|
177
|
+
console.log("🚫 重连条件不满足");
|
|
180
178
|
return;
|
|
181
179
|
}
|
|
182
|
-
if (
|
|
183
|
-
console.
|
|
184
|
-
}), o.maxReconnectTimes !== -1 && y.value >= o.maxReconnectTimes) {
|
|
185
|
-
console.warn(`数字人重连已达最大次数(${o.maxReconnectTimes}),停止重连`), x(), Ce.funcElMessageShowCtrl(`数字人连接失败,已尝试${o.maxReconnectTimes}次重连,请重试!`), y.value = 0;
|
|
180
|
+
if (L(), i.maxReconnectTimes !== -1 && p.value >= i.maxReconnectTimes) {
|
|
181
|
+
console.warn(`🚫 重连已达最大次数(${i.maxReconnectTimes})`), T(), q.funcElMessageShowCtrl(`❌ 数字人连接失败,已尝试${i.maxReconnectTimes}次重连,请重试!`, "error"), p.value = 0;
|
|
186
182
|
return;
|
|
187
183
|
}
|
|
188
|
-
|
|
184
|
+
M.value = !0, U.value = setTimeout(() => {
|
|
189
185
|
try {
|
|
190
|
-
|
|
186
|
+
p.value++, console.log(`🔄 第${p.value}次重连WebRTC...`), r.stopProcessing(), Re();
|
|
191
187
|
} finally {
|
|
192
|
-
|
|
188
|
+
M.value = !1;
|
|
193
189
|
}
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
if (
|
|
190
|
+
}, i.reconnectInterval * 1e3);
|
|
191
|
+
}, $e = async () => {
|
|
192
|
+
if (d)
|
|
197
193
|
try {
|
|
198
|
-
|
|
199
|
-
const
|
|
200
|
-
await
|
|
201
|
-
if (
|
|
202
|
-
|
|
194
|
+
d.addTransceiver("video", { direction: "recvonly" }), d.addTransceiver("audio", { direction: "recvonly" });
|
|
195
|
+
const e = await d.createOffer();
|
|
196
|
+
await d.setLocalDescription(e), await new Promise((a) => {
|
|
197
|
+
if (d?.iceGatheringState === "complete")
|
|
198
|
+
a();
|
|
203
199
|
else {
|
|
204
|
-
const
|
|
205
|
-
|
|
200
|
+
const C = () => {
|
|
201
|
+
d?.iceGatheringState === "complete" && (d?.removeEventListener("icegatheringstatechange", C), a());
|
|
206
202
|
};
|
|
207
|
-
|
|
203
|
+
d?.addEventListener("icegatheringstatechange", C);
|
|
208
204
|
}
|
|
209
205
|
});
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
l ? (b = l.sessionid, s.setRemoteDescription(new RTCSessionDescription(l)), c.value = !0, y.value = 0, x(), console.log("数字人连接成功,重置重连状态"), m(() => w())) : (c.value = !1, console.log("数字人连接失败:接口返回空"), W()), h.value = !1;
|
|
216
|
-
}).catch((l) => {
|
|
217
|
-
console.error("api.digitalHumanOffer 失败:", l), c.value = !1, h.value = !1, W();
|
|
206
|
+
const t = d.localDescription, c = { sdp: t.sdp, type: t.type };
|
|
207
|
+
ce.digitalHumanOffer(i.baseUrl, c).then((a) => {
|
|
208
|
+
a ? (m = a.sessionid, d.setRemoteDescription(new RTCSessionDescription(a)), l.value = !0, p.value = 0, T(), console.log("✅ WebRTC连接成功"), y(() => b())) : (l.value = !1, console.log("❌ WebRTC连接失败:接口返回空"), I()), f.value = !1;
|
|
209
|
+
}).catch((a) => {
|
|
210
|
+
console.error("❌ WebRTC Offer发送失败:", a), l.value = !1, f.value = !1, I();
|
|
218
211
|
});
|
|
219
|
-
} catch (
|
|
220
|
-
console.error("
|
|
212
|
+
} catch (e) {
|
|
213
|
+
console.error("❌ WebRTC协商失败:", e), l.value = !1, f.value = !1, I();
|
|
221
214
|
}
|
|
222
|
-
},
|
|
223
|
-
if (
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
s && (s.close(), s = null), s = new RTCPeerConnection(t), s.addEventListener("track", (e) => {
|
|
232
|
-
e.track.kind === "video" && u.value && (u.value.srcObject = e.streams[0], u.value.onloadedmetadata = async () => {
|
|
233
|
-
u.value && a.value && (p.videoRef.value = u.value, p.canvasRef.value = a.value, await w(), await p.processVideo());
|
|
234
|
-
}, u.value.onresize = () => {
|
|
235
|
-
w();
|
|
215
|
+
}, Re = () => {
|
|
216
|
+
if (l.value || f.value) return;
|
|
217
|
+
f.value = !0, console.log("🔄 开始建立WebRTC连接..."), d && (d.close(), d = null);
|
|
218
|
+
const e = { sdpSemantics: "unified-plan" };
|
|
219
|
+
d = new RTCPeerConnection(e), d.addEventListener("track", (t) => {
|
|
220
|
+
t.track.kind === "video" && s.value && (s.value.srcObject = t.streams[0], s.value.onloadedmetadata = async () => {
|
|
221
|
+
s.value && o.value && (r.videoRef.value = s.value, r.canvasRef.value = o.value, await b(), await r.processVideo());
|
|
222
|
+
}, s.value.onresize = () => {
|
|
223
|
+
b(!0);
|
|
236
224
|
});
|
|
237
|
-
}),
|
|
238
|
-
switch (console.log("ICE
|
|
225
|
+
}), d.addEventListener("iceconnectionstatechange", () => {
|
|
226
|
+
switch (console.log("📶 ICE状态变化:", d.iceConnectionState), d.iceConnectionState) {
|
|
239
227
|
case "disconnected":
|
|
240
228
|
case "failed":
|
|
241
229
|
case "closed":
|
|
242
|
-
console.log("
|
|
243
|
-
console.log("ICE连接断开,已打断对话");
|
|
244
|
-
}), W();
|
|
230
|
+
console.log("📶 ICE连接断开,触发重连"), l.value = !1, f.value = !1, d = null, m = "", s.value && (s.value.srcObject = null), H(), L(), I();
|
|
245
231
|
break;
|
|
246
232
|
case "connected":
|
|
247
|
-
|
|
233
|
+
console.log("📶 ICE连接成功"), p.value = 0, T(), y(async () => {
|
|
234
|
+
!r.isInitSuccess.value && l.value && await r.reInitWebGPU() && await r.processVideo();
|
|
235
|
+
});
|
|
248
236
|
break;
|
|
249
237
|
}
|
|
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
|
-
}), te(
|
|
277
|
-
v,
|
|
278
|
-
async (t, e) => {
|
|
279
|
-
!S.value || !u.value || (await m(), u.value.volume = t ? 0.5 : 1, c.value && (M(), await w()));
|
|
238
|
+
}), $e();
|
|
239
|
+
}, Ve = () => {
|
|
240
|
+
O.value = !0, T(), f.value = !1, r.stopProcessing(), H(), L().then(() => {
|
|
241
|
+
setTimeout(() => {
|
|
242
|
+
d && (d.close(), d = null), m = "", s.value && (s.value.srcObject = null), l.value = !1, p.value = 0, console.log("✅ 手动断开连接,资源已清理");
|
|
243
|
+
}, 500);
|
|
244
|
+
});
|
|
245
|
+
}, Ce = q.debounce(() => {
|
|
246
|
+
if (h.value === "") {
|
|
247
|
+
const { x: e, y: t } = me();
|
|
248
|
+
v.x = e, v.y = t;
|
|
249
|
+
}
|
|
250
|
+
l.value && S.value && (H(!0), y(() => b(!0)));
|
|
251
|
+
}, 50);
|
|
252
|
+
return P(r.isInitSuccess, (e) => {
|
|
253
|
+
!e && f.value && q.funcElMessageShowCtrl("🔄 WebGPU初始化失败,正在尝试重连...", "warning");
|
|
254
|
+
}, { immediate: !0 }), P(
|
|
255
|
+
[() => r.isInitSuccess, () => l.value],
|
|
256
|
+
async ([e, t]) => {
|
|
257
|
+
!e && t && s.value && o.value ? (o.value.style.display = "none", s.value.style.opacity = "1", s.value.style.width = "100%", s.value.style.height = "100%", q.funcElMessageShowCtrl("ℹ️ 当前浏览器不支持WebGPU,将显示原始视频(无透明背景)", "info")) : e && t && s.value && o.value && (o.value.style.display = "block", s.value.style.opacity = "0");
|
|
258
|
+
},
|
|
259
|
+
{ immediate: !0 }
|
|
260
|
+
), P(
|
|
261
|
+
h,
|
|
262
|
+
async (e) => {
|
|
263
|
+
!S.value || !s.value || (await y(), s.value.volume = e ? 0.5 : 1, l.value && (H(), await b()));
|
|
280
264
|
},
|
|
281
265
|
{ immediate: !0, deep: !0 }
|
|
282
|
-
),
|
|
283
|
-
[() =>
|
|
284
|
-
async ([
|
|
285
|
-
|
|
266
|
+
), P(
|
|
267
|
+
[() => l.value, () => i.defaultPlayText],
|
|
268
|
+
async ([e, t], [c]) => {
|
|
269
|
+
e && !c && t && m && (console.log("✅ 连接成功,自动播放默认文本:", t), await ie(t));
|
|
286
270
|
},
|
|
287
271
|
{ immediate: !1 }
|
|
288
|
-
),
|
|
289
|
-
() =>
|
|
290
|
-
async (
|
|
291
|
-
|
|
272
|
+
), P(
|
|
273
|
+
() => i.defaultPlayText,
|
|
274
|
+
async (e) => {
|
|
275
|
+
l.value && e && m && (console.log("✅ 默认文本更新,自动播放:", e), await ie(e));
|
|
292
276
|
},
|
|
293
277
|
{ immediate: !0 }
|
|
294
|
-
),
|
|
295
|
-
await
|
|
296
|
-
const { x:
|
|
297
|
-
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
278
|
+
), Ue(async () => {
|
|
279
|
+
await y(), await y(), S.value = !0;
|
|
280
|
+
const { x: e, y: t } = me();
|
|
281
|
+
v.x = e, v.y = t, window.addEventListener("resize", Ce);
|
|
282
|
+
}), Oe(() => {
|
|
283
|
+
document.removeEventListener("mousemove", z), document.removeEventListener("mousemove", ne), document.removeEventListener("mouseup", oe), document.removeEventListener("mousemove", ee), document.removeEventListener("mouseup", te), window.removeEventListener("resize", Ce), T(), r.stopProcessing(), L(), d && d.close(), s.value && (s.value.srcObject = null);
|
|
284
|
+
}), Ee({
|
|
285
|
+
digitalHumanChat: ie,
|
|
286
|
+
// 播放文本
|
|
287
|
+
digitalHumanInterruptTalk: L,
|
|
288
|
+
// 打断对话
|
|
289
|
+
isConnected: l,
|
|
290
|
+
// 连接状态
|
|
291
|
+
isConnecting: f,
|
|
292
|
+
// 连接中状态
|
|
293
|
+
reconnect: I,
|
|
294
|
+
// 手动重连WebRTC
|
|
295
|
+
clearReconnectTimer: T,
|
|
296
|
+
// 停止重连
|
|
297
|
+
currentReconnectTimes: p,
|
|
298
|
+
// 当前重连次数
|
|
299
|
+
isWaitingReconnect: M,
|
|
300
|
+
// 重连冷却状态
|
|
301
|
+
adaptCanvasToContainer: b,
|
|
302
|
+
// 手动适配Canvas
|
|
303
|
+
webgpuReInit: r.reInitWebGPU,
|
|
304
|
+
// 手动重连WebGPU
|
|
305
|
+
webgpuIsInitSuccess: r.isInitSuccess,
|
|
306
|
+
// WebGPU初始化状态
|
|
307
|
+
webgpuIsProcessing: r.isProcessing
|
|
308
|
+
// WebGPU运行状态
|
|
309
|
+
}), (e, t) => {
|
|
310
|
+
const c = je("drag");
|
|
311
|
+
return k(), D("div", {
|
|
313
312
|
class: "draggable-window-container",
|
|
314
|
-
style:
|
|
313
|
+
style: ke(xe.value)
|
|
315
314
|
}, [
|
|
316
|
-
|
|
317
|
-
[g,
|
|
318
|
-
[
|
|
315
|
+
w(n("div", Ae, null, 512), [
|
|
316
|
+
[g, he.value],
|
|
317
|
+
[c, ["digital-human-assistant", He, !0]]
|
|
319
318
|
]),
|
|
320
319
|
n("div", {
|
|
321
320
|
ref_key: "teleportFallbackRef",
|
|
322
|
-
ref:
|
|
321
|
+
ref: X,
|
|
323
322
|
class: "teleport-fallback"
|
|
324
323
|
}, null, 512),
|
|
325
|
-
|
|
326
|
-
[g,
|
|
324
|
+
w(n("div", Ne, null, 512), [
|
|
325
|
+
[g, K.value]
|
|
327
326
|
]),
|
|
328
|
-
|
|
329
|
-
[g,
|
|
327
|
+
w(n("div", Je, null, 512), [
|
|
328
|
+
[g, Q.value]
|
|
330
329
|
]),
|
|
331
|
-
|
|
330
|
+
Y.value && h.value === "left" ? (k(), D("div", {
|
|
332
331
|
key: 0,
|
|
333
|
-
class:
|
|
332
|
+
class: J(["sidebar left-sidebar", { pressing: R.value }])
|
|
334
333
|
}, [
|
|
335
334
|
n("div", {
|
|
336
335
|
class: "window-header",
|
|
337
|
-
onMousedown:
|
|
338
|
-
onMouseup:
|
|
339
|
-
onMouseleave:
|
|
336
|
+
onMousedown: t[2] || (t[2] = (a) => ye("left", a)),
|
|
337
|
+
onMouseup: F,
|
|
338
|
+
onMouseleave: F
|
|
340
339
|
}, [
|
|
341
|
-
n("div",
|
|
342
|
-
n("span",
|
|
343
|
-
n("div",
|
|
344
|
-
|
|
345
|
-
[g, !
|
|
340
|
+
n("div", qe, [
|
|
341
|
+
n("span", Ke, ae(V.windowTitle), 1),
|
|
342
|
+
n("div", Qe, [
|
|
343
|
+
w(n("button", Ze, "未连接", 512), [
|
|
344
|
+
[g, !l.value && !f.value]
|
|
346
345
|
]),
|
|
347
|
-
|
|
348
|
-
[g,
|
|
346
|
+
w(n("button", et, "连接中...", 512), [
|
|
347
|
+
[g, f.value]
|
|
349
348
|
]),
|
|
350
|
-
|
|
351
|
-
[g,
|
|
349
|
+
w(n("button", tt, "已连接", 512), [
|
|
350
|
+
[g, l.value]
|
|
352
351
|
])
|
|
353
352
|
])
|
|
354
353
|
]),
|
|
355
354
|
n("div", {
|
|
356
355
|
class: "drag-window-hide",
|
|
357
|
-
onClick:
|
|
358
|
-
onMousedown:
|
|
356
|
+
onClick: t[0] || (t[0] = (a) => j(!1)),
|
|
357
|
+
onMousedown: t[1] || (t[1] = se(() => {
|
|
359
358
|
}, ["stop"]))
|
|
360
359
|
}, null, 32)
|
|
361
360
|
], 32),
|
|
362
|
-
n("div",
|
|
363
|
-
|
|
361
|
+
n("div", nt, [
|
|
362
|
+
le(e.$slots, "sidebar-left", {}, void 0, !0),
|
|
364
363
|
n("div", {
|
|
365
364
|
ref_key: "sidebarLeftVideoRef",
|
|
366
|
-
ref:
|
|
365
|
+
ref: ve,
|
|
367
366
|
class: "sidebar-video-container"
|
|
368
367
|
}, null, 512)
|
|
369
368
|
])
|
|
370
|
-
], 2)) :
|
|
369
|
+
], 2)) : $("", !0),
|
|
371
370
|
n("div", {
|
|
372
371
|
class: "main-content-outer",
|
|
373
372
|
ref_key: "containerRef",
|
|
374
|
-
ref:
|
|
373
|
+
ref: ue
|
|
375
374
|
}, [
|
|
376
|
-
n("div",
|
|
377
|
-
|
|
375
|
+
n("div", ot, [
|
|
376
|
+
le(e.$slots, "main", {}, void 0, !0)
|
|
378
377
|
]),
|
|
379
|
-
|
|
378
|
+
Y.value && h.value === "" ? (k(), D("div", {
|
|
380
379
|
key: 0,
|
|
381
380
|
ref_key: "dragWindowRef",
|
|
382
|
-
ref:
|
|
383
|
-
class: "draggable-window",
|
|
384
|
-
style:
|
|
381
|
+
ref: de,
|
|
382
|
+
class: J(["draggable-window", { "draggable-window-shadow": !l.value || E.value }]),
|
|
383
|
+
style: ke(Me.value),
|
|
384
|
+
onMouseenter: Ie,
|
|
385
|
+
onMouseleave: Pe
|
|
385
386
|
}, [
|
|
386
387
|
n("div", {
|
|
387
|
-
class: "window-header",
|
|
388
|
-
onMousedown:
|
|
388
|
+
class: J(["window-header", { "window-header-opacity": l.value && !E.value }]),
|
|
389
|
+
onMousedown: De
|
|
389
390
|
}, [
|
|
390
|
-
n("div",
|
|
391
|
-
n("span",
|
|
392
|
-
n("div",
|
|
393
|
-
|
|
394
|
-
[g, !
|
|
391
|
+
n("div", it, [
|
|
392
|
+
n("span", at, ae(V.windowTitle), 1),
|
|
393
|
+
n("div", st, [
|
|
394
|
+
w(n("button", lt, "未连接", 512), [
|
|
395
|
+
[g, !l.value && !f.value]
|
|
395
396
|
]),
|
|
396
|
-
|
|
397
|
-
[g,
|
|
397
|
+
w(n("button", ct, "连接中...", 512), [
|
|
398
|
+
[g, f.value]
|
|
398
399
|
]),
|
|
399
|
-
|
|
400
|
-
[g,
|
|
400
|
+
w(n("button", dt, "已连接", 512), [
|
|
401
|
+
[g, l.value]
|
|
401
402
|
])
|
|
402
403
|
])
|
|
403
404
|
]),
|
|
404
405
|
n("div", {
|
|
405
406
|
class: "drag-window-hide",
|
|
406
|
-
onClick:
|
|
407
|
-
onMousedown:
|
|
407
|
+
onClick: t[3] || (t[3] = (a) => j(!1)),
|
|
408
|
+
onMousedown: t[4] || (t[4] = se(() => {
|
|
408
409
|
}, ["stop"]))
|
|
409
410
|
}, null, 32)
|
|
410
|
-
],
|
|
411
|
-
n("div",
|
|
411
|
+
], 34),
|
|
412
|
+
n("div", ut, [
|
|
412
413
|
n("div", {
|
|
413
414
|
class: "video-container",
|
|
414
415
|
ref_key: "windowVideoRef",
|
|
415
|
-
ref:
|
|
416
|
+
ref: re
|
|
416
417
|
}, null, 512)
|
|
417
418
|
])
|
|
418
|
-
],
|
|
419
|
+
], 38)) : $("", !0)
|
|
419
420
|
], 512),
|
|
420
|
-
|
|
421
|
+
Y.value && h.value === "right" ? (k(), D("div", {
|
|
421
422
|
key: 1,
|
|
422
|
-
class:
|
|
423
|
+
class: J(["sidebar right-sidebar", { pressing: R.value }])
|
|
423
424
|
}, [
|
|
424
425
|
n("div", {
|
|
425
426
|
class: "window-header",
|
|
426
|
-
onMousedown:
|
|
427
|
-
onMouseup:
|
|
428
|
-
onMouseleave:
|
|
427
|
+
onMousedown: t[7] || (t[7] = (a) => ye("right", a)),
|
|
428
|
+
onMouseup: F,
|
|
429
|
+
onMouseleave: F
|
|
429
430
|
}, [
|
|
430
|
-
n("div",
|
|
431
|
-
n("span",
|
|
432
|
-
n("div",
|
|
433
|
-
|
|
434
|
-
[g, !
|
|
431
|
+
n("div", rt, [
|
|
432
|
+
n("span", vt, ae(V.windowTitle), 1),
|
|
433
|
+
n("div", ft, [
|
|
434
|
+
w(n("button", ht, "未连接", 512), [
|
|
435
|
+
[g, !l.value && !f.value]
|
|
435
436
|
]),
|
|
436
|
-
|
|
437
|
-
[g,
|
|
437
|
+
w(n("button", wt, "连接中...", 512), [
|
|
438
|
+
[g, f.value]
|
|
438
439
|
]),
|
|
439
|
-
|
|
440
|
-
[g,
|
|
440
|
+
w(n("button", gt, "已连接", 512), [
|
|
441
|
+
[g, l.value]
|
|
441
442
|
])
|
|
442
443
|
])
|
|
443
444
|
]),
|
|
444
445
|
n("div", {
|
|
445
446
|
class: "drag-window-hide",
|
|
446
|
-
onClick:
|
|
447
|
-
onMousedown:
|
|
447
|
+
onClick: t[5] || (t[5] = (a) => j(!1)),
|
|
448
|
+
onMousedown: t[6] || (t[6] = se(() => {
|
|
448
449
|
}, ["stop"]))
|
|
449
450
|
}, null, 32)
|
|
450
451
|
], 32),
|
|
451
|
-
n("div",
|
|
452
|
-
|
|
452
|
+
n("div", mt, [
|
|
453
|
+
le(e.$slots, "sidebar-right", {}, void 0, !0),
|
|
453
454
|
n("div", {
|
|
454
455
|
ref_key: "sidebarRightVideoRef",
|
|
455
|
-
ref:
|
|
456
|
+
ref: fe,
|
|
456
457
|
class: "sidebar-video-container"
|
|
457
458
|
}, null, 512)
|
|
458
459
|
])
|
|
459
|
-
], 2)) :
|
|
460
|
-
S.value ? (
|
|
460
|
+
], 2)) : $("", !0),
|
|
461
|
+
S.value ? (k(), Ge(ze, {
|
|
461
462
|
key: 2,
|
|
462
|
-
to:
|
|
463
|
+
to: we()
|
|
463
464
|
}, [
|
|
464
465
|
n("video", {
|
|
465
466
|
ref_key: "digitalHumanVideo",
|
|
466
|
-
ref:
|
|
467
|
+
ref: s,
|
|
467
468
|
class: "digital-video source-video",
|
|
468
469
|
poster: "",
|
|
469
470
|
playsinline: "",
|
|
@@ -471,14 +472,15 @@ const Ue = { class: "digital-human-assistant" }, ze = { class: "placeholder left
|
|
|
471
472
|
}, null, 512),
|
|
472
473
|
n("canvas", {
|
|
473
474
|
ref_key: "processedCanvas",
|
|
474
|
-
ref:
|
|
475
|
+
ref: o,
|
|
475
476
|
class: "digital-video processed-canvas"
|
|
476
|
-
}, null, 512)
|
|
477
|
-
|
|
477
|
+
}, null, 512),
|
|
478
|
+
f.value ? (k(), D("div", pt)) : $("", !0)
|
|
479
|
+
], 8, ["to"])) : $("", !0)
|
|
478
480
|
], 4);
|
|
479
481
|
};
|
|
480
482
|
}
|
|
481
483
|
});
|
|
482
484
|
export {
|
|
483
|
-
|
|
485
|
+
Tt as default
|
|
484
486
|
};
|