@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.
@@ -1 +1 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./index.vue2.ts");;/* empty css */const t=require("../../../../../_virtual/_plugin-vue_export-helper.ts"),u=t.default(e.default,[["__scopeId","data-v-a14c8758"]]);exports.default=u;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./index.vue2.ts");;/* empty css */const t=require("../../../../../_virtual/_plugin-vue_export-helper.ts"),u=t.default(e.default,[["__scopeId","data-v-0e24153b"]]);exports.default=u;
@@ -1 +1 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),A=require("../../utils/api.ts"),ue=require("../../utils/utils.ts"),Ee=require("../../utils/videoBackgroundRemoval.ts"),ke={class:"digital-human-assistant"},Ve={class:"placeholder left-placeholder"},Te={class:"placeholder right-placeholder"},Se={class:"window-header-left"},Re={class:"window-title-text"},_e={class:"window-header-btns"},xe={class:"disconnect-btn"},Ce={class:"connect-btn",disabled:""},Ne={class:"connect-btn"},De={class:"window-content"},Me={class:"main-content-inner"},Le={class:"window-header-left"},He={class:"window-title-text"},We={class:"window-header-btns"},$e={class:"disconnect-btn"},Be={class:"connect-btn",disabled:""},Pe={class:"connect-btn"},Xe={class:"window-content"},Ye={class:"window-header-left"},Ie={class:"window-title-text"},Oe={class:"window-header-btns"},je={class:"disconnect-btn"},ze={class:"connect-btn",disabled:""},Ue={class:"connect-btn"},Fe={class:"window-content"},qe=e.defineComponent({name:"SjDigitalHumanAssistant"}),Ae=e.defineComponent({...qe,props:{windowWidth:{default:320},windowHeight:{default:467},windowTitle:{default:"数字人助手"},sidebarWidth:{default:"25%"},sidebarLeftTitle:{default:"左侧业务区"},sidebarRightTitle:{default:"右侧业务区"},edgeThreshold:{default:10},dragThreshold:{default:8},defaultStickSide:{default:""},defaultPlayText:{default:""},reconnectInterval:{default:5},maxReconnectTimes:{default:10},baseUrl:{default:""}},setup(C,{expose:ve}){const o=C,G=e.ref(null),J=e.ref(null),d=e.ref(null),a=e.ref(null),f=Ee.default(),K=e.ref(null),Q=e.ref(null),Z=e.ref(null),N=e.ref(null),V=e.ref(!1),c=e.ref(!1),v=e.ref(!1),ee=e.ref(!0),D=e.ref(!1),r=e.reactive({x:0,y:0,offsetX:0,offsetY:0}),u=e.ref(o.defaultStickSide),M=e.ref(!1),g=e.ref(!1),T=e.ref(!1),Y=e.ref(!1),I=e.ref(!1);let s=null,m="";const L=e.ref(null),w=e.ref(0),H=e.ref(!1),S=e.ref(!1),he=e.computed(()=>({"--sidebar-width":o.sidebarWidth,"--window-width":`${o.windowWidth}px`,"--window-height":`${o.windowHeight}px`})),fe=e.computed(()=>({left:`${r.x}px`,top:`${r.y}px`,width:`${o.windowWidth}px`,height:`${o.windowHeight}px`,zIndex:M.value||T.value?9999:1e3})),me=n=>{!n&&d.value?(H.value=!1,w.value=0,se()):n?(H.value=!0,be()):console.warn("自动连接超时:video元素未挂载"),ee.value=n},W=n=>{me(!n),D.value=n,n&&c.value&&e.nextTick(()=>h())},we=()=>{W(!0)},te=()=>{switch(u.value){case"left":return Q.value??N.value;case"right":return Z.value??N.value;default:return K.value??N.value}},E=()=>J.value?.getBoundingClientRect()||{width:0,height:0,left:0,right:0,top:0,bottom:0},ne=()=>G.value?.getBoundingClientRect()||{width:0,height:0,left:0,right:0,top:0,bottom:0},O=(n,t)=>{const i=E();return{x:Math.max(0,Math.min(n,i.width-o.windowWidth)),y:Math.max(0,Math.min(t,i.height-o.windowHeight))}},oe=()=>{const n=E(),t=n.width-o.windowWidth-10,i=n.height-o.windowHeight-10;return O(t,i)},ae=()=>{const n=E(),t=ne();Y.value=t.left<=n.left+o.edgeThreshold,I.value=t.right>=n.right-o.edgeThreshold},ie=()=>{const n=E(),t=ne(),i=t.left<=n.left+o.edgeThreshold?"left":t.right>=n.right-o.edgeThreshold?"right":"";i!==u.value&&(u.value=i,d.value&&(d.value.volume=i?.5:1),_(),h()),Y.value=I.value=!1},ge=n=>{M.value=!0,r.offsetX=n.clientX-r.x,r.offsetY=n.clientY-r.y,document.addEventListener("mousemove",j),document.addEventListener("mouseup",z)},j=n=>{if(!M.value)return;const t=E(),{x:i,y:l}=O(n.clientX-t.left-r.offsetX,n.clientY-t.top-r.offsetY);r.x=i,r.y=l,ae()},z=()=>{ie(),M.value=!1,document.removeEventListener("mousemove",j),document.removeEventListener("mouseup",z)},le=(n,t)=>{g.value=!0,r.offsetX=t.clientX-(t.clientX-o.windowWidth/2),r.offsetY=t.clientY-(t.clientY-20),document.addEventListener("mousemove",$)},$=n=>{if(!g.value)return;const t=Math.abs(n.movementX),i=Math.abs(n.movementY);(t>o.dragThreshold||i>o.dragThreshold)&&(T.value=!0,u.value="",document.removeEventListener("mousemove",$),document.addEventListener("mousemove",U),document.addEventListener("mouseup",F))},U=n=>{if(!T.value)return;const t=E(),{x:i,y:l}=O(n.clientX-t.left-r.offsetX,n.clientY-t.top-r.offsetY);r.x=i,r.y=l,ae()},F=()=>{ie(),g.value=T.value=!1,document.removeEventListener("mousemove",U),document.removeEventListener("mouseup",F)},B=()=>{g.value&&!T.value&&(g.value=!1,document.removeEventListener("mousemove",$))},q=async n=>{if(!c.value||!m)return;console.log("已打断当前对话,准备播放新文本:",n);const t={text:n,type:"echo",interrupt:!0,sessionid:parseInt(m)};A.default.digitalHumanChat(o.baseUrl,t).then(i=>{i&&Number(i.code)}).catch(i=>{console.log("api.digitalHumanChat:",i)})},R=async()=>{if(!c.value||!m)return;const n={sessionid:parseInt(m)};A.default.digitalHumanInterruptTalk(o.baseUrl,n).then(t=>{t&&Number(t.code)===0&&console.log("数字人对话已成功打断")}).catch(t=>{console.log("api.digitalHumanInterruptTalk:",t)})},k=()=>{L.value&&(clearTimeout(L.value),L.value=null,console.log("重连定时器已清除")),S.value=!1},_=(n=!1)=>{if(!a.value)return;n||f.stopProcessing();const t=a.value.getContext("2d");if(t&&(t.clearRect(0,0,a.value.width,a.value.height),!n)){const i=a.value.width,l=a.value.height;a.value.width=i,a.value.height=l}a.value&&!n&&(a.value.style.width="",a.value.style.height="",u.value===""&&(a.value.style.marginLeft="",a.value.style.marginTop=""))},h=async(n=!1)=>{if(!d.value||!a.value||!V.value||!c.value)return;await e.nextTick();const t=d.value.videoWidth||o.windowWidth,i=d.value.videoHeight||o.windowHeight,l=t/i;console.log("视频原始宽高比:",l,"尺寸:",t,i);let p;const de=te();de?p=de.getBoundingClientRect():p={width:u.value?0:o.windowWidth,height:u.value?0:o.windowHeight,left:0,top:0,right:0,bottom:0};const P=p.width||(u.value?300:o.windowWidth),X=p.height||(u.value?window.innerHeight-40:o.windowHeight),ye=P/X;let b,y;ye>l?(y=X,b=y*l):(b=P,y=b/l);const re=window.devicePixelRatio||1;a.value.width=Math.floor(b*re),a.value.height=Math.floor(y*re),a.value.style.display="block",a.value.style.objectFit="contain",u.value===""?(a.value.style.width=`${b}px`,a.value.style.height=`${y}px`,a.value.style.marginLeft=`${(P-b)/2}px`,a.value.style.marginTop=`${(X-y)/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适配完成:",{mode:u.value||"浮动",container:{width:P,height:X},canvas:{drawWidth:b,drawHeight:y,physicalWidth:a.value.width,physicalHeight:a.value.height}}),n||(f.videoRef.value=d.value,f.canvasRef.value=a.value,await f.processVideo())},x=()=>{if(H.value||c.value||v.value||S.value){console.log("重连条件不满足:手动断开/已连接/正在连接/正在冷却");return}if(R().then(()=>{console.log("重连前已打断当前对话")}),o.maxReconnectTimes!==-1&&w.value>=o.maxReconnectTimes){console.warn(`数字人重连已达最大次数(${o.maxReconnectTimes}),停止重连`),k(),ue.default.funcElMessageShowCtrl(`数字人连接失败,已尝试${o.maxReconnectTimes}次重连,请重试!`),w.value=0;return}S.value=!0,L.value=setTimeout(()=>{try{w.value++,console.log(`数字人第${w.value}次重连... (最大次数:${o.maxReconnectTimes})`),se()}finally{S.value=!1}},o.reconnectInterval*1e3)},pe=async()=>{if(s)try{s.addTransceiver("video",{direction:"recvonly"}),s.addTransceiver("audio",{direction:"recvonly"});const n=await s.createOffer();await s.setLocalDescription(n),await new Promise(l=>{if(s?.iceGatheringState==="complete")l();else{const p=()=>{s?.iceGatheringState==="complete"&&(s?.removeEventListener("icegatheringstatechange",p),l())};s?.addEventListener("icegatheringstatechange",p)}});const t=s.localDescription,i={sdp:t.sdp,type:t.type};A.default.digitalHumanOffer(o.baseUrl,i).then(l=>{l?(m=l.sessionid,s.setRemoteDescription(new RTCSessionDescription(l)),c.value=!0,w.value=0,k(),console.log("数字人连接成功,重置重连状态"),e.nextTick(()=>h())):(c.value=!1,console.log("数字人连接失败:接口返回空"),x()),v.value=!1}).catch(l=>{console.error("api.digitalHumanOffer 失败:",l),c.value=!1,v.value=!1,x()})}catch(n){console.error("negotiate 失败:",n),c.value=!1,v.value=!1,x()}},se=()=>{if(c.value||v.value){console.log("当前已连接/正在连接,无需重复触发");return}v.value=!0,console.log("开始建立数字人连接...");const n={sdpSemantics:"unified-plan"};s&&(s.close(),s=null),s=new RTCPeerConnection(n),s.addEventListener("track",t=>{t.track.kind==="video"&&d.value&&(d.value.srcObject=t.streams[0],d.value.onloadedmetadata=async()=>{d.value&&a.value&&(f.videoRef.value=d.value,f.canvasRef.value=a.value,await h(),await f.processVideo())},d.value.onresize=()=>{h()})}),s.addEventListener("iceconnectionstatechange",()=>{switch(console.log("ICE连接状态变化:",s.iceConnectionState),s.iceConnectionState){case"disconnected":case"failed":case"closed":console.log("WebRTC连接断开/失败,触发重连"),c.value=!1,v.value=!1,s=null,m="",d.value&&(d.value.srcObject=null),_(),R().then(()=>{console.log("ICE连接断开,已打断对话")}),x();break;case"connected":w.value=0,k(),console.log("ICE连接成功,重置重连状态"),e.nextTick(()=>h());break}}),pe()},be=()=>{H.value=!0,k(),v.value=!1,f.stopProcessing(),_(),R().then(()=>{console.log("手动断开连接,已打断当前对话")}),setTimeout(()=>{s&&(s.close(),s=null),m="",d.value&&(d.value.srcObject=null),c.value=!1,w.value=0,console.log("手动断开连接,重置所有状态")},500)};ve({digitalHumanChat:q,digitalHumanInterruptTalk:R,isConnected:c,isConnecting:v,reconnect:x,clearReconnectTimer:k,currentReconnectTimes:w,isWaitingReconnect:S,adaptCanvasToContainer:h}),e.watch(u,async(n,t)=>{!V.value||!d.value||(await e.nextTick(),d.value.volume=n?.5:1,c.value&&(_(),await h()))},{immediate:!0,deep:!0}),e.watch([()=>c.value,()=>o.defaultPlayText],async([n,t],[i])=>{n&&!i&&t&&m&&(console.log("连接成功,自动播放默认文本:",t),await q(t),e.nextTick(()=>h()))},{immediate:!1}),e.watch(()=>o.defaultPlayText,async n=>{c.value&&n&&m&&(console.log("默认文本加载完成,自动播放:",n),await q(n),e.nextTick(()=>h()))},{immediate:!0}),e.onMounted(async()=>{await e.nextTick(),await e.nextTick(),V.value=!0;const{x:n,y:t}=oe();r.x=n,r.y=t,window.addEventListener("resize",ce)});const ce=ue.default.debounce(()=>{if(u.value===""){const{x:n,y:t}=oe();r.x=n,r.y=t}c.value&&V.value&&(_(!0),e.nextTick(()=>h(!0)))},50);return e.onUnmounted(()=>{R().then(()=>{console.log("组件卸载,已打断当前对话")}),document.removeEventListener("mousemove",$),document.removeEventListener("mousemove",U),document.removeEventListener("mouseup",F),document.removeEventListener("mousemove",j),document.removeEventListener("mouseup",z),window.removeEventListener("resize",ce),k(),f.stopProcessing(),d.value&&(d.value.srcObject=null),s&&s.close()}),(n,t)=>{const i=e.resolveDirective("drag");return e.openBlock(),e.createElementBlock("div",{class:"draggable-window-container",style:e.normalizeStyle(he.value)},[e.withDirectives(e.createElementVNode("div",ke,null,512),[[e.vShow,ee.value],[i,["digital-human-assistant",we,!0]]]),e.createElementVNode("div",{ref_key:"teleportFallbackRef",ref:N,class:"teleport-fallback"},null,512),e.withDirectives(e.createElementVNode("div",Ve,null,512),[[e.vShow,Y.value]]),e.withDirectives(e.createElementVNode("div",Te,null,512),[[e.vShow,I.value]]),D.value&&u.value==="left"?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["sidebar left-sidebar",{pressing:g.value}])},[e.createElementVNode("div",{class:"window-header",onMousedown:t[2]||(t[2]=l=>le("left",l)),onMouseup:B,onMouseleave:B},[e.createElementVNode("div",Se,[e.createElementVNode("span",Re,e.toDisplayString(C.windowTitle),1),e.createElementVNode("div",_e,[e.withDirectives(e.createElementVNode("button",xe,"未连接",512),[[e.vShow,!c.value&&!v.value]]),e.withDirectives(e.createElementVNode("button",Ce,"连接中...",512),[[e.vShow,v.value]]),e.withDirectives(e.createElementVNode("button",Ne,"已连接",512),[[e.vShow,c.value]])])]),e.createElementVNode("div",{class:"drag-window-hide",onClick:t[0]||(t[0]=l=>W(!1)),onMousedown:t[1]||(t[1]=e.withModifiers(()=>{},["stop"]))},null,32)],32),e.createElementVNode("div",De,[e.renderSlot(n.$slots,"sidebar-left",{},void 0,!0),e.createElementVNode("div",{ref_key:"sidebarLeftVideoRef",ref:Q,class:"sidebar-video-container"},null,512)])],2)):e.createCommentVNode("",!0),e.createElementVNode("div",{class:"main-content-outer",ref_key:"containerRef",ref:J},[e.createElementVNode("div",Me,[e.renderSlot(n.$slots,"main",{},void 0,!0)]),D.value&&u.value===""?(e.openBlock(),e.createElementBlock("div",{key:0,ref_key:"dragWindowRef",ref:G,class:"draggable-window",style:e.normalizeStyle(fe.value)},[e.createElementVNode("div",{class:"window-header",onMousedown:ge},[e.createElementVNode("div",Le,[e.createElementVNode("span",He,e.toDisplayString(C.windowTitle),1),e.createElementVNode("div",We,[e.withDirectives(e.createElementVNode("button",$e,"未连接",512),[[e.vShow,!c.value&&!v.value]]),e.withDirectives(e.createElementVNode("button",Be,"连接中...",512),[[e.vShow,v.value]]),e.withDirectives(e.createElementVNode("button",Pe,"已连接",512),[[e.vShow,c.value]])])]),e.createElementVNode("div",{class:"drag-window-hide",onClick:t[3]||(t[3]=l=>W(!1)),onMousedown:t[4]||(t[4]=e.withModifiers(()=>{},["stop"]))},null,32)],32),e.createElementVNode("div",Xe,[e.createElementVNode("div",{class:"video-container",ref_key:"windowVideoRef",ref:K},null,512)])],4)):e.createCommentVNode("",!0)],512),D.value&&u.value==="right"?(e.openBlock(),e.createElementBlock("div",{key:1,class:e.normalizeClass(["sidebar right-sidebar",{pressing:g.value}])},[e.createElementVNode("div",{class:"window-header",onMousedown:t[7]||(t[7]=l=>le("right",l)),onMouseup:B,onMouseleave:B},[e.createElementVNode("div",Ye,[e.createElementVNode("span",Ie,e.toDisplayString(C.windowTitle),1),e.createElementVNode("div",Oe,[e.withDirectives(e.createElementVNode("button",je,"未连接",512),[[e.vShow,!c.value&&!v.value]]),e.withDirectives(e.createElementVNode("button",ze,"连接中...",512),[[e.vShow,v.value]]),e.withDirectives(e.createElementVNode("button",Ue,"已连接",512),[[e.vShow,c.value]])])]),e.createElementVNode("div",{class:"drag-window-hide",onClick:t[5]||(t[5]=l=>W(!1)),onMousedown:t[6]||(t[6]=e.withModifiers(()=>{},["stop"]))},null,32)],32),e.createElementVNode("div",Fe,[e.renderSlot(n.$slots,"sidebar-right",{},void 0,!0),e.createElementVNode("div",{ref_key:"sidebarRightVideoRef",ref:Z,class:"sidebar-video-container"},null,512)])],2)):e.createCommentVNode("",!0),V.value?(e.openBlock(),e.createBlock(e.Teleport,{key:2,to:te()},[e.createElementVNode("video",{ref_key:"digitalHumanVideo",ref:d,class:"digital-video source-video",poster:"",playsinline:"",autoplay:""},null,512),e.createElementVNode("canvas",{ref_key:"processedCanvas",ref:a,class:"digital-video processed-canvas"},null,512)],8,["to"])):e.createCommentVNode("",!0)],4)}}});exports.default=Ae;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),J=require("../../utils/api.ts"),Y=require("../../utils/utils.ts"),Ve=require("../../utils/videoBackgroundRemoval.ts"),Ce={class:"digital-human-assistant"},Re={class:"placeholder left-placeholder"},Te={class:"placeholder right-placeholder"},_e={class:"window-header-left"},Ne={class:"window-title-text"},We={class:"window-header-btns"},xe={class:"disconnect-btn"},Me={class:"connect-btn",disabled:""},De={class:"connect-btn"},Le={class:"window-content"},He={class:"main-content-inner"},Ie={class:"window-header-left"},Pe={class:"window-title-text"},Be={class:"window-header-btns"},$e={class:"disconnect-btn"},Xe={class:"connect-btn",disabled:""},Ye={class:"connect-btn"},Ue={class:"window-content"},ze={class:"window-header-left"},Oe={class:"window-title-text"},je={class:"window-header-btns"},Ge={class:"disconnect-btn"},Fe={class:"connect-btn",disabled:""},qe={class:"connect-btn"},Ae={class:"window-content"},Je={key:0,class:"digital-video-loading"},Ke=e.defineComponent({name:"SjDigitalHumanAssistant"}),Qe=e.defineComponent({...Ke,props:{windowWidth:{default:320},windowHeight:{default:467},windowTitle:{default:"数字人助手"},sidebarWidth:{default:"25%"},sidebarBgColor:{default:"#ffffff"},edgeThreshold:{default:10},dragThreshold:{default:8},defaultStickSide:{default:""},defaultPlayText:{default:""},reconnectInterval:{default:5},maxReconnectTimes:{default:10},baseUrl:{default:""}},setup(N,{expose:fe}){e.useCssVars(t=>({v4920a482:t.sidebarBgColor}));const a=N,K=e.ref(null),Q=e.ref(null),l=e.ref(null),o=e.ref(null),Z=e.ref(null),ee=e.ref(null),te=e.ref(null),W=e.ref(null),r=Ve.default(),S=e.ref(!1),s=e.ref(!1),v=e.ref(!1),k=e.ref(!1),ne=e.ref(!0),x=e.ref(!1),f=e.ref(a.defaultStickSide),M=e.ref(!1),g=e.ref(!1),V=e.ref(!1),U=e.ref(!1),z=e.ref(!1);let d=null,h="";const D=e.ref(null),w=e.ref(0),L=e.ref(!1),C=e.ref(!1),u=e.reactive({x:0,y:0,offsetX:0,offsetY:0}),he=e.computed(()=>({"--sidebar-width":a.sidebarWidth,"--window-width":`${a.windowWidth}px`,"--window-height":`${a.windowHeight}px`})),we=e.computed(()=>({left:`${u.x}px`,top:`${u.y}px`,width:`${a.windowWidth}px`,height:`${a.windowHeight}px`,zIndex:M.value||V.value?9999:1e3})),me=t=>{!t&&l.value?(L.value=!1,w.value=0,de()):t?(L.value=!0,Se()):console.warn("❌ 自动连接超时:video元素未挂载"),ne.value=t},H=t=>{me(!t),x.value=t,t&&s.value?e.nextTick(()=>m()):t||(k.value=!1)},ge=()=>{H(!0)},oe=()=>{switch(f.value){case"left":return ee.value??W.value;case"right":return te.value??W.value;default:return Z.value??W.value}},I=()=>Q.value?.getBoundingClientRect()||{width:0,height:0,left:0,right:0,top:0,bottom:0},ae=()=>K.value?.getBoundingClientRect()||{width:0,height:0,left:0,right:0,top:0,bottom:0},O=(t,n)=>{const c=window.innerWidth||document.documentElement.clientWidth,i=window.innerHeight||document.documentElement.clientHeight;return{x:Math.max(0,Math.min(t,c-a.windowWidth)),y:Math.max(0,Math.min(n,i-a.windowHeight))}},ie=()=>{const t=window.innerWidth||document.documentElement.clientWidth,n=window.innerHeight||document.documentElement.clientHeight,c=t-a.windowWidth-10,i=n-a.windowHeight-10;return O(c,i)},le=()=>{const t=I(),n=ae();U.value=n.left<=t.left+a.edgeThreshold,z.value=n.right>=t.right-a.edgeThreshold},se=()=>{const t=I(),n=ae(),c=n.left<=t.left+a.edgeThreshold?"left":n.right>=t.right-a.edgeThreshold?"right":"";c!==f.value&&(f.value=c,l.value&&(l.value.volume=c?.5:1),T(),m()),U.value=z.value=!1},pe=()=>{k.value=!0},be=()=>{k.value=!1},ye=t=>{M.value=!0,u.offsetX=t.clientX-u.x,u.offsetY=t.clientY-u.y,document.addEventListener("mousemove",j),document.addEventListener("mouseup",G)},j=t=>{if(!M.value)return;const n=I(),{x:c,y:i}=O(t.clientX-n.left-u.offsetX,t.clientY-n.top-u.offsetY);u.x=c,u.y=i,le()},G=()=>{se(),M.value=!1,document.removeEventListener("mousemove",j),document.removeEventListener("mouseup",G)},ce=(t,n)=>{g.value=!0,u.offsetX=n.clientX-(n.clientX-a.windowWidth/2),u.offsetY=n.clientY-(n.clientY-20),document.addEventListener("mousemove",P)},P=t=>{if(!g.value)return;const n=Math.abs(t.movementX),c=Math.abs(t.movementY);(n>a.dragThreshold||c>a.dragThreshold)&&(V.value=!0,f.value="",document.removeEventListener("mousemove",P),document.addEventListener("mousemove",F),document.addEventListener("mouseup",q))},F=t=>{if(!V.value)return;const n=I(),{x:c,y:i}=O(t.clientX-n.left-u.offsetX,t.clientY-n.top-u.offsetY);u.x=c,u.y=i,le()},q=()=>{se(),g.value=V.value=!1,document.removeEventListener("mousemove",F),document.removeEventListener("mouseup",q)},B=()=>{g.value&&!V.value&&(g.value=!1,document.removeEventListener("mousemove",P))},A=async t=>{if(!s.value||!h)return;console.log("✅ 准备播放文本:",t);const n={text:t,type:"echo",interrupt:!0,sessionid:parseInt(h)};J.default.digitalHumanChat(a.baseUrl,n).then(c=>{c&&Number(c.code)===0&&console.log("✅ 播放指令发送成功")}).catch(c=>{console.error("❌ 播放指令发送失败:",c)})},R=async()=>{if(!s.value||!h)return;const t={sessionid:parseInt(h)};J.default.digitalHumanInterruptTalk(a.baseUrl,t).then(n=>{n&&Number(n.code)===0&&console.log("✅ 对话已打断")}).catch(n=>{console.error("❌ 打断对话失败:",n)})},E=()=>{D.value&&(clearTimeout(D.value),D.value=null),C.value=!1,console.log("✅ 重连定时器已清除")},T=(t=!1)=>{if(!o.value)return;t||r.stopProcessing();const n=o.value.getContext("2d");if(n&&(n.clearRect(0,0,o.value.width,o.value.height),!t)){const c=o.value.width,i=o.value.height;o.value.width=c,o.value.height=i}o.value&&!t&&(o.value.style.width="",o.value.style.height="",f.value===""&&(o.value.style.marginLeft="",o.value.style.marginTop=""))},m=async(t=!1)=>{if(!l.value||!o.value||!S.value||!s.value)return;await e.nextTick();const n=l.value.videoWidth||a.windowWidth,c=l.value.videoHeight||a.windowHeight,i=n/c;let p;const ue=oe();ue?p=ue.getBoundingClientRect():p={width:0,height:0,left:0,top:0,right:0,bottom:0};const $=p.width||(f.value?300:a.windowWidth),X=p.height||(f.value?window.innerHeight-40:a.windowHeight),ke=$/X;let b,y;ke>i?(y=X,b=y*i):(b=$,y=b/i);const ve=window.devicePixelRatio||1;o.value.width=Math.floor(b*ve),o.value.height=Math.floor(y*ve),o.value.style.display="block",o.value.style.objectFit="contain",f.value===""?(o.value.style.width=`${b}px`,o.value.style.height=`${y}px`,o.value.style.marginLeft=`${($-b)/2}px`,o.value.style.marginTop=`${(X-y)/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适配完成:",{mode:f.value||"浮动",container:{width:$,height:X},canvas:{drawWidth:b,drawHeight:y}}),t||(r.videoRef.value=l.value,r.canvasRef.value=o.value,await r.processVideo()),!r.isInitSuccess.value&&s.value&&(console.log("🔄 检测到WebGPU未初始化,触发手动重连"),await r.reInitWebGPU()&&await r.processVideo())},_=()=>{if(L.value||s.value||v.value||C.value){console.log("🚫 重连条件不满足");return}if(R(),a.maxReconnectTimes!==-1&&w.value>=a.maxReconnectTimes){console.warn(`🚫 重连已达最大次数(${a.maxReconnectTimes})`),E(),Y.default.funcElMessageShowCtrl(`❌ 数字人连接失败,已尝试${a.maxReconnectTimes}次重连,请重试!`,"error"),w.value=0;return}C.value=!0,D.value=setTimeout(()=>{try{w.value++,console.log(`🔄 第${w.value}次重连WebRTC...`),r.stopProcessing(),de()}finally{C.value=!1}},a.reconnectInterval*1e3)},Ee=async()=>{if(d)try{d.addTransceiver("video",{direction:"recvonly"}),d.addTransceiver("audio",{direction:"recvonly"});const t=await d.createOffer();await d.setLocalDescription(t),await new Promise(i=>{if(d?.iceGatheringState==="complete")i();else{const p=()=>{d?.iceGatheringState==="complete"&&(d?.removeEventListener("icegatheringstatechange",p),i())};d?.addEventListener("icegatheringstatechange",p)}});const n=d.localDescription,c={sdp:n.sdp,type:n.type};J.default.digitalHumanOffer(a.baseUrl,c).then(i=>{i?(h=i.sessionid,d.setRemoteDescription(new RTCSessionDescription(i)),s.value=!0,w.value=0,E(),console.log("✅ WebRTC连接成功"),e.nextTick(()=>m())):(s.value=!1,console.log("❌ WebRTC连接失败:接口返回空"),_()),v.value=!1}).catch(i=>{console.error("❌ WebRTC Offer发送失败:",i),s.value=!1,v.value=!1,_()})}catch(t){console.error("❌ WebRTC协商失败:",t),s.value=!1,v.value=!1,_()}},de=()=>{if(s.value||v.value)return;v.value=!0,console.log("🔄 开始建立WebRTC连接..."),d&&(d.close(),d=null);const t={sdpSemantics:"unified-plan"};d=new RTCPeerConnection(t),d.addEventListener("track",n=>{n.track.kind==="video"&&l.value&&(l.value.srcObject=n.streams[0],l.value.onloadedmetadata=async()=>{l.value&&o.value&&(r.videoRef.value=l.value,r.canvasRef.value=o.value,await m(),await r.processVideo())},l.value.onresize=()=>{m(!0)})}),d.addEventListener("iceconnectionstatechange",()=>{switch(console.log("📶 ICE状态变化:",d.iceConnectionState),d.iceConnectionState){case"disconnected":case"failed":case"closed":console.log("📶 ICE连接断开,触发重连"),s.value=!1,v.value=!1,d=null,h="",l.value&&(l.value.srcObject=null),T(),R(),_();break;case"connected":console.log("📶 ICE连接成功"),w.value=0,E(),e.nextTick(async()=>{!r.isInitSuccess.value&&s.value&&await r.reInitWebGPU()&&await r.processVideo()});break}}),Ee()},Se=()=>{L.value=!0,E(),v.value=!1,r.stopProcessing(),T(),R().then(()=>{setTimeout(()=>{d&&(d.close(),d=null),h="",l.value&&(l.value.srcObject=null),s.value=!1,w.value=0,console.log("✅ 手动断开连接,资源已清理")},500)})},re=Y.default.debounce(()=>{if(f.value===""){const{x:t,y:n}=ie();u.x=t,u.y=n}s.value&&S.value&&(T(!0),e.nextTick(()=>m(!0)))},50);return e.watch(r.isInitSuccess,t=>{!t&&v.value&&Y.default.funcElMessageShowCtrl("🔄 WebGPU初始化失败,正在尝试重连...","warning")},{immediate:!0}),e.watch([()=>r.isInitSuccess,()=>s.value],async([t,n])=>{!t&&n&&l.value&&o.value?(o.value.style.display="none",l.value.style.opacity="1",l.value.style.width="100%",l.value.style.height="100%",Y.default.funcElMessageShowCtrl("ℹ️ 当前浏览器不支持WebGPU,将显示原始视频(无透明背景)","info")):t&&n&&l.value&&o.value&&(o.value.style.display="block",l.value.style.opacity="0")},{immediate:!0}),e.watch(f,async t=>{!S.value||!l.value||(await e.nextTick(),l.value.volume=t?.5:1,s.value&&(T(),await m()))},{immediate:!0,deep:!0}),e.watch([()=>s.value,()=>a.defaultPlayText],async([t,n],[c])=>{t&&!c&&n&&h&&(console.log("✅ 连接成功,自动播放默认文本:",n),await A(n))},{immediate:!1}),e.watch(()=>a.defaultPlayText,async t=>{s.value&&t&&h&&(console.log("✅ 默认文本更新,自动播放:",t),await A(t))},{immediate:!0}),e.onMounted(async()=>{await e.nextTick(),await e.nextTick(),S.value=!0;const{x:t,y:n}=ie();u.x=t,u.y=n,window.addEventListener("resize",re)}),e.onUnmounted(()=>{document.removeEventListener("mousemove",P),document.removeEventListener("mousemove",F),document.removeEventListener("mouseup",q),document.removeEventListener("mousemove",j),document.removeEventListener("mouseup",G),window.removeEventListener("resize",re),E(),r.stopProcessing(),R(),d&&d.close(),l.value&&(l.value.srcObject=null)}),fe({digitalHumanChat:A,digitalHumanInterruptTalk:R,isConnected:s,isConnecting:v,reconnect:_,clearReconnectTimer:E,currentReconnectTimes:w,isWaitingReconnect:C,adaptCanvasToContainer:m,webgpuReInit:r.reInitWebGPU,webgpuIsInitSuccess:r.isInitSuccess,webgpuIsProcessing:r.isProcessing}),(t,n)=>{const c=e.resolveDirective("drag");return e.openBlock(),e.createElementBlock("div",{class:"draggable-window-container",style:e.normalizeStyle(he.value)},[e.withDirectives(e.createElementVNode("div",Ce,null,512),[[e.vShow,ne.value],[c,["digital-human-assistant",ge,!0]]]),e.createElementVNode("div",{ref_key:"teleportFallbackRef",ref:W,class:"teleport-fallback"},null,512),e.withDirectives(e.createElementVNode("div",Re,null,512),[[e.vShow,U.value]]),e.withDirectives(e.createElementVNode("div",Te,null,512),[[e.vShow,z.value]]),x.value&&f.value==="left"?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["sidebar left-sidebar",{pressing:g.value}])},[e.createElementVNode("div",{class:"window-header",onMousedown:n[2]||(n[2]=i=>ce("left",i)),onMouseup:B,onMouseleave:B},[e.createElementVNode("div",_e,[e.createElementVNode("span",Ne,e.toDisplayString(N.windowTitle),1),e.createElementVNode("div",We,[e.withDirectives(e.createElementVNode("button",xe,"未连接",512),[[e.vShow,!s.value&&!v.value]]),e.withDirectives(e.createElementVNode("button",Me,"连接中...",512),[[e.vShow,v.value]]),e.withDirectives(e.createElementVNode("button",De,"已连接",512),[[e.vShow,s.value]])])]),e.createElementVNode("div",{class:"drag-window-hide",onClick:n[0]||(n[0]=i=>H(!1)),onMousedown:n[1]||(n[1]=e.withModifiers(()=>{},["stop"]))},null,32)],32),e.createElementVNode("div",Le,[e.renderSlot(t.$slots,"sidebar-left",{},void 0,!0),e.createElementVNode("div",{ref_key:"sidebarLeftVideoRef",ref:ee,class:"sidebar-video-container"},null,512)])],2)):e.createCommentVNode("",!0),e.createElementVNode("div",{class:"main-content-outer",ref_key:"containerRef",ref:Q},[e.createElementVNode("div",He,[e.renderSlot(t.$slots,"main",{},void 0,!0)]),x.value&&f.value===""?(e.openBlock(),e.createElementBlock("div",{key:0,ref_key:"dragWindowRef",ref:K,class:e.normalizeClass(["draggable-window",{"draggable-window-shadow":!s.value||k.value}]),style:e.normalizeStyle(we.value),onMouseenter:pe,onMouseleave:be},[e.createElementVNode("div",{class:e.normalizeClass(["window-header",{"window-header-opacity":s.value&&!k.value}]),onMousedown:ye},[e.createElementVNode("div",Ie,[e.createElementVNode("span",Pe,e.toDisplayString(N.windowTitle),1),e.createElementVNode("div",Be,[e.withDirectives(e.createElementVNode("button",$e,"未连接",512),[[e.vShow,!s.value&&!v.value]]),e.withDirectives(e.createElementVNode("button",Xe,"连接中...",512),[[e.vShow,v.value]]),e.withDirectives(e.createElementVNode("button",Ye,"已连接",512),[[e.vShow,s.value]])])]),e.createElementVNode("div",{class:"drag-window-hide",onClick:n[3]||(n[3]=i=>H(!1)),onMousedown:n[4]||(n[4]=e.withModifiers(()=>{},["stop"]))},null,32)],34),e.createElementVNode("div",Ue,[e.createElementVNode("div",{class:"video-container",ref_key:"windowVideoRef",ref:Z},null,512)])],38)):e.createCommentVNode("",!0)],512),x.value&&f.value==="right"?(e.openBlock(),e.createElementBlock("div",{key:1,class:e.normalizeClass(["sidebar right-sidebar",{pressing:g.value}])},[e.createElementVNode("div",{class:"window-header",onMousedown:n[7]||(n[7]=i=>ce("right",i)),onMouseup:B,onMouseleave:B},[e.createElementVNode("div",ze,[e.createElementVNode("span",Oe,e.toDisplayString(N.windowTitle),1),e.createElementVNode("div",je,[e.withDirectives(e.createElementVNode("button",Ge,"未连接",512),[[e.vShow,!s.value&&!v.value]]),e.withDirectives(e.createElementVNode("button",Fe,"连接中...",512),[[e.vShow,v.value]]),e.withDirectives(e.createElementVNode("button",qe,"已连接",512),[[e.vShow,s.value]])])]),e.createElementVNode("div",{class:"drag-window-hide",onClick:n[5]||(n[5]=i=>H(!1)),onMousedown:n[6]||(n[6]=e.withModifiers(()=>{},["stop"]))},null,32)],32),e.createElementVNode("div",Ae,[e.renderSlot(t.$slots,"sidebar-right",{},void 0,!0),e.createElementVNode("div",{ref_key:"sidebarRightVideoRef",ref:te,class:"sidebar-video-container"},null,512)])],2)):e.createCommentVNode("",!0),S.value?(e.openBlock(),e.createBlock(e.Teleport,{key:2,to:oe()},[e.createElementVNode("video",{ref_key:"digitalHumanVideo",ref:l,class:"digital-video source-video",poster:"",playsinline:"",autoplay:""},null,512),e.createElementVNode("canvas",{ref_key:"processedCanvas",ref:o,class:"digital-video processed-canvas"},null,512),v.value?(e.openBlock(),e.createElementBlock("div",Je)):e.createCommentVNode("",!0)],8,["to"])):e.createCommentVNode("",!0)],4)}}});exports.default=Qe;
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const h=require("vue");function F(){const d=h.ref(null),r=h.ref(null);let u=null,t=null,l=null,p=null,f=null,n=null,s=null;const b=`
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const x=require("vue");function E(){const g=x.ref(null),o=x.ref(null),u=x.ref(!1),a=x.ref(!1);let c=null,e=null,l=null,p=null,v=null,s=null,d=null;const y=`
2
2
  struct Uniforms {
3
3
  targetColor1: vec3f,
4
4
  threshold: f32,
@@ -19,7 +19,6 @@
19
19
 
20
20
  @vertex
21
21
  fn vertexMain(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
22
- // 全屏四边形顶点
23
22
  var pos = array<vec2f, 6>(
24
23
  vec2f(-1.0, -1.0),
25
24
  vec2f(1.0, -1.0),
@@ -31,7 +30,6 @@
31
30
 
32
31
  var output: VertexOutput;
33
32
  output.position = vec4f(pos[vertexIndex], 0.0, 1.0);
34
- // 翻转Y坐标以修正视频倒置问题
35
33
  output.texCoord = vec2f(
36
34
  pos[vertexIndex].x * 0.5 + 0.5,
37
35
  1.0 - (pos[vertexIndex].y * 0.5 + 0.5)
@@ -52,12 +50,12 @@
52
50
  let rgb = color.rgb;
53
51
  let pixelSize = 1.0 / uniforms.resolution;
54
52
 
55
- // 检查当前像素是否匹配目标色
53
+ // 主颜色匹配:直接透明
56
54
  if (matchesTargetColor(rgb)) {
57
55
  return vec4f(0.0, 0.0, 0.0, 0.0);
58
56
  }
59
57
 
60
- // 检查8个邻居(包括对角线)
58
+ // 8邻域检测:边缘像素透明(第一层侵蚀)
61
59
  let left = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(-pixelSize.x, 0.0)).rgb;
62
60
  let right = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(pixelSize.x, 0.0)).rgb;
63
61
  let top = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(0.0, -pixelSize.y)).rgb;
@@ -67,7 +65,6 @@
67
65
  let bottomLeft = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(-pixelSize.x, pixelSize.y)).rgb;
68
66
  let bottomRight = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(pixelSize.x, pixelSize.y)).rgb;
69
67
 
70
- // 第一层侵蚀:如果任意邻居匹配背景色,当前像素也变透明
71
68
  if (matchesTargetColor(left) || matchesTargetColor(right) ||
72
69
  matchesTargetColor(top) || matchesTargetColor(bottom) ||
73
70
  matchesTargetColor(topLeft) || matchesTargetColor(topRight) ||
@@ -75,18 +72,18 @@
75
72
  return vec4f(0.0, 0.0, 0.0, 0.0);
76
73
  }
77
74
 
78
- // 第二层侵蚀:检查2像素距离的邻居
79
- let left2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(-pixelSize.x * 2.0, 0.0)).rgb;
80
- let right2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(pixelSize.x * 2.0, 0.0)).rgb;
81
- let top2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(0.0, -pixelSize.y * 2.0)).rgb;
82
- let bottom2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(0.0, pixelSize.y * 2.0)).rgb;
75
+ // 2像素邻域检测:第二层侵蚀,优化边缘
76
+ let left2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(-pixelSize.x * 4.0, 0.0)).rgb;
77
+ let right2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(pixelSize.x * 4.0, 0.0)).rgb;
78
+ let top2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(0.0, -pixelSize.y * 4.0)).rgb;
79
+ let bottom2 = textureSampleBaseClampToEdge(videoTexture, videoSampler, input.texCoord + vec2f(0.0, pixelSize.y * 4.0)).rgb;
83
80
 
