ruiyun-human 1.0.4 → 1.0.6
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/dist/ruiyun-human.cjs.js +66 -16
- package/dist/ruiyun-human.es.js +66 -16
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/dist/ruiyun-human.cjs.js
CHANGED
|
@@ -452,20 +452,24 @@ const _sfc_main = {
|
|
|
452
452
|
const y = canvas.height - height;
|
|
453
453
|
ctx.value.drawImage(image, x, y, width, height);
|
|
454
454
|
};
|
|
455
|
-
const stop = () => {
|
|
455
|
+
const stop = (keepAudio = false) => {
|
|
456
|
+
var _a;
|
|
456
457
|
if (animationId.value) {
|
|
457
458
|
cancelAnimationFrame(animationId.value);
|
|
458
459
|
animationId.value = null;
|
|
459
460
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
461
|
+
if (!keepAudio) {
|
|
462
|
+
try {
|
|
463
|
+
(_a = currentAudio.value) == null ? void 0 : _a.pause();
|
|
464
|
+
} catch (error) {
|
|
465
|
+
}
|
|
463
466
|
}
|
|
464
467
|
frameIndex.value = 1;
|
|
465
468
|
animationState.value = "standby";
|
|
466
469
|
};
|
|
467
470
|
const runAnimation = (state) => {
|
|
468
|
-
|
|
471
|
+
const keepAudio = state === "speak" || state === "speakLoop" || state === "speakEnd";
|
|
472
|
+
stop(keepAudio);
|
|
469
473
|
animationState.value = state;
|
|
470
474
|
loopDirection.value = 1;
|
|
471
475
|
let currentFrames;
|
|
@@ -550,6 +554,7 @@ const _sfc_main = {
|
|
|
550
554
|
runAnimation("speak");
|
|
551
555
|
};
|
|
552
556
|
const stopSpeaking = () => {
|
|
557
|
+
abortTTS();
|
|
553
558
|
if (animationState.value === "speak" || animationState.value === "speakLoop") {
|
|
554
559
|
runAnimation("speakEnd");
|
|
555
560
|
} else {
|
|
@@ -625,13 +630,44 @@ const _sfc_main = {
|
|
|
625
630
|
};
|
|
626
631
|
const currentAudio = vue.ref(null);
|
|
627
632
|
const currentTtsRequestId = vue.ref(null);
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
633
|
+
let ttsAbortController = null;
|
|
634
|
+
function abortTTS() {
|
|
635
|
+
currentTtsRequestId.value = null;
|
|
636
|
+
if (ttsAbortController) {
|
|
637
|
+
try {
|
|
638
|
+
ttsAbortController.abort();
|
|
639
|
+
} catch {
|
|
640
|
+
}
|
|
641
|
+
ttsAbortController = null;
|
|
642
|
+
}
|
|
631
643
|
if (currentAudio.value) {
|
|
632
|
-
|
|
644
|
+
try {
|
|
645
|
+
currentAudio.value.pause();
|
|
646
|
+
} catch {
|
|
647
|
+
}
|
|
633
648
|
currentAudio.value = null;
|
|
634
649
|
}
|
|
650
|
+
}
|
|
651
|
+
function waitWithSignal(ms, signal) {
|
|
652
|
+
return new Promise((resolve, reject) => {
|
|
653
|
+
if (signal == null ? void 0 : signal.aborted) {
|
|
654
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
const timer = setTimeout(resolve, ms);
|
|
658
|
+
const onAbort = () => {
|
|
659
|
+
clearTimeout(timer);
|
|
660
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
661
|
+
};
|
|
662
|
+
signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
const playTTS = async (text) => {
|
|
666
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
667
|
+
if (!text || !((_a = currentHuman.value) == null ? void 0 : _a.isMuted)) return;
|
|
668
|
+
abortTTS();
|
|
669
|
+
ttsAbortController = new AbortController();
|
|
670
|
+
const { signal } = ttsAbortController;
|
|
635
671
|
currentTtsRequestId.value = Date.now();
|
|
636
672
|
const requestId = currentTtsRequestId.value;
|
|
637
673
|
try {
|
|
@@ -647,7 +683,8 @@ const _sfc_main = {
|
|
|
647
683
|
const joinRes = await fetch(`${baseUrl}/gradio_api/queue/join`, {
|
|
648
684
|
method: "POST",
|
|
649
685
|
headers: { "Content-Type": "application/json" },
|
|
650
|
-
body: JSON.stringify({ data, session_hash: sessionHash, fn_index: 1, trigger_id: 50 })
|
|
686
|
+
body: JSON.stringify({ data, session_hash: sessionHash, fn_index: 1, trigger_id: 50 }),
|
|
687
|
+
signal
|
|
651
688
|
});
|
|
652
689
|
const joinData = await joinRes.json();
|
|
653
690
|
console.log("[OmniVoice] Step1 响应:", joinData);
|
|
@@ -656,10 +693,13 @@ const _sfc_main = {
|
|
|
656
693
|
let maxPolls = 60;
|
|
657
694
|
let pollInterval = 1e3;
|
|
658
695
|
while (!audioUrl && maxPolls > 0) {
|
|
659
|
-
|
|
696
|
+
if (signal.aborted || currentTtsRequestId.value !== requestId) return;
|
|
697
|
+
await waitWithSignal(pollInterval, signal);
|
|
660
698
|
maxPolls--;
|
|
661
699
|
try {
|
|
662
|
-
const pollRes = await fetch(`${baseUrl}/gradio_api/queue/data?session_hash=${sessionHash}
|
|
700
|
+
const pollRes = await fetch(`${baseUrl}/gradio_api/queue/data?session_hash=${sessionHash}`, {
|
|
701
|
+
signal
|
|
702
|
+
});
|
|
663
703
|
const pollText = await pollRes.text();
|
|
664
704
|
const lines = pollText.split("\n");
|
|
665
705
|
for (const line of lines) {
|
|
@@ -686,7 +726,7 @@ const _sfc_main = {
|
|
|
686
726
|
}
|
|
687
727
|
const wavBlob = createWavBlob(audioBuffer, samplingRate, 1, 16);
|
|
688
728
|
const audioObjectUrl = URL.createObjectURL(wavBlob);
|
|
689
|
-
if (currentTtsRequestId.value !== requestId) {
|
|
729
|
+
if (signal.aborted || currentTtsRequestId.value !== requestId) {
|
|
690
730
|
URL.revokeObjectURL(audioObjectUrl);
|
|
691
731
|
return;
|
|
692
732
|
}
|
|
@@ -722,16 +762,21 @@ const _sfc_main = {
|
|
|
722
762
|
}
|
|
723
763
|
}
|
|
724
764
|
} catch (e) {
|
|
765
|
+
if ((e == null ? void 0 : e.name) === "AbortError") throw e;
|
|
725
766
|
console.warn("[OmniVoice] 轮询失败:", e.message);
|
|
726
767
|
}
|
|
727
768
|
}
|
|
728
769
|
if (audioUrl) {
|
|
729
770
|
if (audioUrl.startsWith("/")) audioUrl = baseUrl + audioUrl;
|
|
730
771
|
console.log("[OmniVoice] 下载音频:", audioUrl);
|
|
731
|
-
if (currentTtsRequestId.value !== requestId) return;
|
|
732
|
-
const audioRes = await fetch(audioUrl);
|
|
772
|
+
if (signal.aborted || currentTtsRequestId.value !== requestId) return;
|
|
773
|
+
const audioRes = await fetch(audioUrl, { signal });
|
|
733
774
|
const audioBlob = await audioRes.blob();
|
|
734
775
|
const audioObjectUrl = URL.createObjectURL(audioBlob);
|
|
776
|
+
if (signal.aborted || currentTtsRequestId.value !== requestId) {
|
|
777
|
+
URL.revokeObjectURL(audioObjectUrl);
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
735
780
|
currentAudio.value = new Audio(audioObjectUrl);
|
|
736
781
|
currentAudio.value.onplaying = () => {
|
|
737
782
|
console.log("[OmniVoice] 音频开始播放");
|
|
@@ -755,6 +800,10 @@ const _sfc_main = {
|
|
|
755
800
|
standby();
|
|
756
801
|
}
|
|
757
802
|
} catch (e) {
|
|
803
|
+
if ((e == null ? void 0 : e.name) === "AbortError") {
|
|
804
|
+
console.log("[OmniVoice] TTS已取消");
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
758
807
|
console.error("[OmniVoice] TTS失败:", e);
|
|
759
808
|
standby();
|
|
760
809
|
}
|
|
@@ -866,6 +915,7 @@ const _sfc_main = {
|
|
|
866
915
|
init();
|
|
867
916
|
});
|
|
868
917
|
vue.onUnmounted(() => {
|
|
918
|
+
abortTTS();
|
|
869
919
|
stop();
|
|
870
920
|
if (recorder2.value) {
|
|
871
921
|
recorder2.value.stop();
|
|
@@ -885,7 +935,7 @@ const _sfc_main = {
|
|
|
885
935
|
};
|
|
886
936
|
}
|
|
887
937
|
};
|
|
888
|
-
const DigitalHuman = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
938
|
+
const DigitalHuman = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-90fb7a29"]]);
|
|
889
939
|
DigitalHuman.install = (app) => app.component("DigitalHuman", DigitalHuman);
|
|
890
940
|
const components = [DemoButton, DemoInput, DigitalHuman];
|
|
891
941
|
const install = (app) => {
|
package/dist/ruiyun-human.es.js
CHANGED
|
@@ -450,20 +450,24 @@ const _sfc_main = {
|
|
|
450
450
|
const y = canvas.height - height;
|
|
451
451
|
ctx.value.drawImage(image, x, y, width, height);
|
|
452
452
|
};
|
|
453
|
-
const stop = () => {
|
|
453
|
+
const stop = (keepAudio = false) => {
|
|
454
|
+
var _a;
|
|
454
455
|
if (animationId.value) {
|
|
455
456
|
cancelAnimationFrame(animationId.value);
|
|
456
457
|
animationId.value = null;
|
|
457
458
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
459
|
+
if (!keepAudio) {
|
|
460
|
+
try {
|
|
461
|
+
(_a = currentAudio.value) == null ? void 0 : _a.pause();
|
|
462
|
+
} catch (error) {
|
|
463
|
+
}
|
|
461
464
|
}
|
|
462
465
|
frameIndex.value = 1;
|
|
463
466
|
animationState.value = "standby";
|
|
464
467
|
};
|
|
465
468
|
const runAnimation = (state) => {
|
|
466
|
-
|
|
469
|
+
const keepAudio = state === "speak" || state === "speakLoop" || state === "speakEnd";
|
|
470
|
+
stop(keepAudio);
|
|
467
471
|
animationState.value = state;
|
|
468
472
|
loopDirection.value = 1;
|
|
469
473
|
let currentFrames;
|
|
@@ -548,6 +552,7 @@ const _sfc_main = {
|
|
|
548
552
|
runAnimation("speak");
|
|
549
553
|
};
|
|
550
554
|
const stopSpeaking = () => {
|
|
555
|
+
abortTTS();
|
|
551
556
|
if (animationState.value === "speak" || animationState.value === "speakLoop") {
|
|
552
557
|
runAnimation("speakEnd");
|
|
553
558
|
} else {
|
|
@@ -623,13 +628,44 @@ const _sfc_main = {
|
|
|
623
628
|
};
|
|
624
629
|
const currentAudio = ref(null);
|
|
625
630
|
const currentTtsRequestId = ref(null);
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
631
|
+
let ttsAbortController = null;
|
|
632
|
+
function abortTTS() {
|
|
633
|
+
currentTtsRequestId.value = null;
|
|
634
|
+
if (ttsAbortController) {
|
|
635
|
+
try {
|
|
636
|
+
ttsAbortController.abort();
|
|
637
|
+
} catch {
|
|
638
|
+
}
|
|
639
|
+
ttsAbortController = null;
|
|
640
|
+
}
|
|
629
641
|
if (currentAudio.value) {
|
|
630
|
-
|
|
642
|
+
try {
|
|
643
|
+
currentAudio.value.pause();
|
|
644
|
+
} catch {
|
|
645
|
+
}
|
|
631
646
|
currentAudio.value = null;
|
|
632
647
|
}
|
|
648
|
+
}
|
|
649
|
+
function waitWithSignal(ms, signal) {
|
|
650
|
+
return new Promise((resolve, reject) => {
|
|
651
|
+
if (signal == null ? void 0 : signal.aborted) {
|
|
652
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
const timer = setTimeout(resolve, ms);
|
|
656
|
+
const onAbort = () => {
|
|
657
|
+
clearTimeout(timer);
|
|
658
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
659
|
+
};
|
|
660
|
+
signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
const playTTS = async (text) => {
|
|
664
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
665
|
+
if (!text || !((_a = currentHuman.value) == null ? void 0 : _a.isMuted)) return;
|
|
666
|
+
abortTTS();
|
|
667
|
+
ttsAbortController = new AbortController();
|
|
668
|
+
const { signal } = ttsAbortController;
|
|
633
669
|
currentTtsRequestId.value = Date.now();
|
|
634
670
|
const requestId = currentTtsRequestId.value;
|
|
635
671
|
try {
|
|
@@ -645,7 +681,8 @@ const _sfc_main = {
|
|
|
645
681
|
const joinRes = await fetch(`${baseUrl}/gradio_api/queue/join`, {
|
|
646
682
|
method: "POST",
|
|
647
683
|
headers: { "Content-Type": "application/json" },
|
|
648
|
-
body: JSON.stringify({ data, session_hash: sessionHash, fn_index: 1, trigger_id: 50 })
|
|
684
|
+
body: JSON.stringify({ data, session_hash: sessionHash, fn_index: 1, trigger_id: 50 }),
|
|
685
|
+
signal
|
|
649
686
|
});
|
|
650
687
|
const joinData = await joinRes.json();
|
|
651
688
|
console.log("[OmniVoice] Step1 响应:", joinData);
|
|
@@ -654,10 +691,13 @@ const _sfc_main = {
|
|
|
654
691
|
let maxPolls = 60;
|
|
655
692
|
let pollInterval = 1e3;
|
|
656
693
|
while (!audioUrl && maxPolls > 0) {
|
|
657
|
-
|
|
694
|
+
if (signal.aborted || currentTtsRequestId.value !== requestId) return;
|
|
695
|
+
await waitWithSignal(pollInterval, signal);
|
|
658
696
|
maxPolls--;
|
|
659
697
|
try {
|
|
660
|
-
const pollRes = await fetch(`${baseUrl}/gradio_api/queue/data?session_hash=${sessionHash}
|
|
698
|
+
const pollRes = await fetch(`${baseUrl}/gradio_api/queue/data?session_hash=${sessionHash}`, {
|
|
699
|
+
signal
|
|
700
|
+
});
|
|
661
701
|
const pollText = await pollRes.text();
|
|
662
702
|
const lines = pollText.split("\n");
|
|
663
703
|
for (const line of lines) {
|
|
@@ -684,7 +724,7 @@ const _sfc_main = {
|
|
|
684
724
|
}
|
|
685
725
|
const wavBlob = createWavBlob(audioBuffer, samplingRate, 1, 16);
|
|
686
726
|
const audioObjectUrl = URL.createObjectURL(wavBlob);
|
|
687
|
-
if (currentTtsRequestId.value !== requestId) {
|
|
727
|
+
if (signal.aborted || currentTtsRequestId.value !== requestId) {
|
|
688
728
|
URL.revokeObjectURL(audioObjectUrl);
|
|
689
729
|
return;
|
|
690
730
|
}
|
|
@@ -720,16 +760,21 @@ const _sfc_main = {
|
|
|
720
760
|
}
|
|
721
761
|
}
|
|
722
762
|
} catch (e) {
|
|
763
|
+
if ((e == null ? void 0 : e.name) === "AbortError") throw e;
|
|
723
764
|
console.warn("[OmniVoice] 轮询失败:", e.message);
|
|
724
765
|
}
|
|
725
766
|
}
|
|
726
767
|
if (audioUrl) {
|
|
727
768
|
if (audioUrl.startsWith("/")) audioUrl = baseUrl + audioUrl;
|
|
728
769
|
console.log("[OmniVoice] 下载音频:", audioUrl);
|
|
729
|
-
if (currentTtsRequestId.value !== requestId) return;
|
|
730
|
-
const audioRes = await fetch(audioUrl);
|
|
770
|
+
if (signal.aborted || currentTtsRequestId.value !== requestId) return;
|
|
771
|
+
const audioRes = await fetch(audioUrl, { signal });
|
|
731
772
|
const audioBlob = await audioRes.blob();
|
|
732
773
|
const audioObjectUrl = URL.createObjectURL(audioBlob);
|
|
774
|
+
if (signal.aborted || currentTtsRequestId.value !== requestId) {
|
|
775
|
+
URL.revokeObjectURL(audioObjectUrl);
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
733
778
|
currentAudio.value = new Audio(audioObjectUrl);
|
|
734
779
|
currentAudio.value.onplaying = () => {
|
|
735
780
|
console.log("[OmniVoice] 音频开始播放");
|
|
@@ -753,6 +798,10 @@ const _sfc_main = {
|
|
|
753
798
|
standby();
|
|
754
799
|
}
|
|
755
800
|
} catch (e) {
|
|
801
|
+
if ((e == null ? void 0 : e.name) === "AbortError") {
|
|
802
|
+
console.log("[OmniVoice] TTS已取消");
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
756
805
|
console.error("[OmniVoice] TTS失败:", e);
|
|
757
806
|
standby();
|
|
758
807
|
}
|
|
@@ -864,6 +913,7 @@ const _sfc_main = {
|
|
|
864
913
|
init();
|
|
865
914
|
});
|
|
866
915
|
onUnmounted(() => {
|
|
916
|
+
abortTTS();
|
|
867
917
|
stop();
|
|
868
918
|
if (recorder2.value) {
|
|
869
919
|
recorder2.value.stop();
|
|
@@ -883,7 +933,7 @@ const _sfc_main = {
|
|
|
883
933
|
};
|
|
884
934
|
}
|
|
885
935
|
};
|
|
886
|
-
const DigitalHuman = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
936
|
+
const DigitalHuman = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-90fb7a29"]]);
|
|
887
937
|
DigitalHuman.install = (app) => app.component("DigitalHuman", DigitalHuman);
|
|
888
938
|
const components = [DemoButton, DemoInput, DigitalHuman];
|
|
889
939
|
const install = (app) => {
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.demo-btn[data-v-9a48516a]{padding:6px 14px;border-radius:4px;border:none;cursor:pointer;font-size:14px}.primary[data-v-9a48516a]{background:#409eff;color:#fff}.success[data-v-9a48516a]{background:#67c23a;color:#fff}.warning[data-v-9a48516a]{background:#e6a23c;color:#fff}.demo-input-wrap[data-v-28a3493c]{display:inline-flex;align-items:center;border:1px solid #dcdcdc;border-radius:4px;padding:0 10px}.demo-input-wrap[data-v-28a3493c]:focus-within{border-color:#409eff}.demo-input[data-v-28a3493c]{border:none;outline:none;padding:8px 6px;flex:1}.prefix[data-v-28a3493c],.suffix[data-v-28a3493c]{color:#909399}.digital-human[data-v-
|
|
1
|
+
.demo-btn[data-v-9a48516a]{padding:6px 14px;border-radius:4px;border:none;cursor:pointer;font-size:14px}.primary[data-v-9a48516a]{background:#409eff;color:#fff}.success[data-v-9a48516a]{background:#67c23a;color:#fff}.warning[data-v-9a48516a]{background:#e6a23c;color:#fff}.demo-input-wrap[data-v-28a3493c]{display:inline-flex;align-items:center;border:1px solid #dcdcdc;border-radius:4px;padding:0 10px}.demo-input-wrap[data-v-28a3493c]:focus-within{border-color:#409eff}.demo-input[data-v-28a3493c]{border:none;outline:none;padding:8px 6px;flex:1}.prefix[data-v-28a3493c],.suffix[data-v-28a3493c]{color:#909399}.digital-human[data-v-90fb7a29]{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.digital-human canvas[data-v-90fb7a29]{max-width:100%;max-height:100%}
|