sense-audio-type 1.0.2 → 1.0.4

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/esm/index.js CHANGED
@@ -1,2 +1,1991 @@
1
- import*as e from"react";import t,{useState as n,useEffect as o}from"react";import*as r from"react-dom/client";function i(e){var t=a(),n=t.envPrefix?"".concat(t.envPrefix,".api.senseaudio.cn"):"api.senseaudio.cn";return"https://".concat(n).concat("/v1/asr/input_stream")}function a(){return"undefined"!=typeof window&&(window.senseAiHelperSdk||(window.senseAiHelperSdk={}),window.senseAiHelperSdk.inputListener||(window.senseAiHelperSdk.inputListener={shortcutKey:{key:"Alt"},recognitionLang:"zh-CN",asrApi:{url:i(),headers:{},mode:"stream"},publicKey:"",targetLang:"None",model:"sense-asr-deepthink",envPrefix:"staging",authToken:null,authTokenPromise:null,selectedText:"",currentInputElement:null,isKeyPressed:!1,isRecordingStarting:!1,isIndicatorShown:!1,mediaRecorder:null,audioChunks:[],isRecording:!1,recognizedText:"",interimText:"",audioContext:null,audioAnalyser:null,audioAnalysisFrameId:null,currentVolumes:null,statusIndicatorRoot:null,toastRoot:null,currentIndicatorStatus:void 0,isHidingIndicator:!1,hideIndicatorTimer:null,isCreatingIndicator:!1,rewriteResultRoot:null,onRecordingStart:null,onRecordingUpdate:null,onRecordingEnd:null,onError:null,shouldContinueRecording:function(){return!1},isInitialized:!1})),window.senseAiHelperSdk.inputListener}function s(e){var t=a();Object.assign(t,e)}var l=function(){return l=Object.assign||function(e){for(var t,n=1,o=arguments.length;n<o;n++)for(var r in t=arguments[n])Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e},l.apply(this,arguments)};function d(e,t,n,o){return new(n||(n=Promise))(function(r,i){function a(e){try{l(o.next(e))}catch(e){i(e)}}function s(e){try{l(o.throw(e))}catch(e){i(e)}}function l(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(a,s)}l((o=o.apply(e,t||[])).next())})}function u(e,t){var n,o,r,i={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return a.next=s(0),a.throw=s(1),a.return=s(2),"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function s(s){return function(l){return function(s){if(n)throw new TypeError("Generator is already executing.");for(;a&&(a=0,s[0]&&(i=0)),i;)try{if(n=1,o&&(r=2&s[0]?o.return:s[0]?o.throw||((r=o.return)&&r.call(o),0):o.next)&&!(r=r.call(o,s[1])).done)return r;switch(o=0,r&&(s=[2&s[0],r.value]),s[0]){case 0:case 1:r=s;break;case 4:return i.label++,{value:s[1],done:!1};case 5:i.label++,o=s[1],s=[0];continue;case 7:s=i.ops.pop(),i.trys.pop();continue;default:if(!(r=i.trys,(r=r.length>0&&r[r.length-1])||6!==s[0]&&2!==s[0])){i=0;continue}if(3===s[0]&&(!r||s[1]>r[0]&&s[1]<r[3])){i.label=s[1];break}if(6===s[0]&&i.label<r[1]){i.label=r[1],r=s;break}if(r&&i.label<r[2]){i.label=r[2],i.ops.push(s);break}r[2]&&i.ops.pop(),i.trys.pop();continue}s=t.call(e,i)}catch(e){s=[6,e],o=0}finally{n=r=0}if(5&s[0])throw s[1];return{value:s[0]?s[1]:void 0,done:!0}}([s,l])}}}function c(e,t){void 0===t&&(t={});var n=t.insertAt;if(e&&"undefined"!=typeof document){var o=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css","top"===n&&o.firstChild?o.insertBefore(r,o.firstChild):o.appendChild(r),r.styleSheet?r.styleSheet.cssText=e:r.appendChild(document.createTextNode(e))}}"function"==typeof SuppressedError&&SuppressedError;var _={statusIndicator:"StatusIndicator-module__statusIndicator___joWb0",hiding:"StatusIndicator-module__hiding___sv8Jg",waveContainer:"StatusIndicator-module__waveContainer___1DHzO",waveBarsContainer:"StatusIndicator-module__waveBarsContainer___MOYeO",dotsContainer:"StatusIndicator-module__dotsContainer___BOEoa",dot:"StatusIndicator-module__dot___A5ESi",loadingWithWaveContainer:"StatusIndicator-module__loadingWithWaveContainer___DG1Yx",rotatingPoints:"StatusIndicator-module__rotatingPoints___P6lwm",rotatingPoint:"StatusIndicator-module__rotatingPoint___QmHOY",waveBar:"StatusIndicator-module__waveBar___irNLu"};c("@keyframes StatusIndicator-module__slideIn___g7A8l{0%{opacity:0;transform:translateX(100%)}to{opacity:1;transform:translateX(0)}}@keyframes StatusIndicator-module__slideOut___7BI02{0%{opacity:1;transform:translateX(0)}to{opacity:0;transform:translateX(100%)}}@keyframes StatusIndicator-module__fadeIn___-ft5Z{0%{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%)}}@keyframes StatusIndicator-module__fadeOut___S2Lbf{0%{opacity:1;transform:translate(-50%)}to{opacity:0;transform:translate(-50%,10px)}}@keyframes StatusIndicator-module__waveAnimation___eM33k{0%,to{height:6px}25%{height:18px}50%{height:30px}75%{height:18px}}@keyframes StatusIndicator-module__spin___9Y9Qv{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes StatusIndicator-module__loadingDots___tV9-o{0%,80%,to{opacity:.5;transform:scale(.6)}40%{opacity:1;transform:scale(1)}}@keyframes StatusIndicator-module__rotatePoints___jYhWY{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.StatusIndicator-module__statusIndicator___joWb0{align-items:flex-start;animation:StatusIndicator-module__fadeIn___-ft5Z .3s ease-out;background:linear-gradient(180deg,#14192f,#252c4a);border:1px solid var(--Angular,#ffc876);border-radius:27px;bottom:-30px;box-shadow:0 4px 24px 0 rgba(36,54,134,.25);box-sizing:border-box;display:flex;gap:3px;height:49.5px;justify-content:center;left:50%;padding:12px 16.5px 12px 12px;position:fixed;transform:translate(-50%);width:171px;z-index:2147483647}.StatusIndicator-module__statusIndicator___joWb0.StatusIndicator-module__hiding___sv8Jg{animation:StatusIndicator-module__fadeOut___S2Lbf .3s ease-out}.StatusIndicator-module__waveContainer___1DHzO{align-items:center;display:flex;height:100%;justify-content:center;position:relative;width:100%}.StatusIndicator-module__waveBarsContainer___MOYeO{align-items:center;display:flex;height:25.5px;justify-content:center}.StatusIndicator-module__waveCanvas___XUPyx{display:block;height:100%;width:100%}.StatusIndicator-module__dotsContainer___BOEoa{align-items:center;display:flex;gap:9px;height:36px}.StatusIndicator-module__dot___A5ESi{background:#fff;border-radius:50%;height:6px;opacity:.6;width:9px}.StatusIndicator-module__loadingWithWaveContainer___DG1Yx{align-items:center;display:flex;gap:3px;height:100%;justify-content:center;width:100%}.StatusIndicator-module__loadingDots___tV9-o{align-items:center;display:flex;flex-shrink:0;gap:4.5px}.StatusIndicator-module__loadingDot___zwgLy{animation:StatusIndicator-module__loadingDots___tV9-o 1.4s ease-in-out infinite;background:#fff;border-radius:50%;height:6px;width:6px}.StatusIndicator-module__loadingDot___zwgLy:first-child{animation-delay:0s}.StatusIndicator-module__loadingDot___zwgLy:nth-child(2){animation-delay:.2s}.StatusIndicator-module__loadingDot___zwgLy:nth-child(3){animation-delay:.4s}.StatusIndicator-module__rotatingPoints___P6lwm{animation:StatusIndicator-module__rotatePoints___jYhWY 1s linear infinite;flex-shrink:0;height:24px;position:relative;width:24px}.StatusIndicator-module__rotatingPoint___QmHOY{background:#fff;border-radius:1.5px;height:6px;left:50%;margin-left:-1.5px;margin-top:-3px;position:absolute;top:50%;transform-origin:center center;width:3px}.StatusIndicator-module__rotatingPoint___QmHOY:first-child{opacity:.25;transform:rotate(0deg) translateY(-7.5px)}.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(2){opacity:.4;transform:rotate(45deg) translateY(-7.5px)}.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(3){opacity:.55;transform:rotate(90deg) translateY(-7.5px)}.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(4){opacity:.7;transform:rotate(135deg) translateY(-7.5px)}.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(5){opacity:.85;transform:rotate(180deg) translateY(-7.5px)}.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(6){opacity:.95;transform:rotate(225deg) translateY(-7.5px)}.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(7){opacity:1;transform:rotate(270deg) translateY(-7.5px)}.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(8){opacity:.95;transform:rotate(315deg) translateY(-7.5px)}.StatusIndicator-module__loadingContainer___5w5a0{align-items:center;display:flex;height:100%;justify-content:center;width:100%}.StatusIndicator-module__loadingOverlay___wLfWy{align-items:center;backdrop-filter:blur(2px);background:rgba(0,0,0,.3);border-radius:12px;bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0}.StatusIndicator-module__spinner___j8wsu{animation:StatusIndicator-module__spin___9Y9Qv .8s linear infinite;border:3px solid hsla(0,0%,100%,.3);border-radius:50%;border-top-color:#fff;height:24px;width:24px}.StatusIndicator-module__waveBar___irNLu{align-items:center;align-self:center;display:flex;flex-shrink:0;justify-content:center;transition:height .1s ease-out}");var m={barCount:13,maxBarHeight:25.5,minBarHeight:4.5,barWidth:4.5,gap:3,borderRadius:2.25},f=m,p={gradientStart:"#ffffff",gradientMiddle:"#f0f0f0",gradientEnd:"#ffffff"},g={interpolationFactor:.7},h=l(l({},m),{staticHeightRatio:.5}),v=function(e){var r=e.volumes,i=e.isStatic,a=void 0!==i&&i,s=e.className,l=void 0===s?"":s,d=n(new Array(f.barCount).fill(f.minBarHeight)),u=d[0],c=d[1];o(function(){if(a){var e=f,t=e.maxBarHeight-e.minBarHeight,n=h.staticHeightRatio,o=new Array(e.barCount).fill(0).map(function(o,r){var i=(e.barCount-1)/2,a=Math.abs(r-i)/i,s=1-.4*Math.pow(a,2),l=Math.max(.6,Math.min(1,s));return e.minBarHeight+l*t*n});c(o)}else if(r&&0!==r.length){var i=f,s=g,l=i.maxBarHeight-i.minBarHeight;c(function(e){var t=(i.barCount-1)/2;return e.map(function(e,n){var o=r[n]||0,a=n-t,d=Math.round(t-a),u=(o+(r[Math.max(0,Math.min(i.barCount-1,d))]||0))/2,c=Math.sqrt(Math.min(u/255,1)),_=Math.abs(a)/t,m=1-.4*Math.pow(_,2),f=Math.max(.6,Math.min(1,m)),p=e+(i.minBarHeight+c*f*l-e)*s.interpolationFactor;return Math.max(i.minBarHeight,Math.min(p,i.maxBarHeight))})})}},[r,a]);var m=f,v=p;return t.createElement("div",{className:"".concat(_.waveContainer," ").concat(_.waveBarsContainer," ").concat(l)},u.map(function(e,n){var o=n===m.barCount-1;return t.createElement("div",{key:n,className:_.waveBar,style:{background:"linear-gradient(to bottom, ".concat(v.gradientStart,", ").concat(v.gradientMiddle,", ").concat(v.gradientEnd,")"),width:"".concat(m.barWidth,"px"),height:"".concat(e,"px"),borderRadius:"".concat(m.borderRadius,"px"),marginRight:o?"0":"".concat(m.gap,"px")}})}))},y=function(t){var n=t.status,o=t.isHiding,r=void 0!==o&&o,i=t.volumes,a=[_.statusIndicator,r?_.hiding:"","loading"===n?_.loadingWithWave:""].filter(Boolean).join(" ");return e.createElement("div",{id:"sdk-status-indicator",className:a},"speaking"===n?e.createElement("div",{className:_.loadingWithWaveContainer},e.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 16 16",fill:"none"},e.createElement("path",{d:"M8 12.6665V14.6665",stroke:"url(#paint0_linear_1445_38138)",strokeWidth:"1.66667",strokeLinecap:"round",strokeLinejoin:"round"}),e.createElement("path",{d:"M10.3337 3.66683C10.3337 2.37817 9.28899 1.3335 8.00033 1.3335C6.71166 1.3335 5.66699 2.37817 5.66699 3.66683V8.00016C5.66699 9.28883 6.71166 10.3335 8.00033 10.3335C9.28899 10.3335 10.3337 9.28883 10.3337 8.00016V3.66683Z",fill:"url(#paint1_linear_1445_38138)",stroke:"url(#paint2_linear_1445_38138)",strokeWidth:"1.66667",strokeLinejoin:"round"}),e.createElement("path",{d:"M3 7.6665C3 10.4279 5.23857 12.6665 8 12.6665C10.7614 12.6665 13 10.4279 13 7.6665",stroke:"url(#paint3_linear_1445_38138)",strokeWidth:"1.66667",strokeLinecap:"round",strokeLinejoin:"round"}),e.createElement("defs",null,e.createElement("linearGradient",{id:"paint0_linear_1445_38138",x1:"8.5",y1:"12.6665",x2:"8.5",y2:"14.6665",gradientUnits:"userSpaceOnUse"},e.createElement("stop",{stopColor:"#ECFAFF"}),e.createElement("stop",{offset:"1",stopColor:"#BDC8FD"})),e.createElement("linearGradient",{id:"paint1_linear_1445_38138",x1:"8.00033",y1:"1.3335",x2:"8.00033",y2:"10.3335",gradientUnits:"userSpaceOnUse"},e.createElement("stop",{stopColor:"#ECFAFF"}),e.createElement("stop",{offset:"1",stopColor:"#BDC8FD"})),e.createElement("linearGradient",{id:"paint2_linear_1445_38138",x1:"8.00033",y1:"1.3335",x2:"8.00033",y2:"10.3335",gradientUnits:"userSpaceOnUse"},e.createElement("stop",{stopColor:"#ECFAFF"}),e.createElement("stop",{offset:"1",stopColor:"#BDC8FD"})),e.createElement("linearGradient",{id:"paint3_linear_1445_38138",x1:"8",y1:"7.6665",x2:"8",y2:"12.6665",gradientUnits:"userSpaceOnUse"},e.createElement("stop",{stopColor:"#ECFAFF"}),e.createElement("stop",{offset:"1",stopColor:"#BDC8FD"})))),e.createElement(v,{volumes:i,isStatic:!1})):"silent"===n?e.createElement("div",{className:_.loadingWithWaveContainer},e.createElement("div",{className:_.dotsContainer},Array.from({length:10}).map(function(t,n){return e.createElement("div",{key:n,className:_.dot})}))):"loading"===n?e.createElement("div",{className:_.loadingWithWaveContainer},e.createElement("div",{className:_.rotatingPoints},Array.from({length:8}).map(function(t,n){return e.createElement("div",{key:n,className:_.rotatingPoint})})),e.createElement(v,{isStatic:!0})):null)},w={toast:"Toast-module__toast___TNqrY",slideIn:"Toast-module__slideIn___OVESo",success:"Toast-module__success___NZdm8",error:"Toast-module__error___yF0Tc",info:"Toast-module__info___lUXoo",hiding:"Toast-module__hiding___mUWl5",slideOut:"Toast-module__slideOut___M2e0e"};c("@keyframes Toast-module__slideIn___OVESo{0%{opacity:0;transform:translate(-50%,-100%)}to{opacity:1;transform:translate(-50%)}}@keyframes Toast-module__slideOut___M2e0e{0%{opacity:1;transform:translate(-50%)}to{opacity:0;transform:translate(-50%,-100%)}}.Toast-module__toast___TNqrY{animation:Toast-module__slideIn___OVESo .3s ease-out;border-radius:8px;font-family:Arial,sans-serif;font-size:14px;left:50%;padding:6px 14px;position:fixed;top:20px;transform:translateX(-50%);z-index:2147483647}.Toast-module__toast___TNqrY.Toast-module__success___NZdm8{background-color:#6bff8d;border:1px solid #fde2e2;color:#f67e7e}.Toast-module__toast___TNqrY.Toast-module__error___yF0Tc{background-color:#fef0f0;border:1px solid #fde2e2;color:#f67e7e}.Toast-module__toast___TNqrY.Toast-module__info___lUXoo{background-color:#fdf6ec;border:1px solid #faecd8;color:#eaae55}.Toast-module__toast___TNqrY.Toast-module__hiding___mUWl5{animation:Toast-module__slideOut___M2e0e .3s ease-out}");var x=function(t){var n=t.message,o=t.type,r=void 0===o?"success":o,i=t.duration,a=void 0===i?2e3:i,s=t.onClose;e.useEffect(function(){var e=setTimeout(function(){s()},a);return function(){return clearTimeout(e)}},[a,s]);var l=[w.toast,w[r]].filter(Boolean).join(" ");return e.createElement("div",{className:l},n)},b="RewriteResult-module__overlay___4tJMY",R="RewriteResult-module__header___cheJF",E="RewriteResult-module__close___D9aIV",I="RewriteResult-module__body___vQYaF",k="RewriteResult-module__footer___68OdM",T="RewriteResult-module__m2___cEJhO",S="RewriteResult-module__logo___hbjf0",C="RewriteResult-module__button___nLV0i";c('@keyframes RewriteResult-module__sdk-rewrite-fade-in___tItTw{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.RewriteResult-module__overlay___4tJMY{align-items:flex-end;display:flex;height:100%;justify-content:center;pointer-events:none;width:100%}.RewriteResult-module__popup___IjoJz{animation:RewriteResult-module__sdk-rewrite-fade-in___tItTw .18s ease-out;background:rgba(0,0,0,.85);border-radius:12px;box-shadow:0 12px 32px rgba(0,0,0,.35);color:#fff;display:flex;flex-direction:column;font-size:14px;gap:12px;max-width:480px;min-width:280px;padding:16px 20px;pointer-events:auto}.RewriteResult-module__header___cheJF{align-items:center;display:flex;justify-content:flex-end}.RewriteResult-module__close___D9aIV{background:transparent;border:none;color:#fff;cursor:pointer;font-size:16px;line-height:1;padding:0;position:absolute;right:16px;top:8px}.RewriteResult-module__body___vQYaF{background:hsla(0,0%,100%,.08);border-radius:8px;line-height:1.5;padding:12px;word-break:break-word}.RewriteResult-module__footer___68OdM{display:flex;gap:8px;justify-content:flex-end}.RewriteResult-module__primary___MIFKB{background:#4b8cf7;border:none;border-radius:8px;color:#fff;cursor:pointer;font-weight:600;padding:8px 14px;transition:background .12s ease}.RewriteResult-module__primary___MIFKB:hover{background:#3b79e0}.RewriteResult-module__primary___MIFKB:active{background:#2f67c4}.RewriteResult-module__m2___cEJhO{align-items:center;animation:RewriteResult-module__gradient-shift___vfj5d 5s ease-in-out infinite;background:linear-gradient(135deg,#1e1e24 10%,#050505 60%);background-size:100% 100%;border-radius:12px;display:flex;flex-direction:column;gap:12px;justify-content:center;max-width:480px;min-width:280px;padding:16px 20px;pointer-events:auto;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none}.RewriteResult-module__m2___cEJhO .RewriteResult-module__logo___hbjf0{-webkit-text-fill-color:currentColor;background:none;background-clip:initial;-webkit-background-clip:initial;color:#fff;display:inline-block;font-size:14px;font-weight:700;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:baseline}.RewriteResult-module__m2___cEJhO .RewriteResult-module__logo___hbjf0 svg{height:5vmin;margin-right:-1vmin;width:5vmin}.RewriteResult-module__m2___cEJhO:after{--size:1px;z-index:-1}.RewriteResult-module__m2___cEJhO:before{--size:6px;animation:RewriteResult-module__blur-animation___tZWlQ 3s ease-in-out infinite alternate;filter:blur(1vmin);z-index:-2}@keyframes RewriteResult-module__blur-animation___tZWlQ{to{filter:blur(3vmin);transform:scale(1.05)}}@keyframes RewriteResult-module__gradient-shift___vfj5d{0%{background-position:0 50%}50%{background-position:100% 50%}to{background-position:0 50%}}.RewriteResult-module__button___nLV0i{background:linear-gradient(45deg,#0ce39a,#69007f,#fc0987);border-radius:10px;color:#fff;cursor:pointer;font-size:14px;font-weight:700;padding:6px 24px;pointer-events:auto;position:relative;text-decoration:none}.RewriteResult-module__button___nLV0i span{position:relative;z-index:1}.RewriteResult-module__button___nLV0i:before{background:#272727;border-radius:9px;content:"";inset:1px;position:absolute;transition:.5s}.RewriteResult-module__button___nLV0i:hover:before{opacity:.7}.RewriteResult-module__button___nLV0i:after{background:linear-gradient(45deg,#0ce39a,#69007f,#fc0987);border-radius:9px;content:"";filter:blur(20px);inset:0;opacity:0;position:absolute;transition:.5s}.RewriteResult-module__button___nLV0i:hover:after{opacity:1}');var A=function(e){var n=e.text,o=e.onClose,r=e.onCopy;return t.createElement("div",{className:b},t.createElement("div",{className:T},t.createElement("div",{className:R},t.createElement("button",{className:E,onClick:o,"aria-label":"close"},"×")),t.createElement("div",{className:S},t.createElement("div",{className:I},n)),t.createElement("div",{className:k},t.createElement("button",{onClick:r,className:C},t.createElement("span",null,"复制")))))};var L="undefined"!=typeof window&&window.React?window.React:e,P=function(){if("undefined"!=typeof window&&window.ReactDOM){var e=window.ReactDOM;if(e.createRoot)return{createRoot:e.createRoot}}if("undefined"!=typeof window&&window.ReactDOMClient){var t=window.ReactDOMClient;if(t.createRoot)return{createRoot:t.createRoot}}return r&&r.createRoot,r}();function M(e){var t=a();if(!t.isCreatingIndicator&&(t.isHidingIndicator&&null!==t.hideIndicatorTimer&&(clearTimeout(t.hideIndicatorTimer),s({hideIndicatorTimer:null,isHidingIndicator:!1})),L&&P))if(t.currentIndicatorStatus===e&&t.statusIndicatorRoot)"speaking"===e&&O();else{s({isCreatingIndicator:!0});try{if(function(){if(!a().statusIndicatorRoot){var e=document.getElementById("sdk-status-indicator-container");e||((e=document.createElement("div")).id="sdk-status-indicator-container",e.style.cssText="position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:2147483647",document.body.appendChild(e));try{s({statusIndicatorRoot:P.createRoot(e)})}catch(e){}}}(),!t.statusIndicatorRoot)return void s({isCreatingIndicator:!1});var n=L.createElement("div",{id:"sdk-status-indicator-wrapper",style:{position:"fixed",bottom:"100px",left:"50%",transform:"translate(-50%, 0)",zIndex:2147483647,pointerEvents:"none"}},L.createElement(y,{status:e,isHiding:!1,volumes:t.currentVolumes||void 0}));t.statusIndicatorRoot.render(n),s({currentIndicatorStatus:e})}catch(e){}finally{s({isCreatingIndicator:!1})}}}function O(){var e=a();if(e.statusIndicatorRoot&&"speaking"===e.currentIndicatorStatus&&L){var t=L.createElement("div",{id:"sdk-status-indicator-wrapper",style:{position:"fixed",bottom:"100px",left:"50%",transform:"translate(-50%, 0)",zIndex:2147483647,pointerEvents:"none"}},L.createElement(y,{status:e.currentIndicatorStatus,isHiding:!1,volumes:e.currentVolumes||void 0}));e.statusIndicatorRoot.render(t)}}function j(){var e=a();if(K(),!e.isHidingIndicator&&e.statusIndicatorRoot&&void 0!==e.currentIndicatorStatus&&L){s({isHidingIndicator:!0}),null!==e.hideIndicatorTimer&&clearTimeout(e.hideIndicatorTimer);var t=L.createElement("div",{id:"sdk-status-indicator-wrapper",style:{position:"fixed",bottom:"100px",left:"50%",transform:"translate(-50%, 0)",zIndex:2147483647,pointerEvents:"none"}},L.createElement(y,{status:e.currentIndicatorStatus,isHiding:!0,volumes:void 0}));e.statusIndicatorRoot.render(t);var n=window.setTimeout(function(){e.statusIndicatorRoot&&e.statusIndicatorRoot.render(null),s({currentIndicatorStatus:void 0,hideIndicatorTimer:null,isHidingIndicator:!1})},300);s({hideIndicatorTimer:n})}}function z(e){var t=a();t.audioAnalysisFrameId&&K();var n=e.frequencyBinCount,o=new Uint8Array(n),r=0;var i=requestAnimationFrame(function i(l){if(l-r>=20){e.getByteFrequencyData(o);for(var d=f.barCount,u=[],c=0;c<d;c++){var _=Math.pow(n,c/d),m=Math.pow(n,(c+1)/d),p=Math.floor(_),g=c===d-1?n:Math.floor(m);if(p>=g||p>=n)u.push(0);else{for(var h=0,v=0,y=0,w=p;w<g&&w<n;w++){var x=o[w];h+=x,x>v&&(v=x),y++}var b=.4*v+.6*(y>0?h/y:0);u.push(Math.max(b,5))}}!function(e){var t=a();if("loading"===t.currentIndicatorStatus)return;s({currentVolumes:e}),O()}(u),r=l}null!==t.audioAnalysisFrameId&&s({audioAnalysisFrameId:requestAnimationFrame(i)})});s({audioAnalysisFrameId:i})}function K(){var e=a();e.audioAnalysisFrameId&&(cancelAnimationFrame(e.audioAnalysisFrameId),s({audioAnalysisFrameId:null,currentVolumes:null}))}function B(e,t){void 0===t&&(t="success");var n=a();if(L&&P){!function(){if(!a().toastRoot){var e=document.getElementById("sdk-toast-container");e||((e=document.createElement("div")).id="sdk-toast-container",e.style.cssText="position:fixed;top:0;right:0;z-index:2147483647;pointer-events:none",document.body.appendChild(e));try{s({toastRoot:P.createRoot(e)})}catch(e){}}}();var o=L.createElement(x,{message:e,type:t,duration:2e3,onClose:function(){n.toastRoot&&n.toastRoot.render(null)}});n.toastRoot&&(n.toastRoot.render(o),setTimeout(function(){n.toastRoot&&n.toastRoot.render(null)},2e3))}}function H(e){var t=this;if(a(),L&&P&&e){!function(){if(!a().rewriteResultRoot){var e=document.getElementById("sdk-rewrite-result-container");e||((e=document.createElement("div")).id="sdk-rewrite-result-container",e.style.cssText="position:fixed;inset:0;z-index:2147483647;display:flex;align-items:flex-end;justify-content:center;pointer-events:none;padding:40px",document.body.appendChild(e));try{s({rewriteResultRoot:P.createRoot(e)})}catch(e){}}}();var n=a().rewriteResultRoot;if(n){var o=function(){n.render(null)},r=L.createElement(A,{text:e,onClose:o,onCopy:function(){return d(t,void 0,void 0,function(){return u(this,function(t){switch(t.label){case 0:return t.trys.push([0,2,,3]),[4,navigator.clipboard.writeText(e)];case 1:return t.sent(),o(),[3,3];case 2:return t.sent(),B("复制失败","error"),[3,3];case 3:return[2]}})})}});n.render(r)}}}var N={"x-platform":"WEB","x-version":"0.0.1","x-product":"SenseType"};function F(e){return"None"===e?"":e}function D(){return d(this,void 0,void 0,function(){var e,t,n=this;return u(this,function(o){switch(o.label){case 0:return(e=a()).authToken?[2,e.authToken]:e.authTokenPromise?[4,e.authTokenPromise]:[3,2];case 1:case 3:return[2,o.sent()];case 2:if(!e.publicKey)throw new Error("缺少 publicKey:无法换取 token");return t=d(n,void 0,void 0,function(){var t,n;return u(this,function(o){switch(o.label){case 0:return[4,V({durationSeconds:86400,publicKey:e.publicKey})];case 1:if(t=o.sent(),n=function(e){var t,n,o,r;if("string"==typeof e)return e.trim()||null;if(!e||"object"!=typeof e)return null;for(var i=e,a=0,s=[null==i?void 0:i.token,null==i?void 0:i.access_token,null===(t=null==i?void 0:i.result)||void 0===t?void 0:t.token,null===(n=null==i?void 0:i.result)||void 0===n?void 0:n.access_token,null===(o=null==i?void 0:i.data)||void 0===o?void 0:o.token,null===(r=null==i?void 0:i.data)||void 0===r?void 0:r.access_token];a<s.length;a++){var l=s[a];if("string"==typeof l&&l.trim())return l.trim()}return null}(t),!n)throw new Error("获取 token 失败:响应中未找到 token 字段");return s({authToken:n,authTokenPromise:null}),[2,n]}})}).catch(function(e){throw s({authTokenPromise:null}),e}),s({authTokenPromise:t}),[4,t]}})})}function Y(e){return d(this,void 0,void 0,function(){var t,n,o;return u(this,function(r){switch(r.label){case 0:return t=a(),n=l(l({},N),e||{}),t.publicKey?[4,D()]:[3,2];case 1:o=r.sent(),n.Authorization=function(e){var t=e.trim();return t?/^Bearer\s+/i.test(t)?t:"Bearer ".concat(t):t}(o),r.label=2;case 2:return[2,n]}})})}function U(e){return d(this,void 0,void 0,function(){var t,n,o,r,i,s,d,c,_,m,f;return u(this,function(u){switch(u.label){case 0:return p=a(),g=p.envPrefix?"".concat(p.envPrefix,".api.senseaudio.cn"):"api.senseaudio.cn",t="https://".concat(g).concat("/v1/asr/input_rewrite"),[4,Y(l(l({},(null===(m=e.asrApi)||void 0===m?void 0:m.headers)||{}),{accept:"application/json","x-platform":"WEB","x-version":"0.0.1","x-product":"SenseType","Content-Type":"application/x-www-form-urlencoded"}))];case 1:return n=u.sent(),o=F(e.targetLang),r={original_text:e.originalText,rewrite_instruction:e.rewriteInstruction,model:e.model},o&&(r.target_lang=o),i=new URLSearchParams(r).toString(),[4,fetch(t,{method:"POST",headers:n,body:i})];case 2:return(s=u.sent()).ok?[3,4]:[4,s.text().catch(function(){return""})];case 3:throw d=u.sent(),new Error("重写接口失败: ".concat(s.status," ").concat(s.statusText).concat(d?" - ".concat(d):""));case 4:return[4,s.json().catch(function(){return{}})];case 5:return c=u.sent(),[2,"string"==typeof(_=null===(f=null==c?void 0:c.result)||void 0===f?void 0:f.rewritten_text)?_:""]}var p,g})})}function W(e){return d(this,void 0,void 0,function(){var t,n,o,r,i,a,s,d,c,_,m,f,p,g;return u(this,function(u){switch(u.label){case 0:return t="recording.mp3",n=new File([e.audioBlob],t,{type:"audio/mpeg"}),(o=new FormData).append("file",n,t),o.append("model",e.model),(r=F(e.targetLang))&&o.append("target_lang",r),[4,Y(l({accept:"*/*","Accept-Language":"en,zh-CN;q=0.9,zh;q=0.8","Cache-Control":"no-cache","x-platform":"WEB","x-version":"0.0.1","x-product":"SenseType",Pragma:"no-cache"},e.headers||{}))];case 1:return delete(i=u.sent())["Content-Type"],[4,fetch(e.asrUrl,{method:"POST",headers:i,body:o,mode:"cors",credentials:"omit",cache:"no-cache"})];case 2:return(a=u.sent()).ok?[3,4]:[4,a.text().catch(function(){return""})];case 3:throw s=u.sent(),new Error("API 请求失败: ".concat(a.status," ").concat(a.statusText).concat(s?" - ".concat(s):""));case 4:return d=a.headers.get("content-type")||"",c="",d.includes("application/json")?[4,a.json().catch(function(){return{}})]:[3,6];case 5:return _=u.sent(),m=null!==(g=null!==(p=null===(f=null==_?void 0:_.result)||void 0===f?void 0:f.final_text)&&void 0!==p?p:null==_?void 0:_.final_text)&&void 0!==g?g:"",c="string"==typeof m?m.trim():"",[3,8];case 6:return[4,a.text()];case 7:c=u.sent().trim(),u.label=8;case 8:return[2,c]}})})}function V(e){return d(this,void 0,void 0,function(){var t,n,o,r,i,s,d,c,_;return u(this,function(u){switch(u.label){case 0:return t=a(),n=t.envPrefix?"".concat(t.envPrefix,".auth.senseaudio.cn"):"auth.senseaudio.cn",o="https://".concat(n,"/v1/apikey/apply_token_via_public_key"),r=e.baseUrl?new URL(o,e.baseUrl).toString():o,i=l(l(l({},N),{"Content-Type":"application/json"}),e.headers||{}),s={duration_seconds:e.durationSeconds,public_key:e.publicKey},e.paths&&e.paths.length>0&&(s.paths=e.paths),d=JSON.stringify(s),[4,fetch(r,{method:"POST",headers:i,body:d})];case 1:return(c=u.sent()).ok?[3,3]:[4,c.text().catch(function(){return""})];case 2:throw _=u.sent(),new Error("apply_token_via_public_key 失败: ".concat(c.status," ").concat(c.statusText).concat(_?" - ".concat(_):""));case 3:return(c.headers.get("content-type")||"").includes("application/json")?[4,c.json().catch(function(){return{}})]:[3,5];case 4:case 6:return[2,u.sent()];case 5:return[4,c.text()]}})})}function Q(){return d(this,void 0,void 0,function(){var e;return u(this,function(t){switch(t.label){case 0:return(e=a()).publicKey?e.authToken?[2]:[4,D()]:[2];case 1:return t.sent(),[2]}})})}function q(e){return d(this,void 0,void 0,function(){var t=this;return u(this,function(n){return[2,new Promise(function(n,o){try{var r=new(window.AudioContext||window.webkitAudioContext),i=new FileReader;i.onload=function(e){return d(t,void 0,void 0,function(){var t,i,a,s,l,d,c,_,m,f,p,g,h,v,y,w,x,b,R,E,I;return u(this,function(u){switch(u.label){case 0:return u.trys.push([0,2,,3]),[4,r.decodeAudioData(null===(I=e.target)||void 0===I?void 0:I.result)];case 1:if(t=u.sent(),i=t.getChannelData(0),a=t.sampleRate,s=i,t.numberOfChannels>1)for(l=t.getChannelData(1),s=new Float32Array(i.length),p=0;p<i.length;p++)s[p]=(i[p]+l[p])/2;for(d=new Int16Array(s.length),p=0;p<s.length;p++)c=Math.max(-1,Math.min(1,s[p])),d[p]=c<0?32768*c:32767*c;if(void 0!==window.lamejs){for(_=window.lamejs,m=new _.Mp3Encoder(1,a,128),f=[],p=0;p<d.length;p+=1152)g=d.subarray(p,p+1152),(h=m.encodeBuffer(g)).length>0&&f.push(h);for((v=m.flush()).length>0&&f.push(v),y=[],w=0,x=f;w<x.length;w++)b=x[w],R=new ArrayBuffer(b.byteLength),new Uint8Array(R).set(new Uint8Array(b.buffer,b.byteOffset,b.byteLength)),y.push(R);n(new Blob(y,{type:"audio/mpeg"}))}else o(new Error("需要加载lamejs库"));return[3,3];case 2:return E=u.sent(),o(E),[3,3];case 3:return[2]}})})},i.onerror=o,i.readAsArrayBuffer(e)}catch(e){o(e)}})]})})}function J(e){return d(this,void 0,void 0,function(){var t,n,o,r,i,l,d,c,_,m,f;return u(this,function(u){switch(u.label){case 0:if(t=a(),null===(i=t.asrApi)||void 0===i||i.mode,!(null===(l=t.asrApi)||void 0===l?void 0:l.url))return null===(d=t.onError)||void 0===d||d.call(t,"API 配置不存在"),[2];u.label=1;case 1:return u.trys.push([1,3,,4]),[4,W({audioBlob:e,asrUrl:t.asrApi.url,headers:t.asrApi.headers,model:t.model,targetLang:t.targetLang})];case 2:return(n=u.sent())?(s({recognizedText:(t.recognizedText?t.recognizedText+" ":"")+n}),null===(c=t.onRecordingUpdate)||void 0===c||c.call(t,t.recognizedText)):B("未识别到信息","info"),t.shouldContinueRecording()||(r=t.recognizedText.trim(),s({recognizedText:"",interimText:""}),null===(_=t.onRecordingEnd)||void 0===_||_.call(t,r)),[3,4];case 3:return o=u.sent(),j(),null===(m=t.onError)||void 0===m||m.call(t,"API 请求失败: ".concat(o.message||"未知错误")),t.shouldContinueRecording()||(r=t.recognizedText.trim(),s({recognizedText:"",interimText:""}),null===(f=t.onRecordingEnd)||void 0===f||f.call(t,r)),[3,4];case 4:return[2]}})})}function X(e){var t,n,o=a();o.isRecording||((null===(t=o.asrApi)||void 0===t?void 0:t.url)?G():null===(n=o.onError)||void 0===n||n.call(o,"API 配置不存在"))}function G(e){return d(this,void 0,void 0,function(){var e,t,n,o,r,i,l,c,_,m,f,p=this;return u(this,function(g){switch(g.label){case 0:e=a(),g.label=1;case 1:return g.trys.push([1,3,,4]),[4,navigator.mediaDevices.getUserMedia({audio:!0})];case 2:return t=g.sent(),n=new(window.AudioContext||window.webkitAudioContext),o=n.createMediaStreamSource(t),(r=n.createAnalyser()).fftSize=256,r.smoothingTimeConstant=.4,r.minDecibels=-90,r.maxDecibels=-10,o.connect(r),s({audioAnalyser:r,audioContext:n}),s({mediaRecorder:i=new MediaRecorder(t,{mimeType:MediaRecorder.isTypeSupported("audio/webm")?"audio/webm":MediaRecorder.isTypeSupported("audio/webm;codecs=opus")?"audio/webm;codecs=opus":MediaRecorder.isTypeSupported("audio/mp4")?"audio/mp4":"audio/webm"}),audioChunks:[],isRecording:!0}),i.ondataavailable=function(t){t.data.size>0&&e.audioChunks.push(t.data)},i.onstop=function(){return d(p,void 0,void 0,function(){var n,o,r,a,l,d,c,_,m;return u(this,function(u){switch(u.label){case 0:if(u.trys.push([0,8,,9]),K(),e.audioContext&&(e.audioContext.close().catch(console.error),s({audioContext:null,audioAnalyser:null})),t.getTracks().forEach(function(e){return e.stop()}),0===e.audioChunks.length)return s({isRecording:!1}),null===(r=e.onRecordingEnd)||void 0===r||r.call(e,""),[2];if(n=new Blob(e.audioChunks,{type:i.mimeType}),s({audioChunks:[]}),o=n,n.type.includes("mpeg")||n.type.includes("mp3"))return[3,6];if(void 0!==window.lamejs)return[3,4];null===(a=e.onRecordingUpdate)||void 0===a||a.call(e,"正在加载MP3编码器..."),u.label=1;case 1:return u.trys.push([1,3,,4]),[4,new Promise(function(e,t){if(void 0===window.lamejs)if(window.__lamejsLoading){var n=setInterval(function(){void 0!==window.lamejs&&(clearInterval(n),e())},100);setTimeout(function(){clearInterval(n),t(new Error("加载lamejs超时"))},1e4)}else{window.__lamejsLoading=!0;var o=document.createElement("script");o.src="https://cdnjs.cloudflare.com/ajax/libs/lamejs/1.2.1/lame.min.js",o.async=!0,o.onload=function(){window.__lamejsLoading=!1,void 0!==window.lamejs?e():t(new Error("lamejs 加载失败"))},o.onerror=function(){window.__lamejsLoading=!1,B("语音加载失败:网络错误","error"),t(new Error("lamejs 加载失败:网络错误"))},document.head.appendChild(o)}else e()})];case 2:return u.sent(),[3,4];case 3:return u.sent(),null===(l=e.onError)||void 0===l||l.call(e,"无法加载MP3编码器"),s({isRecording:!1}),null===(d=e.onRecordingEnd)||void 0===d||d.call(e,""),[2];case 4:return null===(c=e.onRecordingUpdate)||void 0===c||c.call(e,"正在转换为MP3格式..."),[4,q(n)];case 5:o=u.sent(),u.label=6;case 6:return[4,J(o)];case 7:return u.sent(),e.shouldContinueRecording()?G():s({isRecording:!1}),[3,9];case 8:return u.sent(),s({isRecording:!1}),j(),null===(_=e.onError)||void 0===_||_.call(e,"处理录音数据失败"),null===(m=e.onRecordingEnd)||void 0===m||m.call(e,""),[3,9];case 9:return[2]}})})},i.start(),null===(_=e.onRecordingStart)||void 0===_||_.call(e),null===(m=e.onRecordingUpdate)||void 0===m||m.call(e,"正在录音..."),M("speaking"),z(r),[3,4];case 3:return l=g.sent(),s({isRecording:!1}),K(),j(),e.audioContext&&(e.audioContext.close().catch(console.error),s({audioContext:null,audioAnalyser:null})),c="NotAllowedError"===l.name?"麦克风权限被拒绝":"NotFoundError"===l.name?"未找到麦克风设备":"启动录音失败",null===(f=e.onError)||void 0===f||f.call(e,c),[3,4];case 4:return[2]}})})}function Z(){var e,t=a();if(K(),t.mediaRecorder&&t.isRecording)try{"recording"===t.mediaRecorder.state?t.mediaRecorder.stop():(s({isRecording:!1}),j())}catch(n){s({isRecording:!1}),j(),t.audioContext&&(t.audioContext.close().catch(console.error),s({audioContext:null,audioAnalyser:null})),(null===(e=t.mediaRecorder)||void 0===e?void 0:e.stream)&&t.mediaRecorder.stream.getTracks().forEach(function(e){return e.stop()})}else j()}function $(e){s({currentInputElement:e})}var ee=null,te=!1;function ne(e){var t=a().shortcutKey,n=!1,o="AltLeft"===t.code||"AltRight"===t.code||"Alt"===t.key,r="ControlLeft"===t.code||"ControlRight"===t.code||"Control"===t.key,i="ShiftLeft"===t.code||"ShiftRight"===t.code||"Shift"===t.key,s="AltLeft"===e.code||"AltRight"===e.code||"Alt"===e.key,l="ControlLeft"===e.code||"ControlRight"===e.code||"Control"===e.key,d="ShiftLeft"===e.code||"ShiftRight"===e.code||"Shift"===e.key;if(o&&s||r&&l||i&&d?n=!0:(t.code&&e.code===t.code&&(n=void 0===t.location||e.location===t.location),!n&&t.key&&e.key===t.key&&(n=void 0===t.location||e.location===t.location)),!t.code&&!t.key)return!1;if(!n)return!1;var u=o,c=r,_=i;if(u&&(e.ctrlKey||e.shiftKey||e.metaKey))return!1;if(c&&(e.altKey||e.shiftKey||e.metaKey))return!1;if(_&&(e.altKey||e.ctrlKey||e.metaKey))return!1;if(!u&&!c&&!_&&(e.ctrlKey||e.shiftKey||e.altKey||e.metaKey))return!1;return!0}function oe(e){var t=a();if(ne(e))if(e.repeat)e.preventDefault();else if(!t.isKeyPressed){t.rewriteResultRoot&&function(){var e=a();e.rewriteResultRoot&&e.rewriteResultRoot.render(null)}();var n,o=(t.currentInputElement,(n=window.getSelection())?n.toString():""),r=!!o,i=!!t.currentInputElement&&document.activeElement===t.currentInputElement;r||i?(s({isKeyPressed:!0,isRecordingStarting:!0,isIndicatorShown:!1,selectedText:o}),e.preventDefault(),j(),ee=window.setTimeout(function(){var e=a();e.isKeyPressed&&(s({isRecordingStarting:!1}),X(e.recognitionLang))},200)):B("请先聚焦输入框或框选文本","info")}}function re(e){var t=a();ne(e)&&(e.preventDefault(),null!==ee&&(clearTimeout(ee),ee=null),t.isRecording&&(M("loading"),Z()),s({isKeyPressed:!1,isRecordingStarting:!1,isIndicatorShown:!1}))}function ie(e){var t=e.target;if("INPUT"===t.tagName||"TEXTAREA"===t.tagName||"true"===t.contentEditable||t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement){var n=t;s({currentInputElement:n}),$(n)}}function ae(e){var t;a(),(t=a(),{isRecording:t.isRecording,recognizedText:t.recognizedText,interimText:t.interimText}).isRecording&&(Z(),s({isKeyPressed:!1}),j()),s({currentInputElement:null,selectedText:""}),$(null)}function se(){var e,t=a();te||(e={onStart:function(){t.isKeyPressed&&s({isIndicatorShown:!0})},onUpdate:function(){},onEnd:function(e){var t=a().selectedText;s({isIndicatorShown:!1,isRecordingStarting:!1,isKeyPressed:!1,selectedText:""}),e?t?(M("loading"),function(e,t){d(this,void 0,void 0,function(){var n,o;return u(this,function(r){switch(r.label){case 0:n=a(),r.label=1;case 1:return r.trys.push([1,3,,4]),[4,U({originalText:e,rewriteInstruction:t,asrApi:n.asrApi,model:n.model,targetLang:n.targetLang})];case 2:return o=r.sent(),j(),o?H(o):B("未识别到信息","info"),[3,4];case 3:return r.sent(),j(),B("服务器请求超时","error"),[3,4];case 4:return[2]}})})}(t,e)):(j(),function(e){var t,n,o=a().currentInputElement;if(o&&e)if(o instanceof HTMLInputElement||o instanceof HTMLTextAreaElement){var r=o.selectionStart||0,i=o.selectionEnd||0,s=o.value,l=s.substring(0,r)+e+s.substring(i),d=r+e.length,u=o._valueTracker,c=s;if("undefined"!=typeof InputEvent){var _=new InputEvent("beforeinput",{bubbles:!0,cancelable:!0,inputType:"insertText",data:e});if(!o.dispatchEvent(_))return}var m=null;o instanceof HTMLInputElement?m=(null===(t=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,"value"))||void 0===t?void 0:t.set)||null:o instanceof HTMLTextAreaElement&&(m=(null===(n=Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype,"value"))||void 0===n?void 0:n.set)||null),m?m.call(o,l):o.value=l,u&&u.setValue(c),o.selectionStart=d,o.selectionEnd=d;var f="undefined"!=typeof InputEvent?new InputEvent("input",{bubbles:!0,cancelable:!0,data:e,inputType:"insertText"}):new Event("input",{bubbles:!0,cancelable:!0});o.dispatchEvent(f),u&&u.setValue(l);var p=new Event("change",{bubbles:!0,cancelable:!0});o.dispatchEvent(p),document.activeElement!==o&&o.focus(),setTimeout(function(){o&&(o instanceof HTMLInputElement||o instanceof HTMLTextAreaElement)&&(o.selectionStart=d,o.selectionEnd=d)},0)}else if("true"===o.contentEditable){var g=window.getSelection();if(g&&g.rangeCount>0){(v=g.getRangeAt(0)).deleteContents();var h=document.createTextNode(e);v.insertNode(h),v.setStartAfter(h),v.setEndAfter(h),g.removeAllRanges(),g.addRange(v)}else{var v;h=document.createTextNode(e),o.appendChild(h),(v=document.createRange()).setStartAfter(h),v.setEndAfter(h);var y=window.getSelection();y&&(y.removeAllRanges(),y.addRange(v))}f=new Event("input",{bubbles:!0,cancelable:!0}),o.dispatchEvent(f),p=new Event("change",{bubbles:!0,cancelable:!0}),o.dispatchEvent(p),document.activeElement!==o&&o.focus()}}(e)):j()},onError:function(e){s({isIndicatorShown:!1}),B("服务器连接超时","error"),j()},shouldContinue:function(){return!1}},s({onRecordingStart:e.onStart||null,onRecordingUpdate:e.onUpdate||null,onRecordingEnd:e.onEnd||null,onError:e.onError||null,shouldContinueRecording:e.shouldContinue||function(){return!1}}),document.addEventListener("keydown",oe,!0),document.addEventListener("keyup",re,!0),document.addEventListener("focusin",ie,!0),document.addEventListener("focusout",ae,!0),te=!0)}function le(){if("undefined"!=typeof document&&!(document.querySelectorAll("style[data-sdk-styles]").length>0))return document.head?void 0:"loading"===document.readyState?void document.addEventListener("DOMContentLoaded",le):void setTimeout(le,0)}function de(e){var t,n,o=a();o.isInitialized||(s({asrApi:{url:(null===(t=null==e?void 0:e.asrApi)||void 0===t?void 0:t.url)||i(),headers:(null===(n=null==e?void 0:e.asrApi)||void 0===n?void 0:n.headers)||{},mode:"stream"}}),(null==e?void 0:e.lang)&&s({recognitionLang:e.lang}),s({publicKey:(null==e?void 0:e.publicKey)||"",targetLang:(null==e?void 0:e.targetLang)||o.targetLang||"None",model:"sense-asr-deepthink",envPrefix:(null==e?void 0:e.envPrefix)||o.envPrefix,authToken:null,authTokenPromise:null}),(null==e?void 0:e.publicKey)&&Q().catch(function(){}),(null==e?void 0:e.shortcutKey)&&s({shortcutKey:e.shortcutKey}),s({isInitialized:!0}),le(),se())}function ue(e){var t,n,o,r,i,l=a();l.isInitialized&&te&&(null!==ee&&(clearTimeout(ee),ee=null),document.removeEventListener("keydown",oe,!0),document.removeEventListener("keyup",re,!0),document.removeEventListener("focusin",ie,!0),document.removeEventListener("focusout",ae,!0),te=!1),s({isInitialized:!1}),de({lang:null!==(t=null==e?void 0:e.lang)&&void 0!==t?t:l.recognitionLang,shortcutKey:null!==(n=null==e?void 0:e.shortcutKey)&&void 0!==n?n:l.shortcutKey,asrApi:null!==(o=null==e?void 0:e.asrApi)&&void 0!==o?o:l.asrApi,publicKey:null!==(r=null==e?void 0:e.publicKey)&&void 0!==r?r:l.publicKey,targetLang:null!==(i=null==e?void 0:e.targetLang)&&void 0!==i?i:l.targetLang})}function ce(e){if(!1!==(null==e?void 0:e.enabled)){var t=e?{publicKey:e.publicKey,targetLang:e.targetLang,envPrefix:e.envPrefix}:void 0;"loading"===document.readyState?document.addEventListener("DOMContentLoaded",function(){de(t)}):de(t)}}function _e(e){!function(e){ue({publicKey:e}),Q().catch(function(){})}(e)}function me(e){!function(e){s({targetLang:e})}(e)}var fe={init:ce,setPublicKey:_e,setTargetLang:me},pe={InputListener:Object.freeze({__proto__:null,InputListener:fe,initInputListenerSDK:ce,setPublicKey:_e,setTargetLang:me})};function ge(e){ce(e)}export{fe as InputListener,pe as SDKs,ce as initInputListenerSDK,ge as initSDK,_e as setPublicKey,me as setTargetLang};
1
+ import * as React$1 from 'react';
2
+ import React__default, { useState, useEffect } from 'react';
3
+ import * as BundledReactDOMClient from 'react-dom/client';
4
+
5
+ // 统一状态管理
6
+ var STREAM_API_PATH = '/v1/asr/input_stream';
7
+ function getDefaultAsrApiUrl(mode) {
8
+ var _a;
9
+ var path = STREAM_API_PATH;
10
+ // 注意:这里不能使用 getState() 因为会造成递归调用
11
+ // getState() 会调用 initWindowObject(),而 initWindowObject() 中调用了 getDefaultAsrApiUrl()
12
+ var state = typeof window !== 'undefined' ? (_a = window.senseAiHelperSdk) === null || _a === void 0 ? void 0 : _a.inputListener : null;
13
+ var envPrefix = (state === null || state === void 0 ? void 0 : state.envPrefix) || 'staging';
14
+ var domain = "".concat(envPrefix, ".api.senseaudio.cn") ;
15
+ return "https://".concat(domain).concat(path);
16
+ }
17
+ function initWindowObject() {
18
+ if (typeof window === 'undefined')
19
+ return;
20
+ if (!window.senseAiHelperSdk) {
21
+ window.senseAiHelperSdk = {};
22
+ }
23
+ if (!window.senseAiHelperSdk.inputListener) {
24
+ window.senseAiHelperSdk.inputListener = {
25
+ // 默认快捷键:Alt/Option(左右两边都可触发)
26
+ shortcutKey: { key: 'Alt' },
27
+ recognitionLang: 'zh-CN',
28
+ asrApi: { url: getDefaultAsrApiUrl(), headers: {}, mode: 'stream' },
29
+ publicKey: '',
30
+ targetLang: 'None',
31
+ model: 'sense-asr-deepthink',
32
+ envPrefix: 'staging',
33
+ authToken: null,
34
+ authTokenPromise: null,
35
+ selectedText: '',
36
+ currentInputElement: null,
37
+ isKeyPressed: false,
38
+ isRecordingStarting: false,
39
+ isIndicatorShown: false,
40
+ mediaRecorder: null,
41
+ audioChunks: [],
42
+ isRecording: false,
43
+ recognizedText: '',
44
+ interimText: '',
45
+ audioContext: null,
46
+ audioAnalyser: null,
47
+ audioAnalysisFrameId: null,
48
+ currentVolumes: null,
49
+ statusIndicatorRoot: null,
50
+ toastRoot: null,
51
+ currentIndicatorStatus: undefined,
52
+ isHidingIndicator: false,
53
+ hideIndicatorTimer: null,
54
+ isCreatingIndicator: false,
55
+ rewriteResultRoot: null,
56
+ onRecordingStart: null,
57
+ onRecordingUpdate: null,
58
+ onRecordingEnd: null,
59
+ onError: null,
60
+ shouldContinueRecording: function () { return false; },
61
+ isInitialized: false,
62
+ };
63
+ }
64
+ }
65
+ function getState() {
66
+ initWindowObject();
67
+ return window.senseAiHelperSdk.inputListener;
68
+ }
69
+ function updateState(updates) {
70
+ var state = getState();
71
+ Object.assign(state, updates);
72
+ }
73
+
74
+ /******************************************************************************
75
+ Copyright (c) Microsoft Corporation.
76
+
77
+ Permission to use, copy, modify, and/or distribute this software for any
78
+ purpose with or without fee is hereby granted.
79
+
80
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
81
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
82
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
83
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
84
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
85
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
86
+ PERFORMANCE OF THIS SOFTWARE.
87
+ ***************************************************************************** */
88
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
89
+
90
+
91
+ var __assign = function() {
92
+ __assign = Object.assign || function __assign(t) {
93
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
94
+ s = arguments[i];
95
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
96
+ }
97
+ return t;
98
+ };
99
+ return __assign.apply(this, arguments);
100
+ };
101
+
102
+ function __awaiter(thisArg, _arguments, P, generator) {
103
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
104
+ return new (P || (P = Promise))(function (resolve, reject) {
105
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
106
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
107
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
108
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
109
+ });
110
+ }
111
+
112
+ function __generator(thisArg, body) {
113
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
114
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
115
+ function verb(n) { return function (v) { return step([n, v]); }; }
116
+ function step(op) {
117
+ if (f) throw new TypeError("Generator is already executing.");
118
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
119
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
120
+ if (y = 0, t) op = [op[0] & 2, t.value];
121
+ switch (op[0]) {
122
+ case 0: case 1: t = op; break;
123
+ case 4: _.label++; return { value: op[1], done: false };
124
+ case 5: _.label++; y = op[1]; op = [0]; continue;
125
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
126
+ default:
127
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
128
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
129
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
130
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
131
+ if (t[2]) _.ops.pop();
132
+ _.trys.pop(); continue;
133
+ }
134
+ op = body.call(thisArg, _);
135
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
136
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
137
+ }
138
+ }
139
+
140
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
141
+ var e = new Error(message);
142
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
143
+ };
144
+
145
+ function styleInject(css, ref) {
146
+ if ( ref === void 0 ) ref = {};
147
+ var insertAt = ref.insertAt;
148
+
149
+ if (!css || typeof document === 'undefined') { return; }
150
+
151
+ var head = document.head || document.getElementsByTagName('head')[0];
152
+ var style = document.createElement('style');
153
+ style.type = 'text/css';
154
+
155
+ if (insertAt === 'top') {
156
+ if (head.firstChild) {
157
+ head.insertBefore(style, head.firstChild);
158
+ } else {
159
+ head.appendChild(style);
160
+ }
161
+ } else {
162
+ head.appendChild(style);
163
+ }
164
+
165
+ if (style.styleSheet) {
166
+ style.styleSheet.cssText = css;
167
+ } else {
168
+ style.appendChild(document.createTextNode(css));
169
+ }
170
+ }
171
+
172
+ var css_248z$2 = "@keyframes StatusIndicator-module__slideIn___g7A8l {\n from {\n transform: translateX(100%);\n opacity: 0;\n }\n to {\n transform: translateX(0);\n opacity: 1;\n }\n}\n@keyframes StatusIndicator-module__slideOut___7BI02 {\n from {\n transform: translateX(0);\n opacity: 1;\n }\n to {\n transform: translateX(100%);\n opacity: 0;\n }\n}\n@keyframes StatusIndicator-module__fadeIn___-ft5Z {\n from {\n opacity: 0;\n transform: translate(-50%, 10px);\n }\n to {\n opacity: 1;\n transform: translate(-50%, 0);\n }\n}\n@keyframes StatusIndicator-module__fadeOut___S2Lbf {\n from {\n opacity: 1;\n transform: translate(-50%, 0);\n }\n to {\n opacity: 0;\n transform: translate(-50%, 10px);\n }\n}\n@keyframes StatusIndicator-module__waveAnimation___eM33k {\n 0%, 100% {\n height: 6px;\n }\n 25% {\n height: 18px;\n }\n 50% {\n height: 30px;\n }\n 75% {\n height: 18px;\n }\n}\n@keyframes StatusIndicator-module__spin___9Y9Qv {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes StatusIndicator-module__loadingDots___tV9-o {\n 0%, 80%, 100% {\n transform: scale(0.6);\n opacity: 0.5;\n }\n 40% {\n transform: scale(1);\n opacity: 1;\n }\n}\n@keyframes StatusIndicator-module__rotatePoints___jYhWY {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n.StatusIndicator-module__statusIndicator___joWb0 {\n position: fixed;\n bottom: -30px;\n left: 50%;\n transform: translate(-50%, 0);\n display: flex;\n width: 171px;\n height: 49.5px;\n padding: 12px 16.5px 12px 12px;\n justify-content: center;\n align-items: flex-start;\n gap: 3px;\n border-radius: 27px;\n border: 1px solid var(--Angular, #FFC876);\n background: linear-gradient(180deg, #14192F 0%, #252C4A 100%);\n box-shadow: 0 4px 24px 0 rgba(36, 54, 134, 0.25);\n z-index: 2147483647;\n animation: StatusIndicator-module__fadeIn___-ft5Z 0.3s ease-out;\n box-sizing: border-box;\n}\n.StatusIndicator-module__statusIndicator___joWb0.StatusIndicator-module__hiding___sv8Jg {\n animation: StatusIndicator-module__fadeOut___S2Lbf 0.3s ease-out;\n}\n\n.StatusIndicator-module__waveContainer___1DHzO {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n}\n\n.StatusIndicator-module__waveBarsContainer___MOYeO {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 25.5px;\n}\n\n.StatusIndicator-module__waveCanvas___XUPyx {\n width: 100%;\n height: 100%;\n display: block;\n}\n\n.StatusIndicator-module__dotsContainer___BOEoa {\n display: flex;\n align-items: center;\n gap: 9px;\n height: 36px;\n}\n\n.StatusIndicator-module__dot___A5ESi {\n width: 9px;\n height: 6px;\n background: white;\n border-radius: 50%;\n opacity: 0.6;\n}\n\n.StatusIndicator-module__loadingWithWaveContainer___DG1Yx {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n width: 100%;\n height: 100%;\n}\n\n.StatusIndicator-module__loadingDots___tV9-o {\n display: flex;\n align-items: center;\n gap: 4.5px;\n flex-shrink: 0;\n}\n\n.StatusIndicator-module__loadingDot___zwgLy {\n width: 6px;\n height: 6px;\n background: white;\n border-radius: 50%;\n animation: StatusIndicator-module__loadingDots___tV9-o 1.4s ease-in-out infinite;\n}\n.StatusIndicator-module__loadingDot___zwgLy:nth-child(1) {\n animation-delay: 0s;\n}\n.StatusIndicator-module__loadingDot___zwgLy:nth-child(2) {\n animation-delay: 0.2s;\n}\n.StatusIndicator-module__loadingDot___zwgLy:nth-child(3) {\n animation-delay: 0.4s;\n}\n\n.StatusIndicator-module__rotatingPoints___P6lwm {\n position: relative;\n width: 24px;\n height: 24px;\n flex-shrink: 0;\n animation: StatusIndicator-module__rotatePoints___jYhWY 1s linear infinite;\n}\n\n.StatusIndicator-module__rotatingPoint___QmHOY {\n position: absolute;\n width: 3px;\n height: 6px;\n background: white;\n border-radius: 1.5px;\n top: 50%;\n left: 50%;\n margin-top: -3px;\n margin-left: -1.5px;\n transform-origin: center center;\n}\n.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(1) {\n transform: rotate(0deg) translateY(-7.5px);\n opacity: 0.25;\n}\n.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(2) {\n transform: rotate(45deg) translateY(-7.5px);\n opacity: 0.4;\n}\n.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(3) {\n transform: rotate(90deg) translateY(-7.5px);\n opacity: 0.55;\n}\n.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(4) {\n transform: rotate(135deg) translateY(-7.5px);\n opacity: 0.7;\n}\n.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(5) {\n transform: rotate(180deg) translateY(-7.5px);\n opacity: 0.85;\n}\n.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(6) {\n transform: rotate(225deg) translateY(-7.5px);\n opacity: 0.95;\n}\n.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(7) {\n transform: rotate(270deg) translateY(-7.5px);\n opacity: 1;\n}\n.StatusIndicator-module__rotatingPoint___QmHOY:nth-child(8) {\n transform: rotate(315deg) translateY(-7.5px);\n opacity: 0.95;\n}\n\n.StatusIndicator-module__loadingContainer___5w5a0 {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n}\n\n.StatusIndicator-module__loadingOverlay___wLfWy {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.3);\n border-radius: 12px;\n backdrop-filter: blur(2px);\n}\n\n.StatusIndicator-module__spinner___j8wsu {\n width: 24px;\n height: 24px;\n border: 3px solid rgba(255, 255, 255, 0.3);\n border-top-color: white;\n border-radius: 50%;\n animation: StatusIndicator-module__spin___9Y9Qv 0.8s linear infinite;\n}\n\n.StatusIndicator-module__waveBar___irNLu {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: height 0.1s ease-out;\n align-self: center;\n}";
173
+ var styles$2 = {"statusIndicator":"StatusIndicator-module__statusIndicator___joWb0","hiding":"StatusIndicator-module__hiding___sv8Jg","waveContainer":"StatusIndicator-module__waveContainer___1DHzO","waveBarsContainer":"StatusIndicator-module__waveBarsContainer___MOYeO","dotsContainer":"StatusIndicator-module__dotsContainer___BOEoa","dot":"StatusIndicator-module__dot___A5ESi","loadingWithWaveContainer":"StatusIndicator-module__loadingWithWaveContainer___DG1Yx","rotatingPoints":"StatusIndicator-module__rotatingPoints___P6lwm","rotatingPoint":"StatusIndicator-module__rotatingPoint___QmHOY","waveBar":"StatusIndicator-module__waveBar___irNLu"};
174
+ styleInject(css_248z$2);
175
+
176
+ // 波形绘制样式配置
177
+ // 可以在这里修改所有波形相关的样式参数
178
+ // 默认配置
179
+ var defaultWaveBarConfig = {
180
+ barCount: 13, // 9 + 4
181
+ maxBarHeight: 25.5, // 17 * 1.5
182
+ minBarHeight: 4.5, // 3 * 1.5,最小高度,接近点的形式,声音小时波形条会收缩到这里
183
+ barWidth: 4.5, // 3 * 1.5
184
+ gap: 3, // 2 * 1.5
185
+ borderRadius: 2.25 // 1.5 * 1.5
186
+ };
187
+ var defaultWaveColorsConfig = {
188
+ gradientStart: '#ffffff',
189
+ gradientMiddle: '#f0f0f0',
190
+ gradientEnd: '#ffffff'
191
+ };
192
+ var defaultWaveAnimationConfig = {
193
+ interpolationFactor: 0.7};
194
+ // 导出完整配置对象
195
+ var waveConfig = {
196
+ bar: defaultWaveBarConfig,
197
+ colors: defaultWaveColorsConfig,
198
+ animation: defaultWaveAnimationConfig};
199
+ // 用于 loading 状态的静态波形条配置
200
+ var staticWaveConfig = __assign(__assign({}, defaultWaveBarConfig), {
201
+ // 静态波形条使用固定的中等高度(50%)
202
+ staticHeightRatio: 0.5 });
203
+
204
+ var WaveBars = function (_a) {
205
+ var volumes = _a.volumes, _b = _a.isStatic, isStatic = _b === void 0 ? false : _b, _c = _a.className, className = _c === void 0 ? '' : _c;
206
+ // 初始化时使用最小高度(接近点的形式),声音小时会收缩到这里
207
+ var _d = useState(new Array(waveConfig.bar.barCount).fill(waveConfig.bar.minBarHeight)), barHeights = _d[0], setBarHeights = _d[1];
208
+ // 更新波形条高度
209
+ useEffect(function () {
210
+ if (isStatic) {
211
+ // 静态波形:使用固定高度(从最小高度向上扩展)
212
+ var bar_1 = waveConfig.bar;
213
+ var heightRange_1 = bar_1.maxBarHeight - bar_1.minBarHeight;
214
+ var staticHeightRatio_1 = staticWaveConfig.staticHeightRatio;
215
+ var heights = new Array(bar_1.barCount).fill(0).map(function (_, i) {
216
+ var centerIndex = (bar_1.barCount - 1) / 2;
217
+ var distanceFromCenter = Math.abs(i - centerIndex);
218
+ var maxDistance = centerIndex;
219
+ // 使用平方函数让递减更平缓,与动态波形保持一致
220
+ var normalizedDistance = distanceFromCenter / maxDistance;
221
+ var baseSymmetry = 1 - Math.pow(normalizedDistance, 2) * 0.4;
222
+ // 限制对称因子范围:最小 0.6,最大 1.0
223
+ var symmetry = Math.max(0.6, Math.min(1.0, baseSymmetry));
224
+ // 从最小高度向上扩展,使用静态高度比例
225
+ return bar_1.minBarHeight + symmetry * heightRange_1 * staticHeightRatio_1;
226
+ });
227
+ setBarHeights(heights);
228
+ return;
229
+ }
230
+ if (!volumes || volumes.length === 0) {
231
+ return;
232
+ }
233
+ var bar = waveConfig.bar, animation = waveConfig.animation;
234
+ var heightRange = bar.maxBarHeight - bar.minBarHeight;
235
+ // 计算每个波形条的目标高度
236
+ setBarHeights(function (prevHeights) {
237
+ var centerIndex = (bar.barCount - 1) / 2;
238
+ return prevHeights.map(function (prevHeight, i) {
239
+ // 获取当前频段的音量值 (0-255)
240
+ var rawVolume = volumes[i] || 0;
241
+ // 计算对称位置(让左右两侧使用相同的音频数据,实现对称)
242
+ var distanceFromCenter = i - centerIndex;
243
+ var symmetricIndex = Math.round(centerIndex - distanceFromCenter);
244
+ // 使用对称位置的音频数据,如果对称位置不存在则使用当前位置
245
+ var symmetricVolume = volumes[Math.max(0, Math.min(bar.barCount - 1, symmetricIndex))] || 0;
246
+ // 混合当前位置和对称位置的音频数据,实现对称效果
247
+ var mixedVolume = (rawVolume + symmetricVolume) / 2;
248
+ // 归一化到 0-1 范围,使用平方根增强低音量的响应
249
+ var normalizedVolume = Math.sqrt(Math.min(mixedVolume / 255, 1));
250
+ // 计算对称因子(中心高,两边低)
251
+ var absDistanceFromCenter = Math.abs(distanceFromCenter);
252
+ var maxDistance = centerIndex;
253
+ // 对称因子:中心为 1,向两边递减
254
+ var normalizedDistance = absDistanceFromCenter / maxDistance; // 0-1
255
+ // 使用更平缓的曲线,让两侧也有明显波动
256
+ // 计算基础对称因子:使用平方函数让递减更平缓,同时确保两侧不会太低
257
+ // 使用较小的系数,让递减更温和
258
+ var baseSymmetryFactor = 1 - Math.pow(normalizedDistance, 2) * 0.4;
259
+ // 限制对称因子范围:最小 0.6(保证两侧有 60% 的波动范围),最大 1.0
260
+ // 这样即使是最外侧的条,也能有 60% 的高度范围可以波动,不会太低
261
+ var symmetryFactor = Math.max(0.6, Math.min(1.0, baseSymmetryFactor));
262
+ // 基础高度:音量 * 对称因子 * 高度范围 + 最小高度
263
+ // 使用平方根曲线让响应更自然
264
+ var targetHeight = bar.minBarHeight + normalizedVolume * symmetryFactor * heightRange;
265
+ // 平滑插值过渡
266
+ var interpolationFactor = animation.interpolationFactor;
267
+ var newHeight = prevHeight + (targetHeight - prevHeight) * interpolationFactor;
268
+ // 确保高度在有效范围内
269
+ return Math.max(bar.minBarHeight, Math.min(newHeight, bar.maxBarHeight));
270
+ });
271
+ });
272
+ }, [volumes, isStatic]);
273
+ var bar = waveConfig.bar, colors = waveConfig.colors;
274
+ return (React__default.createElement("div", { className: "".concat(styles$2.waveContainer, " ").concat(styles$2.waveBarsContainer, " ").concat(className) }, barHeights.map(function (height, index) {
275
+ var isLast = index === bar.barCount - 1;
276
+ return (React__default.createElement("div", { key: index, className: styles$2.waveBar, style: {
277
+ background: "linear-gradient(to bottom, ".concat(colors.gradientStart, ", ").concat(colors.gradientMiddle, ", ").concat(colors.gradientEnd, ")"),
278
+ width: "".concat(bar.barWidth, "px"),
279
+ height: "".concat(height, "px"),
280
+ borderRadius: "".concat(bar.borderRadius, "px"),
281
+ marginRight: isLast ? '0' : "".concat(bar.gap, "px")
282
+ } }));
283
+ })));
284
+ };
285
+
286
+ var StatusIndicator = function (_a) {
287
+ var status = _a.status, _b = _a.isHiding, isHiding = _b === void 0 ? false : _b, volumes = _a.volumes;
288
+ // 根据不同的状态渲染对应的内容
289
+ var renderContent = function () {
290
+ // 录入状态(正在说话):显示麦克风图标和动态波形条
291
+ if (status === 'speaking') {
292
+ return (React$1.createElement("div", { className: styles$2.loadingWithWaveContainer },
293
+ React$1.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 16 16", fill: "none" },
294
+ React$1.createElement("path", { d: "M8 12.6665V14.6665", stroke: "url(#paint0_linear_1445_38138)", strokeWidth: "1.66667", strokeLinecap: "round", strokeLinejoin: "round" }),
295
+ React$1.createElement("path", { d: "M10.3337 3.66683C10.3337 2.37817 9.28899 1.3335 8.00033 1.3335C6.71166 1.3335 5.66699 2.37817 5.66699 3.66683V8.00016C5.66699 9.28883 6.71166 10.3335 8.00033 10.3335C9.28899 10.3335 10.3337 9.28883 10.3337 8.00016V3.66683Z", fill: "url(#paint1_linear_1445_38138)", stroke: "url(#paint2_linear_1445_38138)", strokeWidth: "1.66667", strokeLinejoin: "round" }),
296
+ React$1.createElement("path", { d: "M3 7.6665C3 10.4279 5.23857 12.6665 8 12.6665C10.7614 12.6665 13 10.4279 13 7.6665", stroke: "url(#paint3_linear_1445_38138)", strokeWidth: "1.66667", strokeLinecap: "round", strokeLinejoin: "round" }),
297
+ React$1.createElement("defs", null,
298
+ React$1.createElement("linearGradient", { id: "paint0_linear_1445_38138", x1: "8.5", y1: "12.6665", x2: "8.5", y2: "14.6665", gradientUnits: "userSpaceOnUse" },
299
+ React$1.createElement("stop", { stopColor: "#ECFAFF" }),
300
+ React$1.createElement("stop", { offset: "1", stopColor: "#BDC8FD" })),
301
+ React$1.createElement("linearGradient", { id: "paint1_linear_1445_38138", x1: "8.00033", y1: "1.3335", x2: "8.00033", y2: "10.3335", gradientUnits: "userSpaceOnUse" },
302
+ React$1.createElement("stop", { stopColor: "#ECFAFF" }),
303
+ React$1.createElement("stop", { offset: "1", stopColor: "#BDC8FD" })),
304
+ React$1.createElement("linearGradient", { id: "paint2_linear_1445_38138", x1: "8.00033", y1: "1.3335", x2: "8.00033", y2: "10.3335", gradientUnits: "userSpaceOnUse" },
305
+ React$1.createElement("stop", { stopColor: "#ECFAFF" }),
306
+ React$1.createElement("stop", { offset: "1", stopColor: "#BDC8FD" })),
307
+ React$1.createElement("linearGradient", { id: "paint3_linear_1445_38138", x1: "8", y1: "7.6665", x2: "8", y2: "12.6665", gradientUnits: "userSpaceOnUse" },
308
+ React$1.createElement("stop", { stopColor: "#ECFAFF" }),
309
+ React$1.createElement("stop", { offset: "1", stopColor: "#BDC8FD" })))),
310
+ React$1.createElement(WaveBars, { volumes: volumes, isStatic: false })));
311
+ }
312
+ else if (status === 'silent') {
313
+ // 静音状态:显示点状动画
314
+ return (React$1.createElement("div", { className: styles$2.loadingWithWaveContainer },
315
+ React$1.createElement("div", { className: styles$2.dotsContainer }, Array.from({ length: 10 }).map(function (_, i) { return (React$1.createElement("div", { key: i, className: styles$2.dot })); }))));
316
+ }
317
+ else if (status === 'loading') {
318
+ // 加载状态:同时显示静止的波形条和旋转加载点(加载点在右边)
319
+ return (React$1.createElement("div", { className: styles$2.loadingWithWaveContainer },
320
+ React$1.createElement("div", { className: styles$2.rotatingPoints }, Array.from({ length: 8 }).map(function (_, i) { return (React$1.createElement("div", { key: i, className: styles$2.rotatingPoint })); })),
321
+ React$1.createElement(WaveBars, { isStatic: true })));
322
+ }
323
+ return null;
324
+ };
325
+ var className = [
326
+ styles$2.statusIndicator,
327
+ isHiding ? styles$2.hiding : '',
328
+ status === 'loading' ? styles$2.loadingWithWave : ''
329
+ ].filter(Boolean).join(' ');
330
+ return (React$1.createElement("div", { id: "sdk-status-indicator", className: className }, renderContent()));
331
+ };
332
+
333
+ var css_248z$1 = "@keyframes Toast-module__slideIn___OVESo {\n from {\n transform: translate(-50%, -100%);\n opacity: 0;\n }\n to {\n transform: translate(-50%, 0);\n opacity: 1;\n }\n}\n@keyframes Toast-module__slideOut___M2e0e {\n from {\n transform: translate(-50%, 0);\n opacity: 1;\n }\n to {\n transform: translate(-50%, -100%);\n opacity: 0;\n }\n}\n.Toast-module__toast___TNqrY {\n position: fixed;\n top: 20px;\n left: 50%;\n transform: translateX(-50%);\n padding: 6px 14px;\n border-radius: 8px;\n z-index: 2147483647;\n font-size: 14px;\n font-family: Arial, sans-serif;\n animation: Toast-module__slideIn___OVESo 0.3s ease-out;\n}\n.Toast-module__toast___TNqrY.Toast-module__success___NZdm8 {\n border: 1px solid #fde2e2;\n color: #f67e7e;\n background-color: #6bff8d;\n}\n.Toast-module__toast___TNqrY.Toast-module__error___yF0Tc {\n border: 1px solid #fde2e2;\n color: #f67e7e;\n background-color: #fef0f0;\n}\n.Toast-module__toast___TNqrY.Toast-module__info___lUXoo {\n border: 1px solid #faecd8;\n color: #eaae55;\n background-color: #fdf6ec;\n}\n.Toast-module__toast___TNqrY.Toast-module__hiding___mUWl5 {\n animation: Toast-module__slideOut___M2e0e 0.3s ease-out;\n}";
334
+ var styles$1 = {"toast":"Toast-module__toast___TNqrY","slideIn":"Toast-module__slideIn___OVESo","success":"Toast-module__success___NZdm8","error":"Toast-module__error___yF0Tc","info":"Toast-module__info___lUXoo","hiding":"Toast-module__hiding___mUWl5","slideOut":"Toast-module__slideOut___M2e0e"};
335
+ styleInject(css_248z$1);
336
+
337
+ var Toast = function (_a) {
338
+ var message = _a.message, _b = _a.type, type = _b === void 0 ? 'success' : _b, _c = _a.duration, duration = _c === void 0 ? 2000 : _c, onClose = _a.onClose;
339
+ React$1.useEffect(function () {
340
+ var timer = setTimeout(function () {
341
+ onClose();
342
+ }, duration);
343
+ return function () { return clearTimeout(timer); };
344
+ }, [duration, onClose]);
345
+ var className = [
346
+ styles$1.toast,
347
+ styles$1[type]
348
+ ].filter(Boolean).join(' ');
349
+ return (React$1.createElement("div", { className: className }, message));
350
+ };
351
+
352
+ var css_248z = "@keyframes RewriteResult-module__sdk-rewrite-fade-in___tItTw {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n.RewriteResult-module__overlay___4tJMY {\n display: flex;\n align-items: flex-end;\n justify-content: center;\n width: 100%;\n height: 100%;\n pointer-events: none;\n}\n\n.RewriteResult-module__popup___IjoJz {\n pointer-events: auto;\n background: rgba(0, 0, 0, 0.85);\n color: #fff;\n border-radius: 12px;\n padding: 16px 20px;\n min-width: 280px;\n max-width: 480px;\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);\n display: flex;\n flex-direction: column;\n gap: 12px;\n font-size: 14px;\n animation: RewriteResult-module__sdk-rewrite-fade-in___tItTw 180ms ease-out;\n}\n\n.RewriteResult-module__header___cheJF {\n display: flex;\n justify-content: flex-end;\n align-items: center;\n}\n\n.RewriteResult-module__close___D9aIV {\n border: none;\n background: transparent;\n color: #fff;\n cursor: pointer;\n font-size: 16px;\n padding: 0;\n line-height: 1;\n position: absolute;\n top: 8px;\n right: 16px;\n}\n\n.RewriteResult-module__body___vQYaF {\n background: rgba(255, 255, 255, 0.08);\n border-radius: 8px;\n padding: 12px;\n line-height: 1.5;\n word-break: break-word;\n}\n\n.RewriteResult-module__footer___68OdM {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n\n.RewriteResult-module__primary___MIFKB {\n border: none;\n background: #4b8cf7;\n color: #fff;\n border-radius: 8px;\n padding: 8px 14px;\n cursor: pointer;\n font-weight: 600;\n transition: background 120ms ease;\n}\n.RewriteResult-module__primary___MIFKB:hover {\n background: #3b79e0;\n}\n.RewriteResult-module__primary___MIFKB:active {\n background: #2f67c4;\n}\n\n/* From Uiverse.io by Cksunandh */\n.RewriteResult-module__m2___cEJhO {\n position: relative;\n pointer-events: auto;\n border-radius: 12px;\n padding: 16px 20px;\n min-width: 280px;\n max-width: 480px;\n background: linear-gradient(135deg, #1e1e24 10%, #050505 60%);\n display: flex;\n flex-direction: column;\n gap: 12px;\n align-items: center;\n justify-content: center;\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n animation: RewriteResult-module__gradient-shift___vfj5d 5s ease-in-out infinite; /* Faster animation */\n background-size: 100% 100%; /* Gradient shift */\n}\n\n.RewriteResult-module__m2___cEJhO .RewriteResult-module__logo___hbjf0 {\n display: inline-block;\n vertical-align: baseline;\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n font-size: 14px; /* Smaller font size */\n color: #fff; /* Ensure solid white text */\n background: none;\n background-clip: initial;\n -webkit-background-clip: initial;\n -webkit-text-fill-color: currentColor;\n font-weight: bold;\n}\n\n.RewriteResult-module__m2___cEJhO .RewriteResult-module__logo___hbjf0 svg {\n margin-right: -1vmin;\n width: 5vmin; /* Smaller SVG size */\n height: 5vmin; /* Smaller SVG size */\n}\n\n.RewriteResult-module__m2___cEJhO::after {\n --size: 1px; /* Smaller inner glow size */\n z-index: -1;\n}\n\n.RewriteResult-module__m2___cEJhO::before {\n --size: 6px; /* Smaller outer glow size */\n z-index: -2;\n filter: blur(1vmin); /* Softer blur */\n animation: RewriteResult-module__blur-animation___tZWlQ 3s ease-in-out alternate infinite; /* Faster blur animation */\n}\n\n/* Faster blur animation */\n@keyframes RewriteResult-module__blur-animation___tZWlQ {\n to {\n filter: blur(3vmin);\n transform: scale(1.05);\n }\n}\n/* Faster gradient animation */\n@keyframes RewriteResult-module__gradient-shift___vfj5d {\n 0% {\n background-position: 0% 50%;\n }\n 50% {\n background-position: 100% 50%;\n }\n 100% {\n background-position: 0% 50%;\n }\n}\n/* From Uiverse.io by nima-mollazadeh */\n.RewriteResult-module__button___nLV0i {\n position: relative;\n text-decoration: none;\n color: #fff;\n background: linear-gradient(45deg, #0ce39a, #69007f, #fc0987);\n padding: 6px 24px;\n border-radius: 10px;\n font-size: 14px;\n font-weight: bold;\n cursor: pointer;\n pointer-events: auto;\n}\n\n.RewriteResult-module__button___nLV0i span {\n position: relative;\n z-index: 1;\n}\n\n.RewriteResult-module__button___nLV0i::before {\n content: \"\";\n position: absolute;\n inset: 1px;\n background: #272727;\n border-radius: 9px;\n transition: 0.5s;\n}\n\n.RewriteResult-module__button___nLV0i:hover::before {\n opacity: 0.7;\n}\n\n.RewriteResult-module__button___nLV0i::after {\n content: \"\";\n position: absolute;\n inset: 0px;\n background: linear-gradient(45deg, #0ce39a, #69007f, #fc0987);\n border-radius: 9px;\n transition: 0.5s;\n opacity: 0;\n filter: blur(20px);\n}\n\n.RewriteResult-module__button___nLV0i:hover:after {\n opacity: 1;\n}";
353
+ var styles = {"overlay":"RewriteResult-module__overlay___4tJMY","header":"RewriteResult-module__header___cheJF","close":"RewriteResult-module__close___D9aIV","body":"RewriteResult-module__body___vQYaF","footer":"RewriteResult-module__footer___68OdM","m2":"RewriteResult-module__m2___cEJhO","logo":"RewriteResult-module__logo___hbjf0","button":"RewriteResult-module__button___nLV0i"};
354
+ styleInject(css_248z);
355
+
356
+ var RewriteResult = function (_a) {
357
+ var text = _a.text, onClose = _a.onClose, onCopy = _a.onCopy;
358
+ return (React__default.createElement("div", { className: styles.overlay },
359
+ React__default.createElement("div", { className: styles.m2 },
360
+ React__default.createElement("div", { className: styles.header },
361
+ React__default.createElement("button", { className: styles.close, onClick: onClose, "aria-label": "close" }, "\u00D7")),
362
+ React__default.createElement("div", { className: styles.logo },
363
+ React__default.createElement("div", { className: styles.body }, text)),
364
+ React__default.createElement("div", { className: styles.footer },
365
+ React__default.createElement("button", { onClick: onCopy, className: styles.button },
366
+ React__default.createElement("span", null, "\u590D\u5236"))))));
367
+ };
368
+
369
+ // UI 功能:使用 React DOM 渲染组件
370
+ // 智能获取 React:优先使用全局的,如果没有再使用打包进来的
371
+ function getReact() {
372
+ if (typeof window !== 'undefined' && window.React) {
373
+ return window.React;
374
+ }
375
+ return React$1;
376
+ }
377
+ // 智能获取 ReactDOM:优先使用全局的,如果没有再使用打包进来的
378
+ // 兼容 React 17, 18, 19
379
+ function getReactDOM() {
380
+ // 首先尝试从全局获取 ReactDOM(用户项目中的 React)
381
+ if (typeof window !== 'undefined' && window.ReactDOM) {
382
+ var globalReactDOM = window.ReactDOM;
383
+ // React 18+: 尝试使用 createRoot
384
+ if (globalReactDOM.createRoot) {
385
+ return { createRoot: globalReactDOM.createRoot };
386
+ }
387
+ }
388
+ // 尝试从全局 ReactDOMClient 获取(React 18+ UMD 格式)
389
+ if (typeof window !== 'undefined' && window.ReactDOMClient) {
390
+ var globalReactDOMClient = window.ReactDOMClient;
391
+ if (globalReactDOMClient.createRoot) {
392
+ return { createRoot: globalReactDOMClient.createRoot };
393
+ }
394
+ }
395
+ // 降级到打包进来的 ReactDOMClient(React 18+)
396
+ if (BundledReactDOMClient && typeof BundledReactDOMClient.createRoot === 'function') {
397
+ return BundledReactDOMClient;
398
+ }
399
+ return BundledReactDOMClient;
400
+ }
401
+ var React = getReact();
402
+ var ReactDOM = getReactDOM();
403
+ // 初始化 Toast 容器
404
+ function initToastContainer() {
405
+ var state = getState();
406
+ if (state.toastRoot)
407
+ return;
408
+ var container = document.getElementById('sdk-toast-container');
409
+ if (!container) {
410
+ container = document.createElement('div');
411
+ container.id = 'sdk-toast-container';
412
+ container.style.cssText = 'position:fixed;top:0;right:0;z-index:2147483647;pointer-events:none';
413
+ document.body.appendChild(container);
414
+ }
415
+ try {
416
+ updateState({ toastRoot: ReactDOM.createRoot(container) });
417
+ }
418
+ catch (e) {
419
+ // ReactDOM 不可用
420
+ }
421
+ }
422
+ // 初始化重写结果容器
423
+ function initRewriteResultContainer() {
424
+ var state = getState();
425
+ if (state.rewriteResultRoot)
426
+ return;
427
+ var container = document.getElementById('sdk-rewrite-result-container');
428
+ if (!container) {
429
+ container = document.createElement('div');
430
+ container.id = 'sdk-rewrite-result-container';
431
+ container.style.cssText = 'position:fixed;inset:0;z-index:2147483647;display:flex;align-items:flex-end;justify-content:center;pointer-events:none;padding:40px';
432
+ document.body.appendChild(container);
433
+ }
434
+ try {
435
+ updateState({ rewriteResultRoot: ReactDOM.createRoot(container) });
436
+ }
437
+ catch (e) {
438
+ // ReactDOM 不可用
439
+ }
440
+ }
441
+ // 初始化状态指示器容器
442
+ function initStatusIndicatorContainer() {
443
+ var state = getState();
444
+ if (state.statusIndicatorRoot)
445
+ return;
446
+ var container = document.getElementById('sdk-status-indicator-container');
447
+ if (!container) {
448
+ container = document.createElement('div');
449
+ container.id = 'sdk-status-indicator-container';
450
+ container.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:2147483647';
451
+ document.body.appendChild(container);
452
+ }
453
+ try {
454
+ updateState({ statusIndicatorRoot: ReactDOM.createRoot(container) });
455
+ }
456
+ catch (e) {
457
+ // ReactDOM 不可用
458
+ }
459
+ }
460
+ // 显示状态指示器
461
+ function showStatusIndicator(status) {
462
+ var state = getState();
463
+ if (state.isCreatingIndicator)
464
+ return;
465
+ if (state.isHidingIndicator && state.hideIndicatorTimer !== null) {
466
+ clearTimeout(state.hideIndicatorTimer);
467
+ updateState({ hideIndicatorTimer: null, isHidingIndicator: false });
468
+ }
469
+ if (!React || !ReactDOM)
470
+ return;
471
+ if (state.currentIndicatorStatus === status && state.statusIndicatorRoot) {
472
+ if (status === 'speaking') {
473
+ updateStatusIndicatorVolumes();
474
+ }
475
+ return;
476
+ }
477
+ updateState({ isCreatingIndicator: true });
478
+ try {
479
+ initStatusIndicatorContainer();
480
+ if (!state.statusIndicatorRoot) {
481
+ updateState({ isCreatingIndicator: false });
482
+ return;
483
+ }
484
+ var wrapper = React.createElement('div', {
485
+ id: 'sdk-status-indicator-wrapper',
486
+ style: {
487
+ position: 'fixed',
488
+ bottom: '100px',
489
+ left: '50%',
490
+ transform: 'translate(-50%, 0)',
491
+ zIndex: 2147483647,
492
+ pointerEvents: 'none'
493
+ }
494
+ }, React.createElement(StatusIndicator, {
495
+ status: status,
496
+ isHiding: false,
497
+ volumes: state.currentVolumes || undefined
498
+ }));
499
+ state.statusIndicatorRoot.render(wrapper);
500
+ updateState({ currentIndicatorStatus: status });
501
+ }
502
+ catch (error) {
503
+ console.error('创建状态指示器失败:', error);
504
+ }
505
+ finally {
506
+ updateState({ isCreatingIndicator: false });
507
+ }
508
+ }
509
+ // 更新状态指示器的音量数据
510
+ function updateStatusIndicatorVolumes() {
511
+ var state = getState();
512
+ if (!state.statusIndicatorRoot || state.currentIndicatorStatus !== 'speaking' || !React) {
513
+ return;
514
+ }
515
+ var wrapper = React.createElement('div', {
516
+ id: 'sdk-status-indicator-wrapper',
517
+ style: {
518
+ position: 'fixed',
519
+ bottom: '100px',
520
+ left: '50%',
521
+ transform: 'translate(-50%, 0)',
522
+ zIndex: 2147483647,
523
+ pointerEvents: 'none'
524
+ }
525
+ }, React.createElement(StatusIndicator, {
526
+ status: state.currentIndicatorStatus,
527
+ isHiding: false,
528
+ volumes: state.currentVolumes || undefined
529
+ }));
530
+ state.statusIndicatorRoot.render(wrapper);
531
+ }
532
+ // 隐藏状态指示器
533
+ function hideStatusIndicator() {
534
+ var state = getState();
535
+ stopAudioAnalysis();
536
+ if (state.isHidingIndicator)
537
+ return;
538
+ if (state.statusIndicatorRoot && state.currentIndicatorStatus !== undefined && React) {
539
+ updateState({ isHidingIndicator: true });
540
+ if (state.hideIndicatorTimer !== null) {
541
+ clearTimeout(state.hideIndicatorTimer);
542
+ }
543
+ var wrapper = React.createElement('div', {
544
+ id: 'sdk-status-indicator-wrapper',
545
+ style: {
546
+ position: 'fixed',
547
+ bottom: '100px',
548
+ left: '50%',
549
+ transform: 'translate(-50%, 0)',
550
+ zIndex: 2147483647,
551
+ pointerEvents: 'none'
552
+ }
553
+ }, React.createElement(StatusIndicator, {
554
+ status: state.currentIndicatorStatus,
555
+ isHiding: true,
556
+ volumes: undefined
557
+ }));
558
+ state.statusIndicatorRoot.render(wrapper);
559
+ var timer = window.setTimeout(function () {
560
+ if (state.statusIndicatorRoot) {
561
+ state.statusIndicatorRoot.render(null);
562
+ }
563
+ updateState({
564
+ currentIndicatorStatus: undefined,
565
+ hideIndicatorTimer: null,
566
+ isHidingIndicator: false
567
+ });
568
+ }, 300);
569
+ updateState({ hideIndicatorTimer: timer });
570
+ }
571
+ }
572
+ // 启动音频分析
573
+ function startAudioAnalysis(analyserNode) {
574
+ var state = getState();
575
+ if (state.audioAnalysisFrameId) {
576
+ stopAudioAnalysis();
577
+ }
578
+ var bufferLength = analyserNode.frequencyBinCount;
579
+ var dataArray = new Uint8Array(bufferLength);
580
+ var lastUpdateTime = 0;
581
+ var updateInterval = 20;
582
+ function updateWaveform(currentTime) {
583
+ if (currentTime - lastUpdateTime >= updateInterval) {
584
+ analyserNode.getByteFrequencyData(dataArray);
585
+ var barCount = waveConfig.bar.barCount; // 使用配置中的波动条数量
586
+ var volumes = [];
587
+ // 使用对数分布来分配频率数据,让低频段分配更多频段,高频段分配较少频段
588
+ // 这样可以确保所有波形条都能获得有效数据
589
+ for (var i = 0; i < barCount; i++) {
590
+ // 对数分布:将频率范围按对数方式分成 barCount 段
591
+ // 低频段(人声主要频段)会分配更多数据点
592
+ var logStart = Math.pow(bufferLength, i / barCount);
593
+ var logEnd = Math.pow(bufferLength, (i + 1) / barCount);
594
+ var start = Math.floor(logStart);
595
+ var end = i === barCount - 1 ? bufferLength : Math.floor(logEnd);
596
+ if (start >= end || start >= bufferLength) {
597
+ volumes.push(0);
598
+ continue;
599
+ }
600
+ var sum = 0;
601
+ var max = 0;
602
+ var count = 0;
603
+ for (var j = start; j < end && j < bufferLength; j++) {
604
+ var value = dataArray[j];
605
+ sum += value;
606
+ if (value > max)
607
+ max = value;
608
+ count++;
609
+ }
610
+ var avg = count > 0 ? sum / count : 0;
611
+ // 调整混合比例,增加最大值权重,让波动更明显
612
+ var mixed = max * 0.4 + avg * 0.6;
613
+ // 添加最小阈值,确保即使音量很小也有基础响应
614
+ var minThreshold = 5; // 最小音量阈值
615
+ volumes.push(Math.max(mixed, minThreshold));
616
+ }
617
+ updateWaveBars(volumes);
618
+ lastUpdateTime = currentTime;
619
+ }
620
+ if (state.audioAnalysisFrameId !== null) {
621
+ var frameId_1 = requestAnimationFrame(updateWaveform);
622
+ updateState({ audioAnalysisFrameId: frameId_1 });
623
+ }
624
+ }
625
+ var frameId = requestAnimationFrame(updateWaveform);
626
+ updateState({ audioAnalysisFrameId: frameId });
627
+ }
628
+ // 停止音频分析
629
+ function stopAudioAnalysis() {
630
+ var state = getState();
631
+ if (state.audioAnalysisFrameId) {
632
+ cancelAnimationFrame(state.audioAnalysisFrameId);
633
+ updateState({ audioAnalysisFrameId: null, currentVolumes: null });
634
+ }
635
+ }
636
+ // 更新波形条
637
+ function updateWaveBars(volumes) {
638
+ var state = getState();
639
+ if (state.currentIndicatorStatus === 'loading')
640
+ return;
641
+ updateState({ currentVolumes: volumes });
642
+ updateStatusIndicatorVolumes();
643
+ }
644
+ // 显示 Toast
645
+ function showToast(message, type) {
646
+ // 只在开发环境显示
647
+ // const nodeEnv = typeof process !== 'undefined' && process.env ? "development" : 'production';
648
+ // if (nodeEnv !== 'development') return;
649
+ if (type === void 0) { type = 'success'; }
650
+ var state = getState();
651
+ if (!React || !ReactDOM)
652
+ return;
653
+ initToastContainer();
654
+ var ToastElement = React.createElement(Toast, {
655
+ message: message,
656
+ type: type,
657
+ duration: 2000,
658
+ onClose: function () {
659
+ if (state.toastRoot) {
660
+ state.toastRoot.render(null);
661
+ }
662
+ }
663
+ });
664
+ if (state.toastRoot) {
665
+ state.toastRoot.render(ToastElement);
666
+ setTimeout(function () {
667
+ if (state.toastRoot) {
668
+ state.toastRoot.render(null);
669
+ }
670
+ }, 2000);
671
+ }
672
+ }
673
+ // 隐藏重写结果弹框
674
+ function hideRewriteResult() {
675
+ var state = getState();
676
+ if (state.rewriteResultRoot) {
677
+ state.rewriteResultRoot.render(null);
678
+ }
679
+ }
680
+ // 显示重写结果弹框,带拷贝按钮
681
+ function showRewriteResult(text) {
682
+ var _this = this;
683
+ getState();
684
+ if (!React || !ReactDOM || !text)
685
+ return;
686
+ initRewriteResultContainer();
687
+ var root = getState().rewriteResultRoot;
688
+ if (!root)
689
+ return;
690
+ var close = function () {
691
+ root.render(null);
692
+ };
693
+ var handleCopy = function () { return __awaiter(_this, void 0, void 0, function () {
694
+ return __generator(this, function (_a) {
695
+ switch (_a.label) {
696
+ case 0:
697
+ _a.trys.push([0, 2, , 3]);
698
+ return [4 /*yield*/, navigator.clipboard.writeText(text)];
699
+ case 1:
700
+ _a.sent();
701
+ // showToast('已复制', 'success');
702
+ close(); // 复制成功后关闭弹框
703
+ return [3 /*break*/, 3];
704
+ case 2:
705
+ _a.sent();
706
+ showToast('复制失败', 'error');
707
+ return [3 /*break*/, 3];
708
+ case 3: return [2 /*return*/];
709
+ }
710
+ });
711
+ }); };
712
+ var popup = React.createElement(RewriteResult, {
713
+ text: text,
714
+ onClose: close,
715
+ onCopy: handleCopy
716
+ });
717
+ root.render(popup);
718
+ }
719
+
720
+ /**
721
+ * 网络请求层:集中处理 ASR / Rewrite 等接口调用,避免与业务逻辑混在一起。
722
+ *
723
+ * 设计目标:
724
+ * - 业务层(events/recognition)只负责流程控制与 UI 状态,不直接写 fetch
725
+ * - API 层负责:URL 生成、请求参数组装、响应解析、错误抛出
726
+ *
727
+ * 约定:
728
+ * - 所有请求失败会 throw Error(由调用方决定如何 toast / fallback)
729
+ * - 返回值尽量“纯数据”(string),不引入 UI 依赖
730
+ */
731
+ var REWRITE_API_PATH = '/v1/asr/input_rewrite';
732
+ // 统一追加的请求头(用户要求:后续所有请求头都要带上)
733
+ var COMMON_HEADERS = {
734
+ 'x-platform': 'WEB',
735
+ 'x-version': '0.0.1',
736
+ 'x-product': 'SenseType'
737
+ };
738
+ function normalizeTargetLang(targetLang) {
739
+ // 不做转译:传什么就用什么;None 表示默认语言 => 不传
740
+ return targetLang === 'None' ? '' : targetLang;
741
+ }
742
+ function normalizeBearerToken(token) {
743
+ var t = token.trim();
744
+ if (!t)
745
+ return t;
746
+ return /^Bearer\s+/i.test(t) ? t : "Bearer ".concat(t);
747
+ }
748
+ function extractTokenFromResponse(data) {
749
+ var _a, _b, _c, _d;
750
+ if (typeof data === 'string')
751
+ return data.trim() || null;
752
+ if (!data || typeof data !== 'object')
753
+ return null;
754
+ var anyData = data;
755
+ var candidates = [
756
+ anyData === null || anyData === void 0 ? void 0 : anyData.token,
757
+ anyData === null || anyData === void 0 ? void 0 : anyData.access_token,
758
+ (_a = anyData === null || anyData === void 0 ? void 0 : anyData.result) === null || _a === void 0 ? void 0 : _a.token,
759
+ (_b = anyData === null || anyData === void 0 ? void 0 : anyData.result) === null || _b === void 0 ? void 0 : _b.access_token,
760
+ (_c = anyData === null || anyData === void 0 ? void 0 : anyData.data) === null || _c === void 0 ? void 0 : _c.token,
761
+ (_d = anyData === null || anyData === void 0 ? void 0 : anyData.data) === null || _d === void 0 ? void 0 : _d.access_token
762
+ ];
763
+ for (var _i = 0, candidates_1 = candidates; _i < candidates_1.length; _i++) {
764
+ var c = candidates_1[_i];
765
+ if (typeof c === 'string' && c.trim())
766
+ return c.trim();
767
+ }
768
+ return null;
769
+ }
770
+ /**
771
+ * 确保已拿到 auth token(如果 state.publicKey 存在,会自动用它换取)。
772
+ * - durationSeconds 固定 86400
773
+ * - paths 不传
774
+ */
775
+ function ensureAuthToken() {
776
+ return __awaiter(this, void 0, void 0, function () {
777
+ var state, p;
778
+ var _this = this;
779
+ return __generator(this, function (_a) {
780
+ switch (_a.label) {
781
+ case 0:
782
+ state = getState();
783
+ if (state.authToken)
784
+ return [2 /*return*/, state.authToken];
785
+ if (!state.authTokenPromise) return [3 /*break*/, 2];
786
+ return [4 /*yield*/, state.authTokenPromise];
787
+ case 1: return [2 /*return*/, _a.sent()];
788
+ case 2:
789
+ if (!state.publicKey) {
790
+ throw new Error('缺少 publicKey:无法换取 token');
791
+ }
792
+ p = (function () { return __awaiter(_this, void 0, void 0, function () {
793
+ var resp, token;
794
+ return __generator(this, function (_a) {
795
+ switch (_a.label) {
796
+ case 0: return [4 /*yield*/, requestApplyTokenViaPublicKey({
797
+ durationSeconds: 86400,
798
+ publicKey: state.publicKey
799
+ })];
800
+ case 1:
801
+ resp = _a.sent();
802
+ token = extractTokenFromResponse(resp);
803
+ if (!token) {
804
+ throw new Error('获取 token 失败:响应中未找到 token 字段');
805
+ }
806
+ updateState({ authToken: token, authTokenPromise: null });
807
+ return [2 /*return*/, token];
808
+ }
809
+ });
810
+ }); })().catch(function (err) {
811
+ updateState({ authTokenPromise: null });
812
+ throw err;
813
+ });
814
+ updateState({ authTokenPromise: p });
815
+ return [4 /*yield*/, p];
816
+ case 3: return [2 /*return*/, _a.sent()];
817
+ }
818
+ });
819
+ });
820
+ }
821
+ /**
822
+ * 组装通用 headers:
823
+ * - 必带 COMMON_HEADERS
824
+ * - 如果已配置 publicKey,则会自动 ensure token,并加 Authorization: Bearer xxx
825
+ */
826
+ function buildAuthedHeaders(extra) {
827
+ return __awaiter(this, void 0, void 0, function () {
828
+ var state, headers, token;
829
+ return __generator(this, function (_a) {
830
+ switch (_a.label) {
831
+ case 0:
832
+ state = getState();
833
+ headers = __assign(__assign({}, COMMON_HEADERS), (extra || {}));
834
+ if (!state.publicKey) return [3 /*break*/, 2];
835
+ return [4 /*yield*/, ensureAuthToken()];
836
+ case 1:
837
+ token = _a.sent();
838
+ headers['Authorization'] = normalizeBearerToken(token);
839
+ _a.label = 2;
840
+ case 2: return [2 /*return*/, headers];
841
+ }
842
+ });
843
+ });
844
+ }
845
+ /**
846
+ * 根据 ASR URL 推导重写接口 URL。
847
+ *
848
+ * 规则:
849
+ * - 优先使用 asrUrl 的 origin(例如 asrUrl=https://a.com/api/v1/asr/... -> https://a.com/api/v1/asr/asr_input_rewrite)
850
+ * - 如果 asrUrl 不可用,则 fallback 到 getDefaultAsrApiUrl('stream') 的 origin
851
+ * - 如果两者都不可解析,则返回相对路径(由浏览器按当前域名解析)
852
+ */
853
+ function getRewriteApiUrlFromAsr(asrUrl) {
854
+ var state = getState();
855
+ var domain = state.envPrefix ? "".concat(state.envPrefix, ".api.senseaudio.cn") : 'api.senseaudio.cn';
856
+ return "https://".concat(domain).concat(REWRITE_API_PATH);
857
+ }
858
+ /**
859
+ * 调用“重写接口”(选中文本 + 语音指令 => 改写结果)。
860
+ *
861
+ * @returns rewritten_text(空字符串表示接口正常返回但无结果)
862
+ * @throws Error 请求失败或返回非 2xx
863
+ */
864
+ function requestRewriteText(params) {
865
+ return __awaiter(this, void 0, void 0, function () {
866
+ var url, headers, normalizedTargetLang, form, body, resp, text, data, rewritten;
867
+ var _a, _b;
868
+ return __generator(this, function (_c) {
869
+ switch (_c.label) {
870
+ case 0:
871
+ url = getRewriteApiUrlFromAsr();
872
+ return [4 /*yield*/, buildAuthedHeaders(__assign(__assign({}, (((_a = params.asrApi) === null || _a === void 0 ? void 0 : _a.headers) || {})), { accept: 'application/json', 'x-platform': 'WEB', 'x-version': '0.0.1', 'x-product': 'SenseType', 'Content-Type': 'application/x-www-form-urlencoded' }))];
873
+ case 1:
874
+ headers = _c.sent();
875
+ normalizedTargetLang = normalizeTargetLang(params.targetLang);
876
+ form = {
877
+ original_text: params.originalText,
878
+ rewrite_instruction: params.rewriteInstruction,
879
+ model: params.model
880
+ };
881
+ // None => 不传 target_lang,走后端默认语言
882
+ if (normalizedTargetLang) {
883
+ form.target_lang = normalizedTargetLang;
884
+ }
885
+ body = new URLSearchParams(form).toString();
886
+ return [4 /*yield*/, fetch(url, {
887
+ method: 'POST',
888
+ headers: headers,
889
+ body: body
890
+ })];
891
+ case 2:
892
+ resp = _c.sent();
893
+ if (!!resp.ok) return [3 /*break*/, 4];
894
+ return [4 /*yield*/, resp.text().catch(function () { return ''; })];
895
+ case 3:
896
+ text = _c.sent();
897
+ throw new Error("\u91CD\u5199\u63A5\u53E3\u5931\u8D25: ".concat(resp.status, " ").concat(resp.statusText).concat(text ? " - ".concat(text) : ''));
898
+ case 4: return [4 /*yield*/, resp.json().catch(function () { return ({}); })];
899
+ case 5:
900
+ data = _c.sent();
901
+ rewritten = (_b = data === null || data === void 0 ? void 0 : data.result) === null || _b === void 0 ? void 0 : _b.rewritten_text;
902
+ return [2 /*return*/, typeof rewritten === 'string' ? rewritten : ''];
903
+ }
904
+ });
905
+ });
906
+ }
907
+ /**
908
+ * 调用 ASR 接口:上传音频并返回识别文本。
909
+ *
910
+ * 说明:
911
+ * - 这里不负责录音/编码(由 recognition.ts 负责)
912
+ * - 只负责将 mp3 blob 以 multipart/form-data 形式上传
913
+ * - stream 模式通常返回 text/plain
914
+ *
915
+ * @returns 识别文本(空字符串表示接口正常返回但无文本)
916
+ * @throws Error 请求失败或解析失败
917
+ */
918
+ function requestAsrTextFromAudio(params) {
919
+ return __awaiter(this, void 0, void 0, function () {
920
+ var fileName, audioFile, formData, normalizedTargetLang, headers, response, errorText, contentType, finalText, result, candidate;
921
+ var _a, _b, _c;
922
+ return __generator(this, function (_d) {
923
+ switch (_d.label) {
924
+ case 0:
925
+ fileName = 'recording.mp3';
926
+ audioFile = new File([params.audioBlob], fileName, { type: 'audio/mpeg' });
927
+ formData = new FormData();
928
+ formData.append('file', audioFile, fileName);
929
+ formData.append('model', params.model);
930
+ normalizedTargetLang = normalizeTargetLang(params.targetLang);
931
+ if (normalizedTargetLang) {
932
+ formData.append('target_lang', normalizedTargetLang);
933
+ }
934
+ return [4 /*yield*/, buildAuthedHeaders(__assign({ accept: '*/*', 'Accept-Language': 'en,zh-CN;q=0.9,zh;q=0.8', 'Cache-Control': 'no-cache', 'x-platform': 'WEB', 'x-version': '0.0.1', 'x-product': 'SenseType', Pragma: 'no-cache' }, (params.headers || {})))];
935
+ case 1:
936
+ headers = _d.sent();
937
+ // fetch + FormData 会自动设置 multipart boundary;手动设置反而可能导致 boundary 丢失
938
+ delete headers['Content-Type'];
939
+ return [4 /*yield*/, fetch(params.asrUrl, {
940
+ method: 'POST',
941
+ headers: headers,
942
+ body: formData,
943
+ mode: 'cors',
944
+ credentials: 'omit',
945
+ cache: 'no-cache'
946
+ })];
947
+ case 2:
948
+ response = _d.sent();
949
+ if (!!response.ok) return [3 /*break*/, 4];
950
+ return [4 /*yield*/, response.text().catch(function () { return ''; })];
951
+ case 3:
952
+ errorText = _d.sent();
953
+ throw new Error("API \u8BF7\u6C42\u5931\u8D25: ".concat(response.status, " ").concat(response.statusText).concat(errorText ? " - ".concat(errorText) : ''));
954
+ case 4:
955
+ contentType = response.headers.get('content-type') || '';
956
+ finalText = '';
957
+ if (!contentType.includes('application/json')) return [3 /*break*/, 6];
958
+ return [4 /*yield*/, response.json().catch(function () { return ({}); })];
959
+ case 5:
960
+ result = _d.sent();
961
+ candidate = (_c = (_b = (_a = result === null || result === void 0 ? void 0 : result.result) === null || _a === void 0 ? void 0 : _a.final_text) !== null && _b !== void 0 ? _b : result === null || result === void 0 ? void 0 : result.final_text) !== null && _c !== void 0 ? _c : '';
962
+ finalText = typeof candidate === 'string' ? candidate.trim() : '';
963
+ return [3 /*break*/, 8];
964
+ case 6: return [4 /*yield*/, response.text()];
965
+ case 7:
966
+ finalText = (_d.sent()).trim();
967
+ _d.label = 8;
968
+ case 8: return [2 /*return*/, finalText];
969
+ }
970
+ });
971
+ });
972
+ }
973
+ /**
974
+ * 申请 token(通过 public_key)。
975
+ *
976
+ * 对应示例:
977
+ * POST /v1/apikey/apply_token_via_public_key
978
+ * Headers:
979
+ * - x-platform: WEB
980
+ * - x-version: v2.0
981
+ * - x-product: SenseAudio
982
+ * - Content-Type: application/json
983
+ */
984
+ function requestApplyTokenViaPublicKey(params) {
985
+ return __awaiter(this, void 0, void 0, function () {
986
+ var state, authDomain, path, url, headers, payload, body, resp, text, contentType;
987
+ return __generator(this, function (_a) {
988
+ switch (_a.label) {
989
+ case 0:
990
+ state = getState();
991
+ authDomain = state.envPrefix ? "".concat(state.envPrefix, ".auth.senseaudio.cn") : 'auth.senseaudio.cn';
992
+ path = "https://".concat(authDomain, "/v1/apikey/apply_token_via_public_key");
993
+ url = params.baseUrl ? new URL(path, params.baseUrl).toString() : path;
994
+ headers = __assign(__assign(__assign({}, COMMON_HEADERS), { 'Content-Type': 'application/json' }), (params.headers || {}));
995
+ payload = {
996
+ duration_seconds: params.durationSeconds,
997
+ public_key: params.publicKey
998
+ };
999
+ if (params.paths && params.paths.length > 0) {
1000
+ payload.paths = params.paths;
1001
+ }
1002
+ body = JSON.stringify(payload);
1003
+ return [4 /*yield*/, fetch(url, {
1004
+ method: 'POST',
1005
+ headers: headers,
1006
+ body: body,
1007
+ // redirect: 'follow'
1008
+ })];
1009
+ case 1:
1010
+ resp = _a.sent();
1011
+ if (!!resp.ok) return [3 /*break*/, 3];
1012
+ return [4 /*yield*/, resp.text().catch(function () { return ''; })];
1013
+ case 2:
1014
+ text = _a.sent();
1015
+ throw new Error("apply_token_via_public_key \u5931\u8D25: ".concat(resp.status, " ").concat(resp.statusText).concat(text ? " - ".concat(text) : ''));
1016
+ case 3:
1017
+ contentType = resp.headers.get('content-type') || '';
1018
+ if (!contentType.includes('application/json')) return [3 /*break*/, 5];
1019
+ return [4 /*yield*/, resp.json().catch(function () { return ({}); })];
1020
+ case 4: return [2 /*return*/, _a.sent()];
1021
+ case 5: return [4 /*yield*/, resp.text()];
1022
+ case 6: return [2 /*return*/, _a.sent()];
1023
+ }
1024
+ });
1025
+ });
1026
+ }
1027
+ /**
1028
+ * 预取 token:用于 init 阶段提前触发一次换取,减少首次请求延迟。
1029
+ * 失败时不抛到 UI 层(调用方可以忽略),真正发请求时仍会 ensureAuthToken 并抛错。
1030
+ */
1031
+ function prefetchAuthToken() {
1032
+ return __awaiter(this, void 0, void 0, function () {
1033
+ var state;
1034
+ return __generator(this, function (_a) {
1035
+ switch (_a.label) {
1036
+ case 0:
1037
+ state = getState();
1038
+ if (!state.publicKey)
1039
+ return [2 /*return*/];
1040
+ if (state.authToken)
1041
+ return [2 /*return*/];
1042
+ return [4 /*yield*/, ensureAuthToken()];
1043
+ case 1:
1044
+ _a.sent();
1045
+ return [2 /*return*/];
1046
+ }
1047
+ });
1048
+ });
1049
+ }
1050
+
1051
+ // 语音识别功能
1052
+ // 动态加载 lamejs
1053
+ function loadLamejs() {
1054
+ return new Promise(function (resolve, reject) {
1055
+ if (typeof window.lamejs !== 'undefined') {
1056
+ resolve();
1057
+ return;
1058
+ }
1059
+ if (window.__lamejsLoading) {
1060
+ var checkInterval_1 = setInterval(function () {
1061
+ if (typeof window.lamejs !== 'undefined') {
1062
+ clearInterval(checkInterval_1);
1063
+ resolve();
1064
+ }
1065
+ }, 100);
1066
+ setTimeout(function () {
1067
+ clearInterval(checkInterval_1);
1068
+ reject(new Error('加载lamejs超时'));
1069
+ }, 10000);
1070
+ return;
1071
+ }
1072
+ window.__lamejsLoading = true;
1073
+ var script = document.createElement('script');
1074
+ script.src = 'https://cdnjs.cloudflare.com/ajax/libs/lamejs/1.2.1/lame.min.js';
1075
+ script.async = true;
1076
+ script.onload = function () {
1077
+ window.__lamejsLoading = false;
1078
+ if (typeof window.lamejs !== 'undefined') {
1079
+ resolve();
1080
+ }
1081
+ else {
1082
+ reject(new Error('lamejs 加载失败'));
1083
+ }
1084
+ };
1085
+ script.onerror = function () {
1086
+ window.__lamejsLoading = false;
1087
+ showToast('语音加载失败:网络错误', 'error');
1088
+ reject(new Error('lamejs 加载失败:网络错误'));
1089
+ };
1090
+ document.head.appendChild(script);
1091
+ });
1092
+ }
1093
+ // 转换为 MP3
1094
+ function convertToMp3(audioBlob) {
1095
+ return __awaiter(this, void 0, void 0, function () {
1096
+ var _this = this;
1097
+ return __generator(this, function (_a) {
1098
+ return [2 /*return*/, new Promise(function (resolve, reject) {
1099
+ try {
1100
+ var audioContext_1 = new (window.AudioContext || window.webkitAudioContext)();
1101
+ var reader = new FileReader();
1102
+ reader.onload = function (e) { return __awaiter(_this, void 0, void 0, function () {
1103
+ var audioBuffer, samples, sampleRate, monoData, channel2, i, pcmData, i, s, lamejs, mp3encoder, sampleBlockSize, mp3Data, i, sampleChunk, mp3buf_1, mp3buf, blobParts, _i, mp3Data_1, arr, buffer, view, error_1;
1104
+ var _a;
1105
+ return __generator(this, function (_b) {
1106
+ switch (_b.label) {
1107
+ case 0:
1108
+ _b.trys.push([0, 2, , 3]);
1109
+ return [4 /*yield*/, audioContext_1.decodeAudioData((_a = e.target) === null || _a === void 0 ? void 0 : _a.result)];
1110
+ case 1:
1111
+ audioBuffer = _b.sent();
1112
+ samples = audioBuffer.getChannelData(0);
1113
+ sampleRate = audioBuffer.sampleRate;
1114
+ monoData = samples;
1115
+ if (audioBuffer.numberOfChannels > 1) {
1116
+ channel2 = audioBuffer.getChannelData(1);
1117
+ monoData = new Float32Array(samples.length);
1118
+ for (i = 0; i < samples.length; i++) {
1119
+ monoData[i] = (samples[i] + channel2[i]) / 2;
1120
+ }
1121
+ }
1122
+ pcmData = new Int16Array(monoData.length);
1123
+ for (i = 0; i < monoData.length; i++) {
1124
+ s = Math.max(-1, Math.min(1, monoData[i]));
1125
+ pcmData[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
1126
+ }
1127
+ if (typeof window.lamejs !== 'undefined') {
1128
+ lamejs = window.lamejs;
1129
+ mp3encoder = new lamejs.Mp3Encoder(1, sampleRate, 128);
1130
+ sampleBlockSize = 1152;
1131
+ mp3Data = [];
1132
+ for (i = 0; i < pcmData.length; i += sampleBlockSize) {
1133
+ sampleChunk = pcmData.subarray(i, i + sampleBlockSize);
1134
+ mp3buf_1 = mp3encoder.encodeBuffer(sampleChunk);
1135
+ if (mp3buf_1.length > 0) {
1136
+ mp3Data.push(mp3buf_1);
1137
+ }
1138
+ }
1139
+ mp3buf = mp3encoder.flush();
1140
+ if (mp3buf.length > 0) {
1141
+ mp3Data.push(mp3buf);
1142
+ }
1143
+ blobParts = [];
1144
+ for (_i = 0, mp3Data_1 = mp3Data; _i < mp3Data_1.length; _i++) {
1145
+ arr = mp3Data_1[_i];
1146
+ buffer = new ArrayBuffer(arr.byteLength);
1147
+ view = new Uint8Array(buffer);
1148
+ view.set(new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength));
1149
+ blobParts.push(buffer);
1150
+ }
1151
+ resolve(new Blob(blobParts, { type: 'audio/mpeg' }));
1152
+ }
1153
+ else {
1154
+ reject(new Error('需要加载lamejs库'));
1155
+ }
1156
+ return [3 /*break*/, 3];
1157
+ case 2:
1158
+ error_1 = _b.sent();
1159
+ reject(error_1);
1160
+ return [3 /*break*/, 3];
1161
+ case 3: return [2 /*return*/];
1162
+ }
1163
+ });
1164
+ }); };
1165
+ reader.onerror = reject;
1166
+ reader.readAsArrayBuffer(audioBlob);
1167
+ }
1168
+ catch (error) {
1169
+ reject(error);
1170
+ }
1171
+ })];
1172
+ });
1173
+ });
1174
+ }
1175
+ // 发送音频到 API
1176
+ function sendAudioToApi(audioBlob) {
1177
+ return __awaiter(this, void 0, void 0, function () {
1178
+ var state, finalText, textToReturn, error_2, textToReturn;
1179
+ var _a, _b, _c, _d, _e, _f, _g;
1180
+ return __generator(this, function (_h) {
1181
+ switch (_h.label) {
1182
+ case 0:
1183
+ state = getState();
1184
+ ((_a = state.asrApi) === null || _a === void 0 ? void 0 : _a.mode) || 'stream';
1185
+ if (!((_b = state.asrApi) === null || _b === void 0 ? void 0 : _b.url)) {
1186
+ (_c = state.onError) === null || _c === void 0 ? void 0 : _c.call(state, 'API 配置不存在');
1187
+ return [2 /*return*/];
1188
+ }
1189
+ _h.label = 1;
1190
+ case 1:
1191
+ _h.trys.push([1, 3, , 4]);
1192
+ return [4 /*yield*/, requestAsrTextFromAudio({
1193
+ audioBlob: audioBlob,
1194
+ asrUrl: state.asrApi.url,
1195
+ headers: state.asrApi.headers,
1196
+ model: state.model,
1197
+ targetLang: state.targetLang
1198
+ })];
1199
+ case 2:
1200
+ finalText = _h.sent();
1201
+ if (finalText) {
1202
+ updateState({
1203
+ recognizedText: (state.recognizedText ? state.recognizedText + ' ' : '') + finalText
1204
+ });
1205
+ (_d = state.onRecordingUpdate) === null || _d === void 0 ? void 0 : _d.call(state, state.recognizedText);
1206
+ }
1207
+ else {
1208
+ // 接口返回内容为空时显示警告
1209
+ showToast('未识别到信息', 'info');
1210
+ }
1211
+ if (!state.shouldContinueRecording()) {
1212
+ textToReturn = state.recognizedText.trim();
1213
+ updateState({ recognizedText: '', interimText: '' });
1214
+ (_e = state.onRecordingEnd) === null || _e === void 0 ? void 0 : _e.call(state, textToReturn);
1215
+ }
1216
+ return [3 /*break*/, 4];
1217
+ case 3:
1218
+ error_2 = _h.sent();
1219
+ hideStatusIndicator();
1220
+ (_f = state.onError) === null || _f === void 0 ? void 0 : _f.call(state, "API \u8BF7\u6C42\u5931\u8D25: ".concat(error_2.message || '未知错误'));
1221
+ if (!state.shouldContinueRecording()) {
1222
+ textToReturn = state.recognizedText.trim();
1223
+ updateState({ recognizedText: '', interimText: '' });
1224
+ (_g = state.onRecordingEnd) === null || _g === void 0 ? void 0 : _g.call(state, textToReturn);
1225
+ }
1226
+ return [3 /*break*/, 4];
1227
+ case 4: return [2 /*return*/];
1228
+ }
1229
+ });
1230
+ });
1231
+ }
1232
+ // 开始语音识别
1233
+ function startSpeechRecognition(lang) {
1234
+ var _a, _b;
1235
+ var state = getState();
1236
+ if (state.isRecording)
1237
+ return;
1238
+ if (!((_a = state.asrApi) === null || _a === void 0 ? void 0 : _a.url)) {
1239
+ (_b = state.onError) === null || _b === void 0 ? void 0 : _b.call(state, 'API 配置不存在');
1240
+ return;
1241
+ }
1242
+ startApiRecognition();
1243
+ }
1244
+ function startApiRecognition(lang) {
1245
+ return __awaiter(this, void 0, void 0, function () {
1246
+ var state, stream_1, audioContext, source, analyser, mediaRecorder_1, error_3, errorMsg;
1247
+ var _this = this;
1248
+ var _a, _b, _c;
1249
+ return __generator(this, function (_d) {
1250
+ switch (_d.label) {
1251
+ case 0:
1252
+ state = getState();
1253
+ _d.label = 1;
1254
+ case 1:
1255
+ _d.trys.push([1, 3, , 4]);
1256
+ return [4 /*yield*/, navigator.mediaDevices.getUserMedia({ audio: true })];
1257
+ case 2:
1258
+ stream_1 = _d.sent();
1259
+ audioContext = new (window.AudioContext || window.webkitAudioContext)();
1260
+ source = audioContext.createMediaStreamSource(stream_1);
1261
+ analyser = audioContext.createAnalyser();
1262
+ analyser.fftSize = 256;
1263
+ analyser.smoothingTimeConstant = 0.4;
1264
+ analyser.minDecibels = -90;
1265
+ analyser.maxDecibels = -10;
1266
+ source.connect(analyser);
1267
+ updateState({ audioAnalyser: analyser, audioContext: audioContext });
1268
+ mediaRecorder_1 = new MediaRecorder(stream_1, {
1269
+ mimeType: MediaRecorder.isTypeSupported('audio/webm') ? 'audio/webm' :
1270
+ MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' :
1271
+ MediaRecorder.isTypeSupported('audio/mp4') ? 'audio/mp4' :
1272
+ 'audio/webm'
1273
+ });
1274
+ updateState({ mediaRecorder: mediaRecorder_1, audioChunks: [], isRecording: true });
1275
+ mediaRecorder_1.ondataavailable = function (event) {
1276
+ if (event.data.size > 0) {
1277
+ state.audioChunks.push(event.data);
1278
+ }
1279
+ };
1280
+ mediaRecorder_1.onstop = function () { return __awaiter(_this, void 0, void 0, function () {
1281
+ var originalBlob, audioBlob;
1282
+ var _a, _b, _c, _d, _e, _f, _g;
1283
+ return __generator(this, function (_h) {
1284
+ switch (_h.label) {
1285
+ case 0:
1286
+ _h.trys.push([0, 8, , 9]);
1287
+ stopAudioAnalysis();
1288
+ if (state.audioContext) {
1289
+ state.audioContext.close().catch(console.error);
1290
+ updateState({ audioContext: null, audioAnalyser: null });
1291
+ }
1292
+ stream_1.getTracks().forEach(function (track) { return track.stop(); });
1293
+ if (state.audioChunks.length === 0) {
1294
+ updateState({ isRecording: false });
1295
+ (_a = state.onRecordingEnd) === null || _a === void 0 ? void 0 : _a.call(state, '');
1296
+ return [2 /*return*/];
1297
+ }
1298
+ originalBlob = new Blob(state.audioChunks, { type: mediaRecorder_1.mimeType });
1299
+ updateState({ audioChunks: [] });
1300
+ audioBlob = originalBlob;
1301
+ if (!(!originalBlob.type.includes('mpeg') && !originalBlob.type.includes('mp3'))) return [3 /*break*/, 6];
1302
+ if (!(typeof window.lamejs === 'undefined')) return [3 /*break*/, 4];
1303
+ (_b = state.onRecordingUpdate) === null || _b === void 0 ? void 0 : _b.call(state, '正在加载MP3编码器...');
1304
+ _h.label = 1;
1305
+ case 1:
1306
+ _h.trys.push([1, 3, , 4]);
1307
+ return [4 /*yield*/, loadLamejs()];
1308
+ case 2:
1309
+ _h.sent();
1310
+ return [3 /*break*/, 4];
1311
+ case 3:
1312
+ _h.sent();
1313
+ (_c = state.onError) === null || _c === void 0 ? void 0 : _c.call(state, '无法加载MP3编码器');
1314
+ updateState({ isRecording: false });
1315
+ (_d = state.onRecordingEnd) === null || _d === void 0 ? void 0 : _d.call(state, '');
1316
+ return [2 /*return*/];
1317
+ case 4:
1318
+ (_e = state.onRecordingUpdate) === null || _e === void 0 ? void 0 : _e.call(state, '正在转换为MP3格式...');
1319
+ return [4 /*yield*/, convertToMp3(originalBlob)];
1320
+ case 5:
1321
+ audioBlob = _h.sent();
1322
+ _h.label = 6;
1323
+ case 6: return [4 /*yield*/, sendAudioToApi(audioBlob)];
1324
+ case 7:
1325
+ _h.sent();
1326
+ if (state.shouldContinueRecording()) {
1327
+ startApiRecognition();
1328
+ }
1329
+ else {
1330
+ updateState({ isRecording: false });
1331
+ }
1332
+ return [3 /*break*/, 9];
1333
+ case 8:
1334
+ _h.sent();
1335
+ updateState({ isRecording: false });
1336
+ hideStatusIndicator();
1337
+ (_f = state.onError) === null || _f === void 0 ? void 0 : _f.call(state, '处理录音数据失败');
1338
+ (_g = state.onRecordingEnd) === null || _g === void 0 ? void 0 : _g.call(state, '');
1339
+ return [3 /*break*/, 9];
1340
+ case 9: return [2 /*return*/];
1341
+ }
1342
+ });
1343
+ }); };
1344
+ mediaRecorder_1.start();
1345
+ (_a = state.onRecordingStart) === null || _a === void 0 ? void 0 : _a.call(state);
1346
+ (_b = state.onRecordingUpdate) === null || _b === void 0 ? void 0 : _b.call(state, '正在录音...');
1347
+ showStatusIndicator('speaking');
1348
+ startAudioAnalysis(analyser);
1349
+ return [3 /*break*/, 4];
1350
+ case 3:
1351
+ error_3 = _d.sent();
1352
+ updateState({ isRecording: false });
1353
+ stopAudioAnalysis();
1354
+ hideStatusIndicator();
1355
+ if (state.audioContext) {
1356
+ state.audioContext.close().catch(console.error);
1357
+ updateState({ audioContext: null, audioAnalyser: null });
1358
+ }
1359
+ errorMsg = error_3.name === 'NotAllowedError' ? '麦克风权限被拒绝' :
1360
+ error_3.name === 'NotFoundError' ? '未找到麦克风设备' :
1361
+ '启动录音失败';
1362
+ (_c = state.onError) === null || _c === void 0 ? void 0 : _c.call(state, errorMsg);
1363
+ return [3 /*break*/, 4];
1364
+ case 4: return [2 /*return*/];
1365
+ }
1366
+ });
1367
+ });
1368
+ }
1369
+ // 停止语音识别
1370
+ function stopSpeechRecognition() {
1371
+ var _a;
1372
+ var state = getState();
1373
+ stopAudioAnalysis();
1374
+ if (state.mediaRecorder && state.isRecording) {
1375
+ try {
1376
+ if (state.mediaRecorder.state === 'recording') {
1377
+ state.mediaRecorder.stop();
1378
+ }
1379
+ else {
1380
+ updateState({ isRecording: false });
1381
+ hideStatusIndicator();
1382
+ }
1383
+ }
1384
+ catch (e) {
1385
+ updateState({ isRecording: false });
1386
+ hideStatusIndicator();
1387
+ if (state.audioContext) {
1388
+ state.audioContext.close().catch(console.error);
1389
+ updateState({ audioContext: null, audioAnalyser: null });
1390
+ }
1391
+ if ((_a = state.mediaRecorder) === null || _a === void 0 ? void 0 : _a.stream) {
1392
+ state.mediaRecorder.stream.getTracks().forEach(function (track) { return track.stop(); });
1393
+ }
1394
+ }
1395
+ }
1396
+ else {
1397
+ hideStatusIndicator();
1398
+ }
1399
+ }
1400
+ // 设置回调
1401
+ function setSpeechRecognitionCallbacks(callbacks) {
1402
+ updateState({
1403
+ onRecordingStart: callbacks.onStart || null,
1404
+ onRecordingUpdate: callbacks.onUpdate || null,
1405
+ onRecordingEnd: callbacks.onEnd || null,
1406
+ onError: callbacks.onError || null,
1407
+ shouldContinueRecording: callbacks.shouldContinue || (function () { return false; })
1408
+ });
1409
+ }
1410
+ // 获取录音状态
1411
+ function getRecordingState() {
1412
+ var state = getState();
1413
+ return {
1414
+ isRecording: state.isRecording,
1415
+ recognizedText: state.recognizedText,
1416
+ interimText: state.interimText
1417
+ };
1418
+ }
1419
+
1420
+ // 文本输入功能
1421
+ function setCurrentInputElementForTextInput(element) {
1422
+ updateState({ currentInputElement: element });
1423
+ }
1424
+ function insertTextToInput(text) {
1425
+ var _a, _b;
1426
+ var state = getState();
1427
+ var element = state.currentInputElement;
1428
+ if (!element || !text)
1429
+ return;
1430
+ // 处理普通 input 和 textarea
1431
+ if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
1432
+ var start = element.selectionStart || 0;
1433
+ var end = element.selectionEnd || 0;
1434
+ var value = element.value;
1435
+ var newValue = value.substring(0, start) + text + value.substring(end);
1436
+ var newCursorPos_1 = start + text.length;
1437
+ var reactValueTracker = element._valueTracker;
1438
+ var previousValue = value;
1439
+ // 触发 beforeInput 事件
1440
+ if (typeof InputEvent !== 'undefined') {
1441
+ var beforeInputEvent = new InputEvent('beforeinput', {
1442
+ bubbles: true,
1443
+ cancelable: true,
1444
+ inputType: 'insertText',
1445
+ data: text
1446
+ });
1447
+ if (!element.dispatchEvent(beforeInputEvent))
1448
+ return;
1449
+ }
1450
+ // 获取原生 setter
1451
+ var nativeValueSetter = null;
1452
+ if (element instanceof HTMLInputElement) {
1453
+ nativeValueSetter = ((_a = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')) === null || _a === void 0 ? void 0 : _a.set) || null;
1454
+ }
1455
+ else if (element instanceof HTMLTextAreaElement) {
1456
+ nativeValueSetter = ((_b = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value')) === null || _b === void 0 ? void 0 : _b.set) || null;
1457
+ }
1458
+ // 设置值
1459
+ if (nativeValueSetter) {
1460
+ nativeValueSetter.call(element, newValue);
1461
+ }
1462
+ else {
1463
+ element.value = newValue;
1464
+ }
1465
+ // 更新 React 值跟踪器为旧值,确保 onChange 触发
1466
+ if (reactValueTracker) {
1467
+ reactValueTracker.setValue(previousValue);
1468
+ }
1469
+ // 设置光标位置
1470
+ element.selectionStart = newCursorPos_1;
1471
+ element.selectionEnd = newCursorPos_1;
1472
+ // 触发事件
1473
+ var inputEvent = typeof InputEvent !== 'undefined'
1474
+ ? new InputEvent('input', { bubbles: true, cancelable: true, data: text, inputType: 'insertText' })
1475
+ : new Event('input', { bubbles: true, cancelable: true });
1476
+ element.dispatchEvent(inputEvent);
1477
+ // 事件触发后同步 React 跟踪器为最新值
1478
+ if (reactValueTracker) {
1479
+ reactValueTracker.setValue(newValue);
1480
+ }
1481
+ var changeEvent = new Event('change', { bubbles: true, cancelable: true });
1482
+ element.dispatchEvent(changeEvent);
1483
+ // 确保焦点
1484
+ if (document.activeElement !== element) {
1485
+ element.focus();
1486
+ }
1487
+ setTimeout(function () {
1488
+ if (element && (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement)) {
1489
+ element.selectionStart = newCursorPos_1;
1490
+ element.selectionEnd = newCursorPos_1;
1491
+ }
1492
+ }, 0);
1493
+ }
1494
+ // 处理 contentEditable 元素
1495
+ else if (element.contentEditable === 'true') {
1496
+ var selection = window.getSelection();
1497
+ if (selection && selection.rangeCount > 0) {
1498
+ var range = selection.getRangeAt(0);
1499
+ range.deleteContents();
1500
+ var textNode = document.createTextNode(text);
1501
+ range.insertNode(textNode);
1502
+ range.setStartAfter(textNode);
1503
+ range.setEndAfter(textNode);
1504
+ selection.removeAllRanges();
1505
+ selection.addRange(range);
1506
+ }
1507
+ else {
1508
+ var textNode = document.createTextNode(text);
1509
+ element.appendChild(textNode);
1510
+ var range = document.createRange();
1511
+ range.setStartAfter(textNode);
1512
+ range.setEndAfter(textNode);
1513
+ var sel = window.getSelection();
1514
+ if (sel) {
1515
+ sel.removeAllRanges();
1516
+ sel.addRange(range);
1517
+ }
1518
+ }
1519
+ var inputEvent = new Event('input', { bubbles: true, cancelable: true });
1520
+ element.dispatchEvent(inputEvent);
1521
+ var changeEvent = new Event('change', { bubbles: true, cancelable: true });
1522
+ element.dispatchEvent(changeEvent);
1523
+ if (document.activeElement !== element) {
1524
+ element.focus();
1525
+ }
1526
+ }
1527
+ }
1528
+
1529
+ // 事件处理
1530
+ // 长按阈值(毫秒)
1531
+ var LONG_PRESS_DELAY = 200;
1532
+ var longPressTimer = null;
1533
+ var eventHandlersRegistered = false;
1534
+ // 获取当前选中的文本:仅使用全局选区,选中哪里取哪里,不回退输入框选区
1535
+ function getSelectedText(currentInput) {
1536
+ var selection = window.getSelection();
1537
+ return selection ? selection.toString() : '';
1538
+ }
1539
+ // 调用文本重写接口
1540
+ function rewriteSelectedText(originalText, rewriteInstruction) {
1541
+ return __awaiter(this, void 0, void 0, function () {
1542
+ var state, rewritten, error_1;
1543
+ return __generator(this, function (_a) {
1544
+ switch (_a.label) {
1545
+ case 0:
1546
+ state = getState();
1547
+ _a.label = 1;
1548
+ case 1:
1549
+ _a.trys.push([1, 3, , 4]);
1550
+ return [4 /*yield*/, requestRewriteText({
1551
+ originalText: originalText,
1552
+ rewriteInstruction: rewriteInstruction,
1553
+ asrApi: state.asrApi,
1554
+ model: state.model,
1555
+ targetLang: state.targetLang
1556
+ })];
1557
+ case 2:
1558
+ rewritten = _a.sent();
1559
+ // 重写接口完成后才隐藏 loading
1560
+ hideStatusIndicator();
1561
+ if (rewritten) {
1562
+ showRewriteResult(rewritten);
1563
+ }
1564
+ else {
1565
+ // 接口返回内容为空时显示警告
1566
+ showToast('未识别到信息', 'info');
1567
+ }
1568
+ return [3 /*break*/, 4];
1569
+ case 3:
1570
+ error_1 = _a.sent();
1571
+ console.error('[SDK] 调用重写接口出错:', error_1);
1572
+ // 出错时也要隐藏 loading
1573
+ hideStatusIndicator();
1574
+ showToast('服务器请求超时', 'error');
1575
+ return [3 /*break*/, 4];
1576
+ case 4: return [2 /*return*/];
1577
+ }
1578
+ });
1579
+ });
1580
+ }
1581
+ // 检查是否匹配快捷键
1582
+ function isShortcutKey(event) {
1583
+ var state = getState();
1584
+ var shortcut = state.shortcutKey;
1585
+ var keyMatches = false;
1586
+ // 统一处理左右修饰键:Alt / Ctrl / Shift 默认支持左右两边
1587
+ var isAltShortcut = shortcut.code === 'AltLeft' || shortcut.code === 'AltRight' || shortcut.key === 'Alt';
1588
+ var isCtrlShortcut = shortcut.code === 'ControlLeft' || shortcut.code === 'ControlRight' || shortcut.key === 'Control';
1589
+ var isShiftShortcut = shortcut.code === 'ShiftLeft' || shortcut.code === 'ShiftRight' || shortcut.key === 'Shift';
1590
+ var eventIsAlt = event.code === 'AltLeft' || event.code === 'AltRight' || event.key === 'Alt';
1591
+ var eventIsCtrl = event.code === 'ControlLeft' || event.code === 'ControlRight' || event.key === 'Control';
1592
+ var eventIsShift = event.code === 'ShiftLeft' || event.code === 'ShiftRight' || event.key === 'Shift';
1593
+ // 修饰键场景:左右都可触发
1594
+ if (isAltShortcut && eventIsAlt) {
1595
+ keyMatches = true;
1596
+ }
1597
+ else if (isCtrlShortcut && eventIsCtrl) {
1598
+ keyMatches = true;
1599
+ }
1600
+ else if (isShiftShortcut && eventIsShift) {
1601
+ keyMatches = true;
1602
+ }
1603
+ else {
1604
+ // 非修饰键按旧逻辑匹配 code/key + location
1605
+ if (shortcut.code) {
1606
+ if (event.code === shortcut.code) {
1607
+ keyMatches = shortcut.location !== undefined ? event.location === shortcut.location : true;
1608
+ }
1609
+ }
1610
+ if (!keyMatches && shortcut.key) {
1611
+ if (event.key === shortcut.key) {
1612
+ keyMatches = shortcut.location !== undefined ? event.location === shortcut.location : true;
1613
+ }
1614
+ }
1615
+ }
1616
+ if (!shortcut.code && !shortcut.key)
1617
+ return false;
1618
+ if (!keyMatches)
1619
+ return false;
1620
+ // 检查其他修饰键
1621
+ var isAltKey = isAltShortcut;
1622
+ var isCtrlKey = isCtrlShortcut;
1623
+ var isShiftKey = isShiftShortcut;
1624
+ if (isAltKey && (event.ctrlKey || event.shiftKey || event.metaKey))
1625
+ return false;
1626
+ if (isCtrlKey && (event.altKey || event.shiftKey || event.metaKey))
1627
+ return false;
1628
+ if (isShiftKey && (event.altKey || event.ctrlKey || event.metaKey))
1629
+ return false;
1630
+ if (!isAltKey && !isCtrlKey && !isShiftKey && (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey))
1631
+ return false;
1632
+ var isMatch = true;
1633
+ console.log('[SDK] 快捷键匹配成功:', {
1634
+ eventCode: event.code,
1635
+ eventKey: event.key,
1636
+ eventLocation: event.location,
1637
+ shortcutConfig: shortcut,
1638
+ isMatch: isMatch
1639
+ });
1640
+ return isMatch;
1641
+ }
1642
+ // 键盘按下
1643
+ function handleKeyDown(event) {
1644
+ var state = getState();
1645
+ if (!isShortcutKey(event))
1646
+ return;
1647
+ // 避免长按重复触发
1648
+ if (event.repeat) {
1649
+ event.preventDefault();
1650
+ return;
1651
+ }
1652
+ // 仅长按才开始录音:按下立即记录状态,超过阈值后再启动录音
1653
+ if (state.isKeyPressed)
1654
+ return;
1655
+ // 如果 RewriteResult 显示,先关闭它
1656
+ if (state.rewriteResultRoot) {
1657
+ hideRewriteResult();
1658
+ }
1659
+ var selectedText = getSelectedText(state.currentInputElement);
1660
+ var hasSelection = !!selectedText;
1661
+ var hasFocusedInput = !!state.currentInputElement && document.activeElement === state.currentInputElement;
1662
+ if (!hasSelection && !hasFocusedInput) {
1663
+ showToast('请先聚焦输入框或框选文本', 'info');
1664
+ return;
1665
+ }
1666
+ console.log('[SDK] 快捷键按下 - 等待长按开始录音', {
1667
+ eventCode: event.code,
1668
+ eventKey: event.key,
1669
+ currentInputElement: state.currentInputElement,
1670
+ hasSelection: hasSelection,
1671
+ hasFocusedInput: hasFocusedInput
1672
+ });
1673
+ updateState({
1674
+ isKeyPressed: true,
1675
+ isRecordingStarting: true,
1676
+ isIndicatorShown: false,
1677
+ selectedText: selectedText
1678
+ });
1679
+ event.preventDefault();
1680
+ hideStatusIndicator();
1681
+ // 设置长按启动定时器
1682
+ longPressTimer = window.setTimeout(function () {
1683
+ var currentState = getState();
1684
+ if (!currentState.isKeyPressed)
1685
+ return;
1686
+ updateState({ isRecordingStarting: false });
1687
+ startSpeechRecognition(currentState.recognitionLang);
1688
+ }, LONG_PRESS_DELAY);
1689
+ }
1690
+ // 键盘松开
1691
+ function handleKeyUp(event) {
1692
+ var state = getState();
1693
+ if (!isShortcutKey(event))
1694
+ return;
1695
+ event.preventDefault();
1696
+ // 取消长按启动定时器
1697
+ if (longPressTimer !== null) {
1698
+ clearTimeout(longPressTimer);
1699
+ longPressTimer = null;
1700
+ }
1701
+ if (state.isRecording) {
1702
+ console.log('[SDK] 快捷键松开 - 停止录音', {
1703
+ eventCode: event.code,
1704
+ eventKey: event.key,
1705
+ isRecording: state.isRecording
1706
+ });
1707
+ showStatusIndicator('loading');
1708
+ stopSpeechRecognition();
1709
+ }
1710
+ updateState({
1711
+ isKeyPressed: false,
1712
+ isRecordingStarting: false,
1713
+ isIndicatorShown: false
1714
+ });
1715
+ }
1716
+ // 输入框聚焦
1717
+ function handleFocus(event) {
1718
+ var target = event.target;
1719
+ if (target.tagName === 'INPUT' ||
1720
+ target.tagName === 'TEXTAREA' ||
1721
+ target.contentEditable === 'true' ||
1722
+ (target instanceof HTMLInputElement) ||
1723
+ (target instanceof HTMLTextAreaElement)) {
1724
+ var element = target;
1725
+ updateState({ currentInputElement: element });
1726
+ setCurrentInputElementForTextInput(element);
1727
+ }
1728
+ }
1729
+ // 输入框失焦
1730
+ function handleBlur(event) {
1731
+ getState();
1732
+ var isRecording = getRecordingState().isRecording;
1733
+ if (isRecording) {
1734
+ stopSpeechRecognition();
1735
+ updateState({ isKeyPressed: false });
1736
+ hideStatusIndicator();
1737
+ }
1738
+ // 失焦后清理当前输入框引用,避免使用旧的选区
1739
+ updateState({ currentInputElement: null, selectedText: '' });
1740
+ setCurrentInputElementForTextInput(null);
1741
+ }
1742
+ // 初始化事件处理器
1743
+ function initEventHandlers() {
1744
+ console.log(123);
1745
+ var state = getState();
1746
+ // 避免重复注册(例如 publicKey 变更触发 reinit)
1747
+ if (eventHandlersRegistered)
1748
+ return;
1749
+ // 设置语音识别回调
1750
+ setSpeechRecognitionCallbacks({
1751
+ onStart: function () {
1752
+ if (state.isKeyPressed) {
1753
+ updateState({ isIndicatorShown: true });
1754
+ }
1755
+ },
1756
+ onUpdate: function () {
1757
+ // 文本更新时保持 speaking 状态
1758
+ },
1759
+ onEnd: function (finalText) {
1760
+ var currentState = getState();
1761
+ var selectedText = currentState.selectedText;
1762
+ updateState({
1763
+ isIndicatorShown: false,
1764
+ isRecordingStarting: false,
1765
+ isKeyPressed: false,
1766
+ selectedText: ''
1767
+ });
1768
+ if (finalText) {
1769
+ if (selectedText) {
1770
+ // 选中文本走重写接口,保持 loading 状态直到接口返回
1771
+ // 不在这里隐藏 loading,让 rewriteSelectedText 处理
1772
+ showStatusIndicator('loading');
1773
+ rewriteSelectedText(selectedText, finalText);
1774
+ }
1775
+ else {
1776
+ // 输入框聚焦场景,按原逻辑插入
1777
+ hideStatusIndicator();
1778
+ insertTextToInput(finalText);
1779
+ // showToast('语音输入完成', 'success');
1780
+ }
1781
+ }
1782
+ else {
1783
+ // 没有识别到文本,隐藏 loading
1784
+ hideStatusIndicator();
1785
+ }
1786
+ },
1787
+ onError: function (error) {
1788
+ updateState({ isIndicatorShown: false });
1789
+ console.log('error', error);
1790
+ showToast("\u670D\u52A1\u5668\u8FDE\u63A5\u8D85\u65F6", 'error');
1791
+ hideStatusIndicator();
1792
+ },
1793
+ shouldContinue: function () { return false; }
1794
+ });
1795
+ // 添加事件监听
1796
+ console.log('[SDK] 注册事件监听器', {
1797
+ shortcutKey: state.shortcutKey,
1798
+ recognitionLang: state.recognitionLang
1799
+ });
1800
+ document.addEventListener('keydown', handleKeyDown, true);
1801
+ document.addEventListener('keyup', handleKeyUp, true);
1802
+ document.addEventListener('focusin', handleFocus, true);
1803
+ document.addEventListener('focusout', handleBlur, true);
1804
+ eventHandlersRegistered = true;
1805
+ console.log('[SDK] 事件监听器注册完成');
1806
+ }
1807
+ // 卸载事件处理器(用于重新初始化,避免重复注册)
1808
+ function destroyEventHandlers() {
1809
+ if (!eventHandlersRegistered)
1810
+ return;
1811
+ // 清理长按定时器
1812
+ if (longPressTimer !== null) {
1813
+ clearTimeout(longPressTimer);
1814
+ longPressTimer = null;
1815
+ }
1816
+ document.removeEventListener('keydown', handleKeyDown, true);
1817
+ document.removeEventListener('keyup', handleKeyUp, true);
1818
+ document.removeEventListener('focusin', handleFocus, true);
1819
+ document.removeEventListener('focusout', handleBlur, true);
1820
+ eventHandlersRegistered = false;
1821
+ }
1822
+ // 当前不对外暴露快捷键配置获取能力
1823
+
1824
+ // 核心功能:初始化和配置
1825
+ // 确保样式在 DOM 准备好后注入
1826
+ function ensureStylesInjected() {
1827
+ if (typeof document === 'undefined')
1828
+ return;
1829
+ // 检查样式是否已经注入
1830
+ var existingStyles = document.querySelectorAll('style[data-sdk-styles]');
1831
+ if (existingStyles.length > 0)
1832
+ return;
1833
+ // 如果 document.head 还没准备好,等待
1834
+ if (!document.head) {
1835
+ if (document.readyState === 'loading') {
1836
+ document.addEventListener('DOMContentLoaded', ensureStylesInjected);
1837
+ return;
1838
+ }
1839
+ else {
1840
+ setTimeout(ensureStylesInjected, 0);
1841
+ return;
1842
+ }
1843
+ }
1844
+ // 样式应该已经由 rollup-plugin-postcss 注入,这里只是确保
1845
+ // 如果样式没有注入,尝试从全局变量获取并注入
1846
+ // 注意:这需要 rollup-plugin-postcss 生成的样式变量在全局作用域
1847
+ }
1848
+ function sense_ai_helper_sdk_voice_to_text(options) {
1849
+ var _a, _b;
1850
+ var state = getState();
1851
+ if (state.isInitialized)
1852
+ return;
1853
+ // 先设置环境前缀(因为API URL生成依赖它)
1854
+ if ((options === null || options === void 0 ? void 0 : options.envPrefix) !== undefined) {
1855
+ updateState({ envPrefix: options.envPrefix });
1856
+ }
1857
+ // 设置 API 配置
1858
+ updateState({
1859
+ asrApi: {
1860
+ url: ((_a = options === null || options === void 0 ? void 0 : options.asrApi) === null || _a === void 0 ? void 0 : _a.url) || getDefaultAsrApiUrl(),
1861
+ headers: ((_b = options === null || options === void 0 ? void 0 : options.asrApi) === null || _b === void 0 ? void 0 : _b.headers) || {},
1862
+ mode: 'stream'
1863
+ }
1864
+ });
1865
+ // 设置识别语言
1866
+ if (options === null || options === void 0 ? void 0 : options.lang) {
1867
+ updateState({ recognitionLang: options.lang });
1868
+ }
1869
+ // 初始化鉴权与通用参数
1870
+ updateState({
1871
+ publicKey: (options === null || options === void 0 ? void 0 : options.publicKey) || '',
1872
+ targetLang: (options === null || options === void 0 ? void 0 : options.targetLang) || state.targetLang || 'None',
1873
+ model: 'sense-asr-deepthink',
1874
+ authToken: null,
1875
+ authTokenPromise: null
1876
+ });
1877
+ // 预取 token(不阻塞初始化;真正发请求时会 await)
1878
+ if (options === null || options === void 0 ? void 0 : options.publicKey) {
1879
+ prefetchAuthToken().catch(function () {
1880
+ // 这里不做 toast,交给实际请求时的错误处理
1881
+ });
1882
+ }
1883
+ // 设置快捷键
1884
+ if (options === null || options === void 0 ? void 0 : options.shortcutKey) {
1885
+ updateState({ shortcutKey: options.shortcutKey });
1886
+ }
1887
+ updateState({ isInitialized: true });
1888
+ // 确保样式已注入
1889
+ ensureStylesInjected();
1890
+ // 初始化事件处理器
1891
+ initEventHandlers();
1892
+ }
1893
+ /**
1894
+ * 重新初始化 SDK(用于 publicKey 变更等场景)。
1895
+ * - 会先卸载事件监听,避免重复注册
1896
+ * - 会复用当前 state 的配置作为默认值
1897
+ */
1898
+ function reinitInputListenerSDK(options) {
1899
+ var _a, _b, _c, _d, _e;
1900
+ var state = getState();
1901
+ // 如果已初始化,先卸载监听避免重复
1902
+ if (state.isInitialized) {
1903
+ destroyEventHandlers();
1904
+ }
1905
+ updateState({ isInitialized: false });
1906
+ sense_ai_helper_sdk_voice_to_text({
1907
+ lang: (_a = options === null || options === void 0 ? void 0 : options.lang) !== null && _a !== void 0 ? _a : state.recognitionLang,
1908
+ shortcutKey: (_b = options === null || options === void 0 ? void 0 : options.shortcutKey) !== null && _b !== void 0 ? _b : state.shortcutKey,
1909
+ asrApi: (_c = options === null || options === void 0 ? void 0 : options.asrApi) !== null && _c !== void 0 ? _c : state.asrApi,
1910
+ publicKey: (_d = options === null || options === void 0 ? void 0 : options.publicKey) !== null && _d !== void 0 ? _d : state.publicKey,
1911
+ targetLang: (_e = options === null || options === void 0 ? void 0 : options.targetLang) !== null && _e !== void 0 ? _e : state.targetLang
1912
+ });
1913
+ }
1914
+ /** 运行时修改 targetLang:直接替换即可 */
1915
+ function setTargetLang$1(targetLang) {
1916
+ updateState({ targetLang: targetLang });
1917
+ }
1918
+ /**
1919
+ * 运行时修改 publicKey:需要重新初始化 SDK(并重新换取 token)。
1920
+ * 说明:会保留现有的 lang/shortcutKey/asrApi 配置。
1921
+ */
1922
+ function setPublicKey$1(publicKey) {
1923
+ reinitInputListenerSDK({ publicKey: publicKey });
1924
+ // 预取 token(不阻塞)
1925
+ prefetchAuthToken().catch(function () { });
1926
+ }
1927
+
1928
+ // 输入框监听 SDK(对外只暴露 publicKey / targetLang)
1929
+ // 初始化输入框监听 SDK
1930
+ function initInputListenerSDK(options) {
1931
+ console.log('语音识别SDK初始化');
1932
+ if ((options === null || options === void 0 ? void 0 : options.enabled) === false) {
1933
+ return;
1934
+ }
1935
+ var convertedOptions = options
1936
+ ? {
1937
+ publicKey: options.publicKey,
1938
+ targetLang: options.targetLang,
1939
+ envPrefix: options.envPrefix
1940
+ }
1941
+ : undefined;
1942
+ // 等待 DOM 加载完成
1943
+ if (document.readyState === 'loading') {
1944
+ document.addEventListener('DOMContentLoaded', function () {
1945
+ sense_ai_helper_sdk_voice_to_text(convertedOptions);
1946
+ });
1947
+ }
1948
+ else {
1949
+ sense_ai_helper_sdk_voice_to_text(convertedOptions);
1950
+ }
1951
+ }
1952
+ // 运行时修改 publicKey:内部会触发重新初始化并重新换取 token
1953
+ function setPublicKey(publicKey) {
1954
+ setPublicKey$1(publicKey);
1955
+ }
1956
+ // 运行时修改 targetLang:直接替换即可
1957
+ function setTargetLang(targetLang) {
1958
+ setTargetLang$1(targetLang);
1959
+ }
1960
+ // 命名导出
1961
+ var InputListener = {
1962
+ init: initInputListenerSDK,
1963
+ setPublicKey: setPublicKey,
1964
+ setTargetLang: setTargetLang
1965
+ };
1966
+ // 注意:不再在脚本加载/模块导入时自动初始化。
1967
+ // 如需启用,请由业务方显式调用 initInputListenerSDK() 或 InputListener.init()。
1968
+
1969
+ var InputListenerSDK = /*#__PURE__*/Object.freeze({
1970
+ __proto__: null,
1971
+ InputListener: InputListener,
1972
+ initInputListenerSDK: initInputListenerSDK,
1973
+ setPublicKey: setPublicKey,
1974
+ setTargetLang: setTargetLang
1975
+ });
1976
+
1977
+ // 所有 SDK 的统一导出入口
1978
+ var SDKs = {
1979
+ InputListener: InputListenerSDK,
1980
+ };
1981
+
1982
+ // 主入口文件 - 导出所有 SDK 模块
1983
+ // 初始化 SDK(向后兼容)
1984
+ function initSDK(options) {
1985
+ initInputListenerSDK(options);
1986
+ }
1987
+ // 注意:不再在脚本加载/模块导入时自动初始化。
1988
+ // 如需启用,请由业务方显式调用 initSDK()。
1989
+
1990
+ export { InputListener, SDKs, initInputListenerSDK, initSDK, setPublicKey, setTargetLang };
2
1991
  //# sourceMappingURL=index.js.map