84
81
  if (matchesTargetColor(left2) || matchesTargetColor(right2) ||
85
82
  matchesTargetColor(top2) || matchesTargetColor(bottom2)) {
86
83
  return vec4f(0.0, 0.0, 0.0, 0.0);
87
84
  }
88
85
 
89
- // 不匹配且不在边缘 - 完全保留
86
+ // 非背景/非边缘像素:完全保留
90
87
  return vec4f(rgb, 1.0);
91
88
  }
92
- `;function v(o){const e=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(o);return e?{r:parseInt(e[1],16),g:parseInt(e[2],16),b:parseInt(e[3],16)}:{r:0,g:0,b:0}}async function C(o){if(!navigator.gpu)return console.error("WebGPU不受支持。请使用Chrome 113+或Edge 113+,或在chrome://flags中启用WebGPU"),!1;try{const e=await navigator.gpu.requestAdapter();if(!e)return console.error("无法获取WebGPU适配器"),!1;if(t=await e.requestDevice(),l=o.getContext("webgpu"),!l)return console.error("无法获取WebGPU上下文"),!1;const i=navigator.gpu.getPreferredCanvasFormat();l.configure({device:t,format:i,alphaMode:"premultiplied"});const a=t.createShaderModule({code:b});f=t.createSampler({magFilter:"linear",minFilter:"linear"}),n=t.createBuffer({size:48,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),s=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{}},{binding:1,visibility:GPUShaderStage.FRAGMENT,externalTexture:{}},{binding:2,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}}]});const c=t.createPipelineLayout({bindGroupLayouts:[s]});return p=t.createRenderPipeline({layout:c,vertex:{module:a,entryPoint:"vertexMain"},fragment:{module:a,entryPoint:"fragmentMain",targets:[{format:i,blend:{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}}}]},primitive:{topology:"triangle-list"}}),console.log("WebGPU初始化成功"),!0}catch(e){return console.error("WebGPU初始化失败:",e),!1}}function m(){if(!d.value||!r.value||!t||!l||!p||!f||!n||!s)return;const o=d.value,e=r.value;if(o.readyState<o.HAVE_CURRENT_DATA){u=requestAnimationFrame(m);return}(e.width!==o.videoWidth||e.height!==o.videoHeight)&&(e.width=o.videoWidth,e.height=o.videoHeight);try{const i=t.importExternalTexture({source:o}),a=v("#0AFFFF"),c=v("#0AFFFF"),y=new Float32Array([a.r/255,a.g/255,a.b/255,.4,c.r/255,c.g/255,c.b/255,0,e.width,e.height,0,0]);t.queue.writeBuffer(n,0,y);const P=t.createBindGroup({layout:s,entries:[{binding:0,resource:f},{binding:1,resource:i},{binding:2,resource:{buffer:n}}]}),x=t.createCommandEncoder(),g=x.beginRenderPass({colorAttachments:[{view:l.getCurrentTexture().createView(),clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]});g.setPipeline(p),g.setBindGroup(0,P),g.draw(6),g.end(),t.queue.submit([x.finish()])}catch(i){console.error("WebGPU渲染帧错误:",i)}u=requestAnimationFrame(m)}async function S(){if(!d.value||!r.value)return;if(!await C(r.value)){console.error("WebGPU初始化失败,请确保浏览器支持WebGPU");return}u=requestAnimationFrame(m)}function T(){if(u!==null&&(cancelAnimationFrame(u),u=null),r.value&&(r.value.getContext("2d")||r.value.getContext("webgpu"))){if(l&&t){const i=t.createCommandEncoder();i.beginRenderPass({colorAttachments:[{view:l.getCurrentTexture().createView(),clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]}).end(),t.queue.submit([i.finish()])}const e=r.value.getContext("2d");if(e){e.clearRect(0,0,r.value.width,r.value.height);const i=r.value.width,a=r.value.height;r.value.width=i,r.value.height=a}}n&&(n.destroy(),n=null),t=null,l=null,p=null,f=null,s=null}return{videoRef:d,canvasRef:r,processVideo:S,stopProcessing:T}}exports.default=F;
89
+ `;function S(t){const r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return r?{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16)}:{r:0,g:0,b:0}}const T=()=>{if(c&&(cancelAnimationFrame(c),c=null),s&&(s.destroy(),s=null),p&&(p=null),d&&(d=null),v&&(v=null),l){try{l.unconfigure()}catch{}l=null}e&&(e.destroy(),e=null),u.value=!1,a.value=!1,console.log("✅ WebGPU资源已彻底销毁,可重新初始化")};async function h(t,r=3){if(T(),!navigator.gpu)return console.error("WebGPU不受支持:请使用Chrome113+/Edge113+,或在chrome://flags中启用WebGPU"),!1;if(!t)return console.error("❌ WebGPU初始化失败:canvas节点不存在"),!1;try{const i=await navigator.gpu.requestAdapter({powerPreference:"low-power"});if(!i)throw new Error("获取GPU适配器失败");if(e=await i.requestDevice(),!e)throw new Error("获取GPU设备失败");if(l=t.getContext("webgpu"),!l)throw new Error("获取canvas的WebGPU上下文失败");const n=navigator.gpu.getPreferredCanvasFormat();l.configure({device:e,format:n,alphaMode:"premultiplied"});const f=e.createShaderModule({code:y});v=e.createSampler({magFilter:"linear",minFilter:"linear"}),s=e.createBuffer({size:48,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),d=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{}},{binding:1,visibility:GPUShaderStage.FRAGMENT,externalTexture:{}},{binding:2,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}}]});const C=e.createPipelineLayout({bindGroupLayouts:[d]});return p=e.createRenderPipeline({layout:C,vertex:{module:f,entryPoint:"vertexMain"},fragment:{module:f,entryPoint:"fragmentMain",targets:[{format:n,blend:{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}}}]},primitive:{topology:"triangle-list"}}),u.value=!0,console.log("WebGPU初始化成功"),!0}catch(i){return console.error(`❌ WebGPU初始化失败(剩余重试${r-1}次):`,i),r>1?(await new Promise(n=>setTimeout(n,500)),h(t,r-1)):(u.value=!1,!1)}}function b(){if(!u.value||!g.value||!o.value||!e||!l||!p||!v||!s||!d){a.value=!1;return}const t=g.value,r=o.value;if(t.readyState<t.HAVE_CURRENT_DATA){c=requestAnimationFrame(b);return}(r.width!==t.videoWidth||r.height!==t.videoHeight)&&(r.width=t.videoWidth,r.height=t.videoHeight);try{const i=e.importExternalTexture({source:t}),n=S("#0AFFFF"),f=S("#0AFFFF"),C=new Float32Array([n.r/255,n.g/255,n.b/255,.4,f.r/255,f.g/255,f.b/255,0,r.width,r.height,0,0]);e.queue.writeBuffer(s,0,C);const U=e.createBindGroup({layout:d,entries:[{binding:0,resource:v},{binding:1,resource:i},{binding:2,resource:{buffer:s}}]}),P=e.createCommandEncoder(),m=P.beginRenderPass({colorAttachments:[{view:l.getCurrentTexture().createView(),clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]});m.setPipeline(p),m.setBindGroup(0,U),m.draw(6),m.end(),e.queue.submit([P.finish()])}catch(i){console.error("WebGPU渲染帧错误:",i),a.value=!1;return}c=requestAnimationFrame(b)}async function G(){if(!g.value||!o.value){console.error("❌ processVideo失败:video/canvas节点未绑定");return}if(a.value)return;if(a.value=!0,!await h(o.value)){console.error("WebGPU初始化重试耗尽,无法处理视频"),a.value=!1,u.value=!1;return}c=requestAnimationFrame(b)}function w(){if(a.value=!1,u.value=!1,T(),o.value){const t=o.value.getContext("2d");if(t){t.clearRect(0,0,o.value.width,o.value.height);const r=o.value.width,i=o.value.height;o.value.width=r,o.value.height=i}}}async function F(){return o.value?await h(o.value,3):(console.error("❌ reInitWebGPU失败:canvas节点未绑定"),!1)}return{videoRef:g,canvasRef:o,isInitSuccess:u,isProcessing:a,processVideo:G,stopProcessing:w,reInitWebGPU:F}}exports.default=E;