diff --git a/docs/assets/example/asr.js b/docs/assets/example/asr.js index e6ebfdab9..d70307133 100644 --- a/docs/assets/example/asr.js +++ b/docs/assets/example/asr.js @@ -11,16 +11,25 @@ var art = new Artplayer({ sampleRate: 16000, autoHideTimeout: 10000, // Use your AI tool to convert buffer into subtitles - onAudioChunk: (buffer) => tencentASR(buffer), + onAudioChunk: (buffer) => startAsr(buffer), }), ] }); var ws = null; var loading = false; -async function tencentASR(buffer) { - if (loading) return; +function stopAsr() { + try { + ws.send(JSON.stringify({ type: 'end' })); + ws.close(); + } catch {} + ws = null; + loading = false; +} + +async function startAsr(buffer) { + if (loading) return; if (!ws) { loading = true; const api = 'https://api.aimu.app/asr/tencent?engine_model_type=16k_en'; @@ -30,26 +39,16 @@ async function tencentASR(buffer) { ws.onmessage = (event) => { const { code, result } = JSON.parse(event.data); if (code === 0) { - const subtitle = result?.voice_text_str; - art.plugins.artplayerPluginAsr.append(subtitle); + art.plugins.artplayerPluginAsr.append(result.voice_text_str); } else { - ws.close(); - ws = null; + stopAsr(); } - }; loading = false; } - - if (ws.readyState === WebSocket.OPEN) { + if (ws?.readyState === WebSocket.OPEN) { ws.send(buffer); } } -art.on('destroy', () => { - try { - ws.send(JSON.stringify({ type: 'end' })); - ws.close(); - } catch {} - ws = null; -}); +art.on('destroy', stopAsr); diff --git a/docs/compiled/artplayer-plugin-asr.esm.js b/docs/compiled/artplayer-plugin-asr.esm.js index 7224d7ef9..84d9e864f 100644 --- a/docs/compiled/artplayer-plugin-asr.esm.js +++ b/docs/compiled/artplayer-plugin-asr.esm.js @@ -5,5 +5,5 @@ * (c) 2017-2025 Harvey Zack * Released under the MIT License. */ -!function(e,t,r,n,o,a,l,i){var u="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof u[n]&&u[n],c=s.i||{},d=s.cache||{},p="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function f(t,r){if(!d[t]){if(!e[t]){if(o[t])return o[t];var a="function"==typeof u[n]&&u[n];if(!r&&a)return a(t,!0);if(s)return s(t,!0);if(p&&"string"==typeof t)return p(t);var l=Error("Cannot find module '"+t+"'");throw l.code="MODULE_NOT_FOUND",l}c.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},c.cache={};var i=d[t]=new f.Module(t);e[t][0].call(i.exports,c,i,i.exports,u)}return d[t].exports;function c(e){var t=c.resolve(e);return!1===t?{}:f(t)}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.require=p,this.exports={}},f.modules=e,f.cache=d,f.parent=s,f.distDir=void 0,f.publicUrl=void 0,f.devServer=void 0,f.i=c,f.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(f,"root",{get:function(){return u[n]}}),u[n]=f;for(var y=0;yi);var a=e("bundle-text:./style.less"),l=o.interopDefault(a);function i(e={}){let{hideTimeout:t=1e4,length:r=3,interval:n=100,sampleRate:o=16e3,onAudioChunk:a=()=>null}=e;return e=>{let l=!1,i=null,u=null,s=null,c=null,d=[],p=null,f=!1,y=null,m=null,b=null,g=e.layers.add({name:"asr",html:""});function v(){g.style.display="none"}function x(e){"string"==typeof e&&(clearTimeout(y),y=setTimeout(v,t),g.style.display="",g.innerHTML=e.split(/(?<=[、。!?!?\.])\s*/u).map(e=>e.trim()).filter(Boolean).slice(-r).map(e=>`
${e}
`).join(""))}let h=` class RecorderProcessor extends AudioWorkletProcessor { process(inputs) { const input = inputs[0]; if (input && input[0]) { this.port.postMessage(input[0]); } return true; } } registerProcessor('recorder-processor', RecorderProcessor); `,w=()=>{let e=new Blob([h],{type:"application/javascript"});return URL.createObjectURL(e)};async function P(){return i||"suspended"===(i=new(window.AudioContext||window.webkitAudioContext)({sampleRate:o})).state&&await i.resume(),i}async function j(){if(!u&&e.video)try{return u=i.createMediaElementSource(e.video)}catch(e){console.warn("[artplayerPluginAsr] Direct connection failed, trying fallback...",e)}try{if(m||(m=await A(e.video)),m)return b=i.createMediaStreamSource(m)}catch(e){console.warn("[artplayerPluginAsr] MediaStream fallback failed:",e)}return null}async function A(e){try{if(e.captureStream)return e.captureStream();if(e.mozCaptureStream)return e.mozCaptureStream();return console.warn("[artplayerPluginAsr] captureStream not supported"),null}catch(e){return console.warn("[artplayerPluginAsr] Error capturing stream:",e),null}}async function M(){if(!l)try{await P();let e=await j();if(!e)throw Error("Could not establish audio source");if(!f){let e=w();await i.audioWorklet.addModule(e),URL.revokeObjectURL(e),f=!0}(c=i.createGain()).gain.value=1,(s=new AudioWorkletNode(i,"recorder-processor")).port.onmessage=e=>{d.push(new Float32Array(e.data))},e.connect(s),e.connect(c),c.connect(i.destination);let t=n/1e3*o;p=setInterval(async()=>{if(0===d.length)return;let e=new Float32Array(0);for(;e.lengthe.stop()),m=null),i&&(await i.close(),i=null),f=!1}return e.on("play",M),e.on("pause",C),e.on("destroy",O),{name:"artplayerPluginAsr",stop:O,hide:v,append:x}}}if("undefined"!=typeof document&&!document.getElementById("artplayer-plugin-asr")){let e=document.createElement("style");e.id="artplayer-plugin-asr",e.textContent=l.default,document.head.appendChild(e)}"undefined"!=typeof window&&(window.artplayerPluginAsr=i)},{"bundle-text:./style.less":"dKHY3","@parcel/transformer-js/src/esmodule-helpers.js":"5lQoW"}],dKHY3:[function(e,t,r,n){t.exports=".art-video-player .art-layer-asr{z-index:150;justify-content:end;gap:var(--art-subtitle-gap);padding:0 2%;padding-bottom:var(--art-subtitle-bottom);transition:padding-bottom var(--art-transition-duration)ease;text-shadow:var(--art-subtitle-border)1px 0 1px,var(--art-subtitle-border)0 1px 1px,var(--art-subtitle-border)-1px 0 1px,var(--art-subtitle-border)0 -1px 1px,var(--art-subtitle-border)1px 1px 1px,var(--art-subtitle-border)-1px -1px 1px,var(--art-subtitle-border)1px -1px 1px,var(--art-subtitle-border)-1px 1px 1px;flex-direction:column;font-size:1rem;display:flex;position:absolute;inset:0;pointer-events:none!important}.art-video-player.art-control-show .art-layer-asr{padding-bottom:calc(var(--art-control-height) + var(--art-subtitle-bottom))}"},{}],"5lQoW":[function(e,t,r,n){r.interopDefault=function(e){return e&&e.__esModule?e:{default:e}},r.defineInteropFlag=function(e){Object.defineProperty(e,"__esModule",{value:!0})},r.exportAll=function(e,t){return Object.keys(e).forEach(function(r){"default"===r||"__esModule"===r||Object.prototype.hasOwnProperty.call(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:function(){return e[r]}})}),t},r.export=function(e,t,r){Object.defineProperty(e,t,{enumerable:!0,get:r})}},{}]},["40eeC"],"40eeC","parcelRequire4dc0",{});let{default:e}=parcelRequire4dc0("40eeC");export{e as default}; +!function(e,t,r,n,o,a,l,i){var u="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof u[n]&&u[n],c=s.i||{},d=s.cache||{},p="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function f(t,r){if(!d[t]){if(!e[t]){if(o[t])return o[t];var a="function"==typeof u[n]&&u[n];if(!r&&a)return a(t,!0);if(s)return s(t,!0);if(p&&"string"==typeof t)return p(t);var l=Error("Cannot find module '"+t+"'");throw l.code="MODULE_NOT_FOUND",l}c.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},c.cache={};var i=d[t]=new f.Module(t);e[t][0].call(i.exports,c,i,i.exports,u)}return d[t].exports;function c(e){var t=c.resolve(e);return!1===t?{}:f(t)}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.require=p,this.exports={}},f.modules=e,f.cache=d,f.parent=s,f.distDir=void 0,f.publicUrl=void 0,f.devServer=void 0,f.i=c,f.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(f,"root",{get:function(){return u[n]}}),u[n]=f;for(var y=0;yi);var a=e("bundle-text:./style.less"),l=o.interopDefault(a);function i(e={}){let{length:t=3,interval:r=100,sampleRate:n=16e3,autoHideTimeout:o=1e4,onAudioChunk:a=()=>null}=e;return e=>{let l=!1,i=null,u=null,s=null,c=null,d=[],p=null,f=!1,y=null,m=null,b=null,g=e.layers.add({name:"asr",html:""});function v(){g.style.display="none"}function x(e){"string"==typeof e&&(clearTimeout(y),y=setTimeout(v,o),g.style.display="",g.innerHTML=e.split(/(?<=[、。!?!?\.])\s*/u).map(e=>e.trim()).filter(Boolean).slice(-t).map(e=>`
${e}
`).join(""))}let h=` class RecorderProcessor extends AudioWorkletProcessor { process(inputs) { const input = inputs[0]; if (input && input[0]) { this.port.postMessage(input[0]); } return true; } } registerProcessor('recorder-processor', RecorderProcessor); `,w=()=>{let e=new Blob([h],{type:"application/javascript"});return URL.createObjectURL(e)};async function P(){return i||"suspended"===(i=new(window.AudioContext||window.webkitAudioContext)({sampleRate:n})).state&&await i.resume(),i}async function j(){if(!u&&e.video)try{return u=i.createMediaElementSource(e.video)}catch(e){console.warn("[artplayerPluginAsr] Direct connection failed, trying fallback...",e)}try{if(m||(m=await A(e.video)),m)return b=i.createMediaStreamSource(m)}catch(e){console.warn("[artplayerPluginAsr] MediaStream fallback failed:",e)}return null}async function A(e){try{if(e.captureStream)return e.captureStream();if(e.mozCaptureStream)return e.mozCaptureStream();return console.warn("[artplayerPluginAsr] captureStream not supported"),null}catch(e){return console.warn("[artplayerPluginAsr] Error capturing stream:",e),null}}async function M(){if(!l)try{await P();let e=await j();if(!e)throw Error("Could not establish audio source");if(!f){let e=w();await i.audioWorklet.addModule(e),URL.revokeObjectURL(e),f=!0}(c=i.createGain()).gain.value=1,(s=new AudioWorkletNode(i,"recorder-processor")).port.onmessage=e=>{d.push(new Float32Array(e.data))},e.connect(s),e.connect(c),c.connect(i.destination);let t=r/1e3*n;p=setInterval(async()=>{if(0===d.length)return;let e=new Float32Array(0);for(;e.lengthe.stop()),m=null),i&&(await i.close(),i=null),f=!1}return e.on("play",M),e.on("pause",C),e.on("destroy",O),{name:"artplayerPluginAsr",stop:O,hide:v,append:x}}}if("undefined"!=typeof document&&!document.getElementById("artplayer-plugin-asr")){let e=document.createElement("style");e.id="artplayer-plugin-asr",e.textContent=l.default,document.head.appendChild(e)}"undefined"!=typeof window&&(window.artplayerPluginAsr=i)},{"bundle-text:./style.less":"dKHY3","@parcel/transformer-js/src/esmodule-helpers.js":"5lQoW"}],dKHY3:[function(e,t,r,n){t.exports=".art-video-player .art-layer-asr{z-index:150;justify-content:end;gap:var(--art-subtitle-gap);padding:0 2%;padding-bottom:var(--art-subtitle-bottom);transition:padding-bottom var(--art-transition-duration)ease;text-shadow:var(--art-subtitle-border)1px 0 1px,var(--art-subtitle-border)0 1px 1px,var(--art-subtitle-border)-1px 0 1px,var(--art-subtitle-border)0 -1px 1px,var(--art-subtitle-border)1px 1px 1px,var(--art-subtitle-border)-1px -1px 1px,var(--art-subtitle-border)1px -1px 1px,var(--art-subtitle-border)-1px 1px 1px;flex-direction:column;font-size:1rem;display:flex;position:absolute;inset:0;pointer-events:none!important}.art-video-player.art-control-show .art-layer-asr{padding-bottom:calc(var(--art-control-height) + var(--art-subtitle-bottom))}"},{}],"5lQoW":[function(e,t,r,n){r.interopDefault=function(e){return e&&e.__esModule?e:{default:e}},r.defineInteropFlag=function(e){Object.defineProperty(e,"__esModule",{value:!0})},r.exportAll=function(e,t){return Object.keys(e).forEach(function(r){"default"===r||"__esModule"===r||Object.prototype.hasOwnProperty.call(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:function(){return e[r]}})}),t},r.export=function(e,t,r){Object.defineProperty(e,t,{enumerable:!0,get:r})}},{}]},["40eeC"],"40eeC","parcelRequire4dc0",{});let{default:e}=parcelRequire4dc0("40eeC");export{e as default}; //# sourceMappingURL=artplayer-plugin-asr.esm.js.map \ No newline at end of file diff --git a/docs/compiled/artplayer-plugin-asr.esm.js.map b/docs/compiled/artplayer-plugin-asr.esm.js.map index 92fe74b29..270af49da 100644 --- a/docs/compiled/artplayer-plugin-asr.esm.js.map +++ b/docs/compiled/artplayer-plugin-asr.esm.js.map @@ -1 +1 @@ -{"mappings":"C,A,S,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,E,I,E,A,a,O,W,W,A,a,O,K,K,A,a,O,O,O,A,a,O,O,O,C,E,E,A,Y,O,C,C,E,E,C,C,E,C,E,E,C,E,C,E,E,E,K,E,C,E,E,A,a,O,Q,A,Y,O,O,O,E,O,O,C,I,C,Q,S,E,C,C,C,E,G,C,C,C,E,C,C,G,C,C,C,E,C,C,G,C,C,E,C,O,C,C,E,C,I,E,A,Y,O,C,C,E,E,C,C,E,C,G,C,G,E,O,E,E,C,G,G,E,O,E,E,C,G,G,G,A,U,O,E,O,E,G,I,E,A,M,uB,E,I,O,E,I,C,mB,C,C,E,O,C,S,C,E,I,E,C,C,E,C,E,C,E,C,O,A,M,E,E,C,E,E,K,C,C,E,I,E,C,C,E,C,I,E,M,C,G,C,C,E,C,E,C,I,C,E,O,C,E,E,E,O,C,E,C,O,C,C,E,C,O,C,S,E,C,E,I,E,E,O,C,G,M,A,C,I,E,C,E,E,E,C,C,E,e,C,C,E,E,M,C,S,C,E,I,C,E,C,E,I,C,M,C,E,I,C,O,C,E,I,C,O,C,C,C,E,E,O,C,E,E,K,C,E,E,M,C,E,E,O,C,K,E,E,S,C,K,E,E,S,C,K,E,E,C,C,E,E,Q,C,S,C,C,C,E,C,C,E,C,C,S,C,C,C,E,E,O,C,C,E,C,E,A,E,O,c,C,E,O,C,I,W,O,C,C,E,A,C,G,C,C,E,C,E,I,I,E,E,E,E,M,C,I,E,C,C,E,E,G,E,C,I,E,E,E,A,C,U,O,S,A,a,O,O,O,O,C,E,A,Y,O,Q,O,G,E,O,W,O,C,E,C,E,C,Q,C,S,C,C,C,C,C,C,C,E,I,E,E,kD,E,iB,C,GCEwB,EAAA,MAAA,CAAA,EAAA,UAAA,IAAA,GAFxB,IAAA,EAAA,EAAA,4B,E,E,c,C,GAEe,SAAS,EAAmB,EAAS,CAAC,CAAC,EAClD,GAAM,CAAE,YAAA,EAAc,GAAK,CAAE,OAAA,EAAS,CAAC,CAAE,SAAA,EAAW,GAAG,CAAE,WAAA,EAAa,IAAK,CAAE,aAAA,EAAe,IAAM,IAAI,CAAE,CAAG,EAE3G,OAAO,AAAC,IACJ,IAAI,EAAU,CAAA,EACV,EAAW,KACX,EAAa,KACb,EAAe,KACf,EAAW,KACX,EAAe,EAAE,CACjB,EAAQ,KACR,EAAgB,CAAA,EAChB,EAAY,KACZ,EAAc,KACd,EAAoB,KAElB,EAAO,EAAI,MAAM,CAAC,GAAG,CAAC,CACxB,KAAM,MACN,KAAM,EACV,GAaA,SAAS,IACL,EAAK,KAAK,CAAC,OAAO,CAAG,MACzB,CAEA,SAAS,EAAO,CAAQ,EAChB,AAAoB,UAApB,OAAO,IACX,aAAa,GACb,EAAY,WAAW,EAAM,GAC7B,EAAK,KAAK,CAAC,OAAO,CAAG,GACrB,EAAK,SAAS,CAAG,AAlBb,AAkBgC,EAhB3B,KAAK,CAAC,uBACN,GAAG,CAAC,AAAC,GAAM,EAAE,IAAI,IACjB,MAAM,CAAC,SACP,KAAK,CAAC,CAAC,GAcX,GAAG,CAAC,AAAC,GAAS,CAAC,0BAA0B,EAAE,EAAK,MAAM,CAAC,EACvD,IAAI,CAAC,IACd,CAEA,IAAM,EAAwB;A;A;A;A;A;A;A;A;A;A;AAW9B,QAAA,CAAC,CAEK,EAAuB,KACzB,IAAM,EAAO,IAAI,KAAK,CAAC,EAAsB,CAAE,CAAE,KAAM,wBAAyB,GAChF,OAAO,IAAI,eAAe,CAAC,EAC/B,EAaA,eAAe,WACP,GAEA,AAAmB,cAAnB,AADJ,CAAA,EAAW,GAAK,CAAA,OAAO,YAAY,EAAI,OAAO,kBAAkB,AAAlB,EAAoB,CAAE,WAAA,CAAW,EAAA,EAClE,KAAK,EAAkB,MAAM,EAAS,MAAM,GAFpC,CAIzB,CAEA,eAAe,IACX,GAAI,CAAC,GAAc,EAAI,KAAK,CACxB,GAAI,CAEA,OADA,EAAa,EAAS,wBAAwB,CAAC,EAAI,KAAK,CAE5D,CAAE,MAAO,EAAK,CACV,QAAQ,IAAI,CAAC,oEAAqE,EACtF,CAGJ,GAAI,CAIA,GAHI,AAAC,GACD,CAAA,EAAc,MAAM,EAAsB,EAAI,KAAK,CAAA,EAEnD,EAEA,OADA,EAAoB,EAAS,uBAAuB,CAAC,EAG7D,CAAE,MAAO,EAAK,CACV,QAAQ,IAAI,CAAC,oDAAqD,EACtE,CAEA,OAAO,IACX,CAEA,eAAe,EAAsB,CAAY,EAC7C,GAAI,CACA,GAAI,EAAa,aAAa,CAAE,OAAO,EAAa,aAAa,GACjE,GAAI,EAAa,gBAAgB,CAAE,OAAO,EAAa,gBAAgB,GAEvE,OADA,QAAQ,IAAI,CAAC,oDACN,IACX,CAAE,MAAO,EAAK,CAEV,OADA,QAAQ,IAAI,CAAC,+CAAgD,GACtD,IACX,CACJ,CAEA,eAAe,IACX,IAAI,EAEJ,GAAI,CACA,MAAM,IACN,IAAM,EAAc,MAAM,IAC1B,GAAI,CAAC,EAAa,MAAM,AAAI,MAAM,oCAElC,GAAI,CAAC,EAAe,CAChB,IAAM,EAAU,GAChB,OAAM,EAAS,YAAY,CAAC,SAAS,CAAC,GACtC,IAAI,eAAe,CAAC,GACpB,EAAgB,CAAA,CACpB,CAIA,AADA,CAAA,EAAW,EAAS,UAAU,EAA9B,EACS,IAAI,CAAC,KAAK,CAAG,EAGtB,AADA,CAAA,EAAe,IAAI,iBAAiB,EAAU,qBAA9C,EACa,IAAI,CAAC,SAAS,CAAG,AAAC,IAC3B,EAAa,IAAI,CAAC,IAAI,aAAa,EAAM,IAAI,EACjD,EAGA,EAAY,OAAO,CAAC,GACpB,EAAY,OAAO,CAAC,GAEpB,EAAS,OAAO,CAAC,EAAS,WAAW,EAGrC,IAAM,EAAgB,AAAc,EAAW,IAAzB,EACtB,EAAQ,YAAY,UAChB,GAAI,AAAwB,IAAxB,EAAa,MAAM,CAAQ,OAE/B,IAAI,EAAc,IAAI,aAAa,GACnC,KAAO,EAAY,MAAM,CAAG,GAAiB,EAAa,MAAM,EAAE,CAC9D,IAAM,EAAO,EAAa,KAAK,GACzB,EAAM,IAAI,aAAa,EAAY,MAAM,CAAG,EAAK,MAAM,EAC7D,EAAI,GAAG,CAAC,EAAa,GACrB,EAAI,GAAG,CAAC,EAAM,EAAY,MAAM,EAChC,EAAc,CAClB,CAEA,GAAI,EAAY,MAAM,CAAG,EAAe,OAExC,IAAM,EAAc,EAAY,KAAK,CAAC,EAAG,GACnC,EAAM,AAtGxB,SAAyB,CAAY,EACjC,IAAM,EAAM,EAAa,MAAM,CACzB,EAAS,IAAI,YAAY,AAAM,EAAN,GACzB,EAAO,IAAI,SAAS,GAC1B,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,IAAK,CAC1B,IAAI,EAAI,KAAK,GAAG,CAAC,GAAI,KAAK,GAAG,CAAC,EAAG,CAAY,CAAC,EAAE,GAChD,EAAK,QAAQ,CAAC,AAAI,EAAJ,EAAO,EAAI,EAAI,AAAI,MAAJ,EAAa,AAAI,MAAJ,EAAY,CAAA,EAC1D,CACA,OAAO,CACX,EA6FwC,GACtB,EAAW,MAAM,EAAa,GACpC,EAAO,EACX,EAAG,GAEH,EAAU,CAAA,CACd,CAAE,MAAO,EAAK,CACV,QAAQ,KAAK,CAAC,8CAA+C,GAC7D,MAAM,GACV,CACJ,CAEA,eAAe,IACN,IACL,EAAU,CAAA,EAEV,cAAc,GACd,EAAQ,KAEJ,IACA,EAAa,UAAU,GACvB,EAAa,IAAI,CAAC,SAAS,CAAG,KAC9B,EAAe,MAGf,IACA,EAAS,UAAU,GACnB,EAAW,MAGf,EAAe,EAAE,CACrB,CAEA,eAAe,IACX,MAAM,IAEF,IACA,EAAkB,UAAU,GAC5B,EAAoB,MAGpB,IACA,EAAW,UAAU,GACrB,EAAa,MAGb,IACA,EAAY,SAAS,GAAG,OAAO,CAAC,AAAC,GAAU,EAAM,IAAI,IACrD,EAAc,MAGd,IACA,MAAM,EAAS,KAAK,GACpB,EAAW,MAGf,EAAgB,CAAA,CACpB,CAMA,OAJA,EAAI,EAAE,CAAC,OAAQ,GACf,EAAI,EAAE,CAAC,QAAS,GAChB,EAAI,EAAE,CAAC,UAAW,GAEX,CACH,KAAM,qBACN,KAAM,EACN,KAAA,EACA,OAAA,CACJ,CACJ,CACJ,CAEA,GAAI,AAAoB,aAApB,OAAO,UACH,CAAC,SAAS,cAAc,CAAC,wBAAyB,CAClD,IAAM,EAAS,SAAS,aAAa,CAAC,QACtC,CAAA,EAAO,EAAE,CAAG,uBACZ,EAAO,WAAW,CAAG,EAAA,OAAK,CAC1B,SAAS,IAAI,CAAC,WAAW,CAAC,EAC9B,CAGA,AAAkB,aAAlB,OAAO,QACP,CAAA,OAAO,kBAAqB,CAAG,CADnC,C,E,C,2B,Q,iD,O,E,C,M,C,S,C,C,C,C,C,C,C,ECzPA,EAAO,OAAO,CAAG,qvB,E,C,E,C,Q,C,S,C,C,C,C,C,C,C,ECAjB,EAAQ,cAAc,CAAG,SAAU,CAAC,EAClC,OAAO,GAAK,EAAE,UAAU,CAAG,EAAI,CAAC,QAAS,CAAC,CAC5C,EAEA,EAAQ,iBAAiB,CAAG,SAAU,CAAC,EACrC,OAAO,cAAc,CAAC,EAAG,aAAc,CAAC,MAAO,CAAA,CAAI,EACrD,EAEA,EAAQ,SAAS,CAAG,SAAU,CAAM,CAAE,CAAI,EAkBxC,OAjBA,OAAO,IAAI,CAAC,GAAQ,OAAO,CAAC,SAAU,CAAG,EAE7B,YAAR,GACA,AAAQ,eAAR,GACA,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,EAAM,IAK7C,OAAO,cAAc,CAAC,EAAM,EAAK,CAC/B,WAAY,CAAA,EACZ,IAAK,WACH,OAAO,CAAM,CAAC,EAAI,AACpB,CACF,EACF,GAEO,CACT,EAEA,EAAQ,MAAM,CAAG,SAAU,CAAI,CAAE,CAAQ,CAAE,CAAG,EAC5C,OAAO,cAAc,CAAC,EAAM,EAAU,CACpC,WAAY,CAAA,EACZ,IAAK,CACP,EACF,C,E,C,E,E,C,Q,C,Q,oB,C,G,G,C,Q,C,C,C,kB,gB,K,O","sources":["","packages/artplayer-plugin-asr/src/index.js","node_modules/@parcel/runtime-js/lib/bundles/runtime-8d01a8f56d551fc8.js","node_modules/@parcel/transformer-js/src/esmodule-helpers.js"],"sourcesContent":["// modules are defined as an array\n// [ module function, map of requires ]\n//\n// map of requires is short require name -> numeric require\n//\n// anything defined in a previous bundle is accessed via the\n// orig method which is the require for previous bundles\n\n(function (\n modules,\n entry,\n mainEntry,\n parcelRequireName,\n externals,\n distDir,\n publicUrl,\n devServer\n) {\n /* eslint-disable no-undef */\n var globalObject =\n typeof globalThis !== 'undefined'\n ? globalThis\n : typeof self !== 'undefined'\n ? self\n : typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined'\n ? global\n : {};\n /* eslint-enable no-undef */\n\n // Save the require from previous bundle to this closure if any\n var previousRequire =\n typeof globalObject[parcelRequireName] === 'function' &&\n globalObject[parcelRequireName];\n\n var importMap = previousRequire.i || {};\n var cache = previousRequire.cache || {};\n // Do not use `require` to prevent Webpack from trying to bundle this call\n var nodeRequire =\n typeof module !== 'undefined' &&\n typeof module.require === 'function' &&\n module.require.bind(module);\n\n function newRequire(name, jumped) {\n if (!cache[name]) {\n if (!modules[name]) {\n if (externals[name]) {\n return externals[name];\n }\n // if we cannot find the module within our internal map or\n // cache jump to the current global require ie. the last bundle\n // that was added to the page.\n var currentRequire =\n typeof globalObject[parcelRequireName] === 'function' &&\n globalObject[parcelRequireName];\n if (!jumped && currentRequire) {\n return currentRequire(name, true);\n }\n\n // If there are other bundles on this page the require from the\n // previous one is saved to 'previousRequire'. Repeat this as\n // many times as there are bundles until the module is found or\n // we exhaust the require chain.\n if (previousRequire) {\n return previousRequire(name, true);\n }\n\n // Try the node require function if it exists.\n if (nodeRequire && typeof name === 'string') {\n return nodeRequire(name);\n }\n\n var err = new Error(\"Cannot find module '\" + name + \"'\");\n err.code = 'MODULE_NOT_FOUND';\n throw err;\n }\n\n localRequire.resolve = resolve;\n localRequire.cache = {};\n\n var module = (cache[name] = new newRequire.Module(name));\n\n modules[name][0].call(\n module.exports,\n localRequire,\n module,\n module.exports,\n globalObject\n );\n }\n\n return cache[name].exports;\n\n function localRequire(x) {\n var res = localRequire.resolve(x);\n return res === false ? {} : newRequire(res);\n }\n\n function resolve(x) {\n var id = modules[name][1][x];\n return id != null ? id : x;\n }\n }\n\n function Module(moduleName) {\n this.id = moduleName;\n this.bundle = newRequire;\n this.require = nodeRequire;\n this.exports = {};\n }\n\n newRequire.isParcelRequire = true;\n newRequire.Module = Module;\n newRequire.modules = modules;\n newRequire.cache = cache;\n newRequire.parent = previousRequire;\n newRequire.distDir = distDir;\n newRequire.publicUrl = publicUrl;\n newRequire.devServer = devServer;\n newRequire.i = importMap;\n newRequire.register = function (id, exports) {\n modules[id] = [\n function (require, module) {\n module.exports = exports;\n },\n {},\n ];\n };\n\n // Only insert newRequire.load when it is actually used.\n // The code in this file is linted against ES5, so dynamic import is not allowed.\n // INSERT_LOAD_HERE\n\n Object.defineProperty(newRequire, 'root', {\n get: function () {\n return globalObject[parcelRequireName];\n },\n });\n\n globalObject[parcelRequireName] = newRequire;\n\n for (var i = 0; i < entry.length; i++) {\n newRequire(entry[i]);\n }\n\n if (mainEntry) {\n // Expose entry point to Node, AMD or browser globals\n // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js\n var mainExports = newRequire(mainEntry);\n\n // CommonJS\n if (typeof exports === 'object' && typeof module !== 'undefined') {\n module.exports = mainExports;\n\n // RequireJS\n } else if (typeof define === 'function' && define.amd) {\n define(function () {\n return mainExports;\n });\n }\n }\n})({\"40eeC\":[function(require,module,exports,__globalThis) {\nvar parcelHelpers = require(\"@parcel/transformer-js/src/esmodule-helpers.js\");\nparcelHelpers.defineInteropFlag(exports);\nparcelHelpers.export(exports, \"default\", ()=>artplayerPluginAsr);\nvar _styleLess = require(\"bundle-text:./style.less\");\nvar _styleLessDefault = parcelHelpers.interopDefault(_styleLess);\nfunction artplayerPluginAsr(option = {}) {\n const { hideTimeout = 10000, length = 3, interval = 100, sampleRate = 16000, onAudioChunk = ()=>null } = option;\n return (art)=>{\n let started = false;\n let audioCtx = null;\n let sourceNode = null;\n let recorderNode = null;\n let gainNode = null;\n let bufferChunks = [];\n let timer = null;\n let workletLoaded = false;\n let hideTimer = null;\n let mediaStream = null;\n let mediaStreamSource = null;\n const $asr = art.layers.add({\n name: 'asr',\n html: ''\n });\n function splitByPunctuation(text) {\n return text// eslint-disable-next-line no-useless-escape\n .split(/(?<=[、。!?!?\\.])\\s*/u).map((s)=>s.trim()).filter(Boolean).slice(-length);\n }\n function hide() {\n $asr.style.display = 'none';\n }\n function append(subtitle) {\n if (typeof subtitle !== 'string') return;\n clearTimeout(hideTimer);\n hideTimer = setTimeout(hide, hideTimeout);\n $asr.style.display = '';\n $asr.innerHTML = splitByPunctuation(subtitle).map((line)=>`
${line}
`).join('');\n }\n const recorderProcessorCode = `\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n `;\n const createWorkletBlobUrl = ()=>{\n const blob = new Blob([\n recorderProcessorCode\n ], {\n type: 'application/javascript'\n });\n return URL.createObjectURL(blob);\n };\n function floatTo16BitPCM(float32Array) {\n const len = float32Array.length;\n const buffer = new ArrayBuffer(len * 2);\n const view = new DataView(buffer);\n for(let i = 0; i < len; i++){\n let s = Math.max(-1, Math.min(1, float32Array[i]));\n view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n }\n return buffer;\n }\n async function setupAudioContext() {\n if (audioCtx) return audioCtx;\n audioCtx = new (window.AudioContext || window.webkitAudioContext)({\n sampleRate\n });\n if (audioCtx.state === 'suspended') await audioCtx.resume();\n return audioCtx;\n }\n async function setupAudioSource() {\n if (!sourceNode && art.video) try {\n sourceNode = audioCtx.createMediaElementSource(art.video);\n return sourceNode;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Direct connection failed, trying fallback...', err);\n }\n try {\n if (!mediaStream) mediaStream = await captureAudioFromVideo(art.video);\n if (mediaStream) {\n mediaStreamSource = audioCtx.createMediaStreamSource(mediaStream);\n return mediaStreamSource;\n }\n } catch (err) {\n console.warn('[artplayerPluginAsr] MediaStream fallback failed:', err);\n }\n return null;\n }\n async function captureAudioFromVideo(videoElement) {\n try {\n if (videoElement.captureStream) return videoElement.captureStream();\n if (videoElement.mozCaptureStream) return videoElement.mozCaptureStream();\n console.warn('[artplayerPluginAsr] captureStream not supported');\n return null;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Error capturing stream:', err);\n return null;\n }\n }\n async function startCapture() {\n if (started) return;\n try {\n await setupAudioContext();\n const audioSource = await setupAudioSource();\n if (!audioSource) throw new Error('Could not establish audio source');\n if (!workletLoaded) {\n const blobUrl = createWorkletBlobUrl();\n await audioCtx.audioWorklet.addModule(blobUrl);\n URL.revokeObjectURL(blobUrl);\n workletLoaded = true;\n }\n // 创建输出音频的 GainNode(正常播放)\n gainNode = audioCtx.createGain();\n gainNode.gain.value = 1;\n recorderNode = new AudioWorkletNode(audioCtx, 'recorder-processor');\n recorderNode.port.onmessage = (event)=>{\n bufferChunks.push(new Float32Array(event.data));\n };\n // 分流:识别和播放\n audioSource.connect(recorderNode);\n audioSource.connect(gainNode);\n gainNode.connect(audioCtx.destination); // 正常声音输出\n // recorderNode 不连接 destination,避免输出干扰\n const CHUNK_SAMPLES = sampleRate * (interval / 1000);\n timer = setInterval(async ()=>{\n if (bufferChunks.length === 0) return;\n let accumulated = new Float32Array(0);\n while(accumulated.length < CHUNK_SAMPLES && bufferChunks.length){\n const next = bufferChunks.shift();\n const tmp = new Float32Array(accumulated.length + next.length);\n tmp.set(accumulated, 0);\n tmp.set(next, accumulated.length);\n accumulated = tmp;\n }\n if (accumulated.length < CHUNK_SAMPLES) return;\n const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES);\n const pcm = floatTo16BitPCM(chunkToSend);\n const subtitle = await onAudioChunk(pcm);\n append(subtitle);\n }, interval);\n started = true;\n } catch (err) {\n console.error('[artplayerPluginAsr] Initialization failed:', err);\n await stopCapture();\n }\n }\n async function stopCapture() {\n if (!started) return;\n started = false;\n clearInterval(timer);\n timer = null;\n if (recorderNode) {\n recorderNode.disconnect();\n recorderNode.port.onmessage = null;\n recorderNode = null;\n }\n if (gainNode) {\n gainNode.disconnect();\n gainNode = null;\n }\n bufferChunks = [];\n }\n async function destroy() {\n await stopCapture();\n if (mediaStreamSource) {\n mediaStreamSource.disconnect();\n mediaStreamSource = null;\n }\n if (sourceNode) {\n sourceNode.disconnect();\n sourceNode = null;\n }\n if (mediaStream) {\n mediaStream.getTracks().forEach((track)=>track.stop());\n mediaStream = null;\n }\n if (audioCtx) {\n await audioCtx.close();\n audioCtx = null;\n }\n workletLoaded = false;\n }\n art.on('play', startCapture);\n art.on('pause', stopCapture);\n art.on('destroy', destroy);\n return {\n name: 'artplayerPluginAsr',\n stop: destroy,\n hide,\n append\n };\n };\n}\nif (typeof document !== 'undefined') {\n if (!document.getElementById('artplayer-plugin-asr')) {\n const $style = document.createElement('style');\n $style.id = 'artplayer-plugin-asr';\n $style.textContent = (0, _styleLessDefault.default);\n document.head.appendChild($style);\n }\n}\nif (typeof window !== 'undefined') window['artplayerPluginAsr'] = artplayerPluginAsr;\n\n},{\"bundle-text:./style.less\":\"dKHY3\",\"@parcel/transformer-js/src/esmodule-helpers.js\":\"5lQoW\"}],\"dKHY3\":[function(require,module,exports,__globalThis) {\nmodule.exports = \".art-video-player .art-layer-asr{z-index:150;justify-content:end;gap:var(--art-subtitle-gap);padding:0 2%;padding-bottom:var(--art-subtitle-bottom);transition:padding-bottom var(--art-transition-duration)ease;text-shadow:var(--art-subtitle-border)1px 0 1px,var(--art-subtitle-border)0 1px 1px,var(--art-subtitle-border)-1px 0 1px,var(--art-subtitle-border)0 -1px 1px,var(--art-subtitle-border)1px 1px 1px,var(--art-subtitle-border)-1px -1px 1px,var(--art-subtitle-border)1px -1px 1px,var(--art-subtitle-border)-1px 1px 1px;flex-direction:column;font-size:1rem;display:flex;position:absolute;inset:0;pointer-events:none!important}.art-video-player.art-control-show .art-layer-asr{padding-bottom:calc(var(--art-control-height) + var(--art-subtitle-bottom))}\";\n\n},{}],\"5lQoW\":[function(require,module,exports,__globalThis) {\nexports.interopDefault = function(a) {\n return a && a.__esModule ? a : {\n default: a\n };\n};\nexports.defineInteropFlag = function(a) {\n Object.defineProperty(a, '__esModule', {\n value: true\n });\n};\nexports.exportAll = function(source, dest) {\n Object.keys(source).forEach(function(key) {\n if (key === 'default' || key === '__esModule' || Object.prototype.hasOwnProperty.call(dest, key)) return;\n Object.defineProperty(dest, key, {\n enumerable: true,\n get: function() {\n return source[key];\n }\n });\n });\n return dest;\n};\nexports.export = function(dest, destName, get) {\n Object.defineProperty(dest, destName, {\n enumerable: true,\n get: get\n });\n};\n\n},{}]},[\"40eeC\"], \"40eeC\", \"parcelRequire4dc0\", {})\nlet {default: _default, } = parcelRequire4dc0(\"40eeC\");\nexport {_default as default, };\n\n//# sourceMappingURL=index.js.map\n","import style from 'bundle-text:./style.less';\n\nexport default function artplayerPluginAsr(option = {}) {\n const { hideTimeout = 10000, length = 3, interval = 100, sampleRate = 16000, onAudioChunk = () => null } = option;\n\n return (art) => {\n let started = false;\n let audioCtx = null;\n let sourceNode = null;\n let recorderNode = null;\n let gainNode = null;\n let bufferChunks = [];\n let timer = null;\n let workletLoaded = false;\n let hideTimer = null;\n let mediaStream = null;\n let mediaStreamSource = null;\n\n const $asr = art.layers.add({\n name: 'asr',\n html: '',\n });\n\n function splitByPunctuation(text) {\n return (\n text\n // eslint-disable-next-line no-useless-escape\n .split(/(?<=[、。!?!?\\.])\\s*/u)\n .map((s) => s.trim())\n .filter(Boolean)\n .slice(-length)\n );\n }\n\n function hide() {\n $asr.style.display = 'none';\n }\n\n function append(subtitle) {\n if (typeof subtitle !== 'string') return;\n clearTimeout(hideTimer);\n hideTimer = setTimeout(hide, hideTimeout);\n $asr.style.display = '';\n $asr.innerHTML = splitByPunctuation(subtitle)\n .map((line) => `
${line}
`)\n .join('');\n }\n\n const recorderProcessorCode = `\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n `;\n\n const createWorkletBlobUrl = () => {\n const blob = new Blob([recorderProcessorCode], { type: 'application/javascript' });\n return URL.createObjectURL(blob);\n };\n\n function floatTo16BitPCM(float32Array) {\n const len = float32Array.length;\n const buffer = new ArrayBuffer(len * 2);\n const view = new DataView(buffer);\n for (let i = 0; i < len; i++) {\n let s = Math.max(-1, Math.min(1, float32Array[i]));\n view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n }\n return buffer;\n }\n\n async function setupAudioContext() {\n if (audioCtx) return audioCtx;\n audioCtx = new (window.AudioContext || window.webkitAudioContext)({ sampleRate });\n if (audioCtx.state === 'suspended') await audioCtx.resume();\n return audioCtx;\n }\n\n async function setupAudioSource() {\n if (!sourceNode && art.video) {\n try {\n sourceNode = audioCtx.createMediaElementSource(art.video);\n return sourceNode;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Direct connection failed, trying fallback...', err);\n }\n }\n\n try {\n if (!mediaStream) {\n mediaStream = await captureAudioFromVideo(art.video);\n }\n if (mediaStream) {\n mediaStreamSource = audioCtx.createMediaStreamSource(mediaStream);\n return mediaStreamSource;\n }\n } catch (err) {\n console.warn('[artplayerPluginAsr] MediaStream fallback failed:', err);\n }\n\n return null;\n }\n\n async function captureAudioFromVideo(videoElement) {\n try {\n if (videoElement.captureStream) return videoElement.captureStream();\n if (videoElement.mozCaptureStream) return videoElement.mozCaptureStream();\n console.warn('[artplayerPluginAsr] captureStream not supported');\n return null;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Error capturing stream:', err);\n return null;\n }\n }\n\n async function startCapture() {\n if (started) return;\n\n try {\n await setupAudioContext();\n const audioSource = await setupAudioSource();\n if (!audioSource) throw new Error('Could not establish audio source');\n\n if (!workletLoaded) {\n const blobUrl = createWorkletBlobUrl();\n await audioCtx.audioWorklet.addModule(blobUrl);\n URL.revokeObjectURL(blobUrl);\n workletLoaded = true;\n }\n\n // 创建输出音频的 GainNode(正常播放)\n gainNode = audioCtx.createGain();\n gainNode.gain.value = 1;\n\n recorderNode = new AudioWorkletNode(audioCtx, 'recorder-processor');\n recorderNode.port.onmessage = (event) => {\n bufferChunks.push(new Float32Array(event.data));\n };\n\n // 分流:识别和播放\n audioSource.connect(recorderNode);\n audioSource.connect(gainNode);\n\n gainNode.connect(audioCtx.destination); // 正常声音输出\n // recorderNode 不连接 destination,避免输出干扰\n\n const CHUNK_SAMPLES = sampleRate * (interval / 1000);\n timer = setInterval(async () => {\n if (bufferChunks.length === 0) return;\n\n let accumulated = new Float32Array(0);\n while (accumulated.length < CHUNK_SAMPLES && bufferChunks.length) {\n const next = bufferChunks.shift();\n const tmp = new Float32Array(accumulated.length + next.length);\n tmp.set(accumulated, 0);\n tmp.set(next, accumulated.length);\n accumulated = tmp;\n }\n\n if (accumulated.length < CHUNK_SAMPLES) return;\n\n const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES);\n const pcm = floatTo16BitPCM(chunkToSend);\n const subtitle = await onAudioChunk(pcm);\n append(subtitle);\n }, interval);\n\n started = true;\n } catch (err) {\n console.error('[artplayerPluginAsr] Initialization failed:', err);\n await stopCapture();\n }\n }\n\n async function stopCapture() {\n if (!started) return;\n started = false;\n\n clearInterval(timer);\n timer = null;\n\n if (recorderNode) {\n recorderNode.disconnect();\n recorderNode.port.onmessage = null;\n recorderNode = null;\n }\n\n if (gainNode) {\n gainNode.disconnect();\n gainNode = null;\n }\n\n bufferChunks = [];\n }\n\n async function destroy() {\n await stopCapture();\n\n if (mediaStreamSource) {\n mediaStreamSource.disconnect();\n mediaStreamSource = null;\n }\n\n if (sourceNode) {\n sourceNode.disconnect();\n sourceNode = null;\n }\n\n if (mediaStream) {\n mediaStream.getTracks().forEach((track) => track.stop());\n mediaStream = null;\n }\n\n if (audioCtx) {\n await audioCtx.close();\n audioCtx = null;\n }\n\n workletLoaded = false;\n }\n\n art.on('play', startCapture);\n art.on('pause', stopCapture);\n art.on('destroy', destroy);\n\n return {\n name: 'artplayerPluginAsr',\n stop: destroy,\n hide,\n append,\n };\n };\n}\n\nif (typeof document !== 'undefined') {\n if (!document.getElementById('artplayer-plugin-asr')) {\n const $style = document.createElement('style');\n $style.id = 'artplayer-plugin-asr';\n $style.textContent = style;\n document.head.appendChild($style);\n }\n}\n\nif (typeof window !== 'undefined') {\n window['artplayerPluginAsr'] = artplayerPluginAsr;\n}\n","module.exports = \"704cf673cb407483\";","exports.interopDefault = function (a) {\n return a && a.__esModule ? a : {default: a};\n};\n\nexports.defineInteropFlag = function (a) {\n Object.defineProperty(a, '__esModule', {value: true});\n};\n\nexports.exportAll = function (source, dest) {\n Object.keys(source).forEach(function (key) {\n if (\n key === 'default' ||\n key === '__esModule' ||\n Object.prototype.hasOwnProperty.call(dest, key)\n ) {\n return;\n }\n\n Object.defineProperty(dest, key, {\n enumerable: true,\n get: function () {\n return source[key];\n },\n });\n });\n\n return dest;\n};\n\nexports.export = function (dest, destName, get) {\n Object.defineProperty(dest, destName, {\n enumerable: true,\n get: get,\n });\n};\n"],"names":["modules","entry","mainEntry","parcelRequireName","externals","distDir","publicUrl","devServer","globalObject","globalThis","self","window","global","previousRequire","importMap","i","cache","nodeRequire","module","require","bind","newRequire","name","jumped","currentRequire","err","Error","code","localRequire","resolve","x","id","Module","call","exports","res","isParcelRequire","moduleName","bundle","parent","register","Object","defineProperty","get","length","mainExports","define","amd","__globalThis","parcelHelpers","defineInteropFlag","export","artplayerPluginAsr","_styleLess","_styleLessDefault","interopDefault","option","hideTimeout","interval","sampleRate","onAudioChunk","art","started","audioCtx","sourceNode","recorderNode","gainNode","bufferChunks","timer","workletLoaded","hideTimer","mediaStream","mediaStreamSource","$asr","layers","add","html","hide","style","display","append","subtitle","clearTimeout","setTimeout","innerHTML","splitByPunctuation","text","split","map","s","trim","filter","Boolean","slice","line","join","recorderProcessorCode","createWorkletBlobUrl","blob","Blob","type","URL","createObjectURL","setupAudioContext","AudioContext","webkitAudioContext","state","resume","setupAudioSource","video","createMediaElementSource","console","warn","captureAudioFromVideo","createMediaStreamSource","videoElement","captureStream","mozCaptureStream","startCapture","audioSource","blobUrl","audioWorklet","addModule","revokeObjectURL","createGain","gain","value","AudioWorkletNode","port","onmessage","event","push","Float32Array","data","connect","destination","CHUNK_SAMPLES","setInterval","accumulated","next","shift","tmp","set","chunkToSend","pcm","floatTo16BitPCM","float32Array","len","buffer","ArrayBuffer","view","DataView","Math","max","min","setInt16","error","stopCapture","clearInterval","disconnect","destroy","getTracks","forEach","track","stop","close","on","document","getElementById","$style","createElement","textContent","default","head","appendChild","a","__esModule","exportAll","source","dest","keys","key","prototype","hasOwnProperty","enumerable","destName","_default","parcelRequire4dc0"],"version":3,"file":"index.js.map"} \ No newline at end of file +{"mappings":"C,A,S,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,E,I,E,A,a,O,W,W,A,a,O,K,K,A,a,O,O,O,A,a,O,O,O,C,E,E,A,Y,O,C,C,E,E,C,C,E,C,E,E,C,E,C,E,E,E,K,E,C,E,E,A,a,O,Q,A,Y,O,O,O,E,O,O,C,I,C,Q,S,E,C,C,C,E,G,C,C,C,E,C,C,G,C,C,C,E,C,C,G,C,C,E,C,O,C,C,E,C,I,E,A,Y,O,C,C,E,E,C,C,E,C,G,C,G,E,O,E,E,C,G,G,E,O,E,E,C,G,G,G,A,U,O,E,O,E,G,I,E,A,M,uB,E,I,O,E,I,C,mB,C,C,E,O,C,S,C,E,I,E,C,C,E,C,E,C,E,C,O,A,M,E,E,C,E,E,K,C,C,E,I,E,C,C,E,C,I,E,M,C,G,C,C,E,C,E,C,I,C,E,O,C,E,E,E,O,C,E,C,O,C,C,E,C,O,C,S,E,C,E,I,E,E,O,C,G,M,A,C,I,E,C,E,E,E,C,C,E,e,C,C,E,E,M,C,S,C,E,I,C,E,C,E,I,C,M,C,E,I,C,O,C,E,I,C,O,C,C,C,E,E,O,C,E,E,K,C,E,E,M,C,E,E,O,C,K,E,E,S,C,K,E,E,S,C,K,E,E,C,C,E,E,Q,C,S,C,C,C,E,C,C,E,C,C,S,C,C,C,E,E,O,C,C,E,C,E,A,E,O,c,C,E,O,C,I,W,O,C,C,E,A,C,G,C,C,E,C,E,I,I,E,E,E,E,M,C,I,E,C,C,E,E,G,E,C,I,E,E,E,A,C,U,O,S,A,a,O,O,O,O,C,E,A,Y,O,Q,O,G,E,O,W,O,C,E,C,E,C,Q,C,S,C,C,C,C,C,C,C,E,I,E,E,kD,E,iB,C,GCEwB,EAAA,MAAA,CAAA,EAAA,UAAA,IAAA,GAFxB,IAAA,EAAA,EAAA,4B,E,E,c,C,GAEe,SAAS,EAAmB,EAAS,CAAC,CAAC,EAClD,GAAM,CACF,OAAA,EAAS,CAAC,CACV,SAAA,EAAW,GAAG,CACd,WAAA,EAAa,IAAK,CAClB,gBAAA,EAAkB,GAAK,CACvB,aAAA,EAAe,IAAM,IAAI,CAC5B,CAAG,EAEJ,OAAO,AAAC,IACJ,IAAI,EAAU,CAAA,EACV,EAAW,KACX,EAAa,KACb,EAAe,KACf,EAAW,KACX,EAAe,EAAE,CACjB,EAAQ,KACR,EAAgB,CAAA,EAChB,EAAY,KACZ,EAAc,KACd,EAAoB,KAElB,EAAO,EAAI,MAAM,CAAC,GAAG,CAAC,CACxB,KAAM,MACN,KAAM,EACV,GAaA,SAAS,IACL,EAAK,KAAK,CAAC,OAAO,CAAG,MACzB,CAEA,SAAS,EAAO,CAAQ,EAChB,AAAoB,UAApB,OAAO,IACX,aAAa,GACb,EAAY,WAAW,EAAM,GAC7B,EAAK,KAAK,CAAC,OAAO,CAAG,GACrB,EAAK,SAAS,CAAG,AAlBb,AAkBgC,EAhB3B,KAAK,CAAC,uBACN,GAAG,CAAC,AAAC,GAAM,EAAE,IAAI,IACjB,MAAM,CAAC,SACP,KAAK,CAAC,CAAC,GAcX,GAAG,CAAC,AAAC,GAAS,CAAC,0BAA0B,EAAE,EAAK,MAAM,CAAC,EACvD,IAAI,CAAC,IACd,CAEA,IAAM,EAAwB;A;A;A;A;A;A;A;A;A;A;AAW9B,QAAA,CAAC,CAEK,EAAuB,KACzB,IAAM,EAAO,IAAI,KAAK,CAAC,EAAsB,CAAE,CAAE,KAAM,wBAAyB,GAChF,OAAO,IAAI,eAAe,CAAC,EAC/B,EAaA,eAAe,WACP,GAEA,AAAmB,cAAnB,AADJ,CAAA,EAAW,GAAK,CAAA,OAAO,YAAY,EAAI,OAAO,kBAAkB,AAAlB,EAAoB,CAAE,WAAA,CAAW,EAAA,EAClE,KAAK,EAAkB,MAAM,EAAS,MAAM,GAFpC,CAIzB,CAEA,eAAe,IACX,GAAI,CAAC,GAAc,EAAI,KAAK,CACxB,GAAI,CAEA,OADA,EAAa,EAAS,wBAAwB,CAAC,EAAI,KAAK,CAE5D,CAAE,MAAO,EAAK,CACV,QAAQ,IAAI,CAAC,oEAAqE,EACtF,CAGJ,GAAI,CAIA,GAHI,AAAC,GACD,CAAA,EAAc,MAAM,EAAsB,EAAI,KAAK,CAAA,EAEnD,EAEA,OADA,EAAoB,EAAS,uBAAuB,CAAC,EAG7D,CAAE,MAAO,EAAK,CACV,QAAQ,IAAI,CAAC,oDAAqD,EACtE,CAEA,OAAO,IACX,CAEA,eAAe,EAAsB,CAAY,EAC7C,GAAI,CACA,GAAI,EAAa,aAAa,CAAE,OAAO,EAAa,aAAa,GACjE,GAAI,EAAa,gBAAgB,CAAE,OAAO,EAAa,gBAAgB,GAEvE,OADA,QAAQ,IAAI,CAAC,oDACN,IACX,CAAE,MAAO,EAAK,CAEV,OADA,QAAQ,IAAI,CAAC,+CAAgD,GACtD,IACX,CACJ,CAEA,eAAe,IACX,IAAI,EAEJ,GAAI,CACA,MAAM,IACN,IAAM,EAAc,MAAM,IAC1B,GAAI,CAAC,EAAa,MAAM,AAAI,MAAM,oCAElC,GAAI,CAAC,EAAe,CAChB,IAAM,EAAU,GAChB,OAAM,EAAS,YAAY,CAAC,SAAS,CAAC,GACtC,IAAI,eAAe,CAAC,GACpB,EAAgB,CAAA,CACpB,CAGA,AADA,CAAA,EAAW,EAAS,UAAU,EAA9B,EACS,IAAI,CAAC,KAAK,CAAG,EAEtB,AADA,CAAA,EAAe,IAAI,iBAAiB,EAAU,qBAA9C,EACa,IAAI,CAAC,SAAS,CAAG,AAAC,IAC3B,EAAa,IAAI,CAAC,IAAI,aAAa,EAAM,IAAI,EACjD,EACA,EAAY,OAAO,CAAC,GACpB,EAAY,OAAO,CAAC,GACpB,EAAS,OAAO,CAAC,EAAS,WAAW,EAErC,IAAM,EAAgB,AAAc,EAAW,IAAzB,EACtB,EAAQ,YAAY,UAChB,GAAI,AAAwB,IAAxB,EAAa,MAAM,CAAQ,OAE/B,IAAI,EAAc,IAAI,aAAa,GACnC,KAAO,EAAY,MAAM,CAAG,GAAiB,EAAa,MAAM,EAAE,CAC9D,IAAM,EAAO,EAAa,KAAK,GACzB,EAAM,IAAI,aAAa,EAAY,MAAM,CAAG,EAAK,MAAM,EAC7D,EAAI,GAAG,CAAC,EAAa,GACrB,EAAI,GAAG,CAAC,EAAM,EAAY,MAAM,EAChC,EAAc,CAClB,CAEA,GAAI,EAAY,MAAM,CAAG,EAAe,OAExC,IAAM,EAAc,EAAY,KAAK,CAAC,EAAG,GACnC,EAAS,AAhG3B,SAAyB,CAAY,EACjC,IAAM,EAAM,EAAa,MAAM,CACzB,EAAS,IAAI,YAAY,AAAM,EAAN,GACzB,EAAO,IAAI,SAAS,GAC1B,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,IAAK,CAC1B,IAAI,EAAI,KAAK,GAAG,CAAC,GAAI,KAAK,GAAG,CAAC,EAAG,CAAY,CAAC,EAAE,GAChD,EAAK,QAAQ,CAAC,AAAI,EAAJ,EAAO,EAAI,EAAI,AAAI,MAAJ,EAAa,AAAI,MAAJ,EAAY,CAAA,EAC1D,CACA,OAAO,CACX,EAuF2C,GACzB,EAAW,MAAM,EAAa,GACpC,EAAO,EACX,EAAG,GAEH,EAAU,CAAA,CACd,CAAE,MAAO,EAAK,CACV,QAAQ,KAAK,CAAC,8CAA+C,GAC7D,MAAM,GACV,CACJ,CAEA,eAAe,IACN,IACL,EAAU,CAAA,EAEV,cAAc,GACd,EAAQ,KAEJ,IACA,EAAa,UAAU,GACvB,EAAa,IAAI,CAAC,SAAS,CAAG,KAC9B,EAAe,MAGf,IACA,EAAS,UAAU,GACnB,EAAW,MAGf,EAAe,EAAE,CACrB,CAEA,eAAe,IACX,MAAM,IAEF,IACA,EAAkB,UAAU,GAC5B,EAAoB,MAGpB,IACA,EAAW,UAAU,GACrB,EAAa,MAGb,IACA,EAAY,SAAS,GAAG,OAAO,CAAC,AAAC,GAAU,EAAM,IAAI,IACrD,EAAc,MAGd,IACA,MAAM,EAAS,KAAK,GACpB,EAAW,MAGf,EAAgB,CAAA,CACpB,CAMA,OAJA,EAAI,EAAE,CAAC,OAAQ,GACf,EAAI,EAAE,CAAC,QAAS,GAChB,EAAI,EAAE,CAAC,UAAW,GAEX,CACH,KAAM,qBACN,KAAM,EACN,KAAA,EACA,OAAA,CACJ,CACJ,CACJ,CAEA,GAAI,AAAoB,aAApB,OAAO,UACH,CAAC,SAAS,cAAc,CAAC,wBAAyB,CAClD,IAAM,EAAS,SAAS,aAAa,CAAC,QACtC,CAAA,EAAO,EAAE,CAAG,uBACZ,EAAO,WAAW,CAAG,EAAA,OAAK,CAC1B,SAAS,IAAI,CAAC,WAAW,CAAC,EAC9B,CAGA,AAAkB,aAAlB,OAAO,QACP,CAAA,OAAO,kBAAqB,CAAG,CADnC,C,E,C,2B,Q,iD,O,E,C,M,C,S,C,C,C,C,C,C,C,ECzPA,EAAO,OAAO,CAAG,qvB,E,C,E,C,Q,C,S,C,C,C,C,C,C,C,ECAjB,EAAQ,cAAc,CAAG,SAAU,CAAC,EAClC,OAAO,GAAK,EAAE,UAAU,CAAG,EAAI,CAAC,QAAS,CAAC,CAC5C,EAEA,EAAQ,iBAAiB,CAAG,SAAU,CAAC,EACrC,OAAO,cAAc,CAAC,EAAG,aAAc,CAAC,MAAO,CAAA,CAAI,EACrD,EAEA,EAAQ,SAAS,CAAG,SAAU,CAAM,CAAE,CAAI,EAkBxC,OAjBA,OAAO,IAAI,CAAC,GAAQ,OAAO,CAAC,SAAU,CAAG,EAE7B,YAAR,GACA,AAAQ,eAAR,GACA,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,EAAM,IAK7C,OAAO,cAAc,CAAC,EAAM,EAAK,CAC/B,WAAY,CAAA,EACZ,IAAK,WACH,OAAO,CAAM,CAAC,EAAI,AACpB,CACF,EACF,GAEO,CACT,EAEA,EAAQ,MAAM,CAAG,SAAU,CAAI,CAAE,CAAQ,CAAE,CAAG,EAC5C,OAAO,cAAc,CAAC,EAAM,EAAU,CACpC,WAAY,CAAA,EACZ,IAAK,CACP,EACF,C,E,C,E,E,C,Q,C,Q,oB,C,G,G,C,Q,C,C,C,kB,gB,K,O","sources":["","packages/artplayer-plugin-asr/src/index.js","node_modules/@parcel/runtime-js/lib/bundles/runtime-8d01a8f56d551fc8.js","node_modules/@parcel/transformer-js/src/esmodule-helpers.js"],"sourcesContent":["// modules are defined as an array\n// [ module function, map of requires ]\n//\n// map of requires is short require name -> numeric require\n//\n// anything defined in a previous bundle is accessed via the\n// orig method which is the require for previous bundles\n\n(function (\n modules,\n entry,\n mainEntry,\n parcelRequireName,\n externals,\n distDir,\n publicUrl,\n devServer\n) {\n /* eslint-disable no-undef */\n var globalObject =\n typeof globalThis !== 'undefined'\n ? globalThis\n : typeof self !== 'undefined'\n ? self\n : typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined'\n ? global\n : {};\n /* eslint-enable no-undef */\n\n // Save the require from previous bundle to this closure if any\n var previousRequire =\n typeof globalObject[parcelRequireName] === 'function' &&\n globalObject[parcelRequireName];\n\n var importMap = previousRequire.i || {};\n var cache = previousRequire.cache || {};\n // Do not use `require` to prevent Webpack from trying to bundle this call\n var nodeRequire =\n typeof module !== 'undefined' &&\n typeof module.require === 'function' &&\n module.require.bind(module);\n\n function newRequire(name, jumped) {\n if (!cache[name]) {\n if (!modules[name]) {\n if (externals[name]) {\n return externals[name];\n }\n // if we cannot find the module within our internal map or\n // cache jump to the current global require ie. the last bundle\n // that was added to the page.\n var currentRequire =\n typeof globalObject[parcelRequireName] === 'function' &&\n globalObject[parcelRequireName];\n if (!jumped && currentRequire) {\n return currentRequire(name, true);\n }\n\n // If there are other bundles on this page the require from the\n // previous one is saved to 'previousRequire'. Repeat this as\n // many times as there are bundles until the module is found or\n // we exhaust the require chain.\n if (previousRequire) {\n return previousRequire(name, true);\n }\n\n // Try the node require function if it exists.\n if (nodeRequire && typeof name === 'string') {\n return nodeRequire(name);\n }\n\n var err = new Error(\"Cannot find module '\" + name + \"'\");\n err.code = 'MODULE_NOT_FOUND';\n throw err;\n }\n\n localRequire.resolve = resolve;\n localRequire.cache = {};\n\n var module = (cache[name] = new newRequire.Module(name));\n\n modules[name][0].call(\n module.exports,\n localRequire,\n module,\n module.exports,\n globalObject\n );\n }\n\n return cache[name].exports;\n\n function localRequire(x) {\n var res = localRequire.resolve(x);\n return res === false ? {} : newRequire(res);\n }\n\n function resolve(x) {\n var id = modules[name][1][x];\n return id != null ? id : x;\n }\n }\n\n function Module(moduleName) {\n this.id = moduleName;\n this.bundle = newRequire;\n this.require = nodeRequire;\n this.exports = {};\n }\n\n newRequire.isParcelRequire = true;\n newRequire.Module = Module;\n newRequire.modules = modules;\n newRequire.cache = cache;\n newRequire.parent = previousRequire;\n newRequire.distDir = distDir;\n newRequire.publicUrl = publicUrl;\n newRequire.devServer = devServer;\n newRequire.i = importMap;\n newRequire.register = function (id, exports) {\n modules[id] = [\n function (require, module) {\n module.exports = exports;\n },\n {},\n ];\n };\n\n // Only insert newRequire.load when it is actually used.\n // The code in this file is linted against ES5, so dynamic import is not allowed.\n // INSERT_LOAD_HERE\n\n Object.defineProperty(newRequire, 'root', {\n get: function () {\n return globalObject[parcelRequireName];\n },\n });\n\n globalObject[parcelRequireName] = newRequire;\n\n for (var i = 0; i < entry.length; i++) {\n newRequire(entry[i]);\n }\n\n if (mainEntry) {\n // Expose entry point to Node, AMD or browser globals\n // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js\n var mainExports = newRequire(mainEntry);\n\n // CommonJS\n if (typeof exports === 'object' && typeof module !== 'undefined') {\n module.exports = mainExports;\n\n // RequireJS\n } else if (typeof define === 'function' && define.amd) {\n define(function () {\n return mainExports;\n });\n }\n }\n})({\"40eeC\":[function(require,module,exports,__globalThis) {\nvar parcelHelpers = require(\"@parcel/transformer-js/src/esmodule-helpers.js\");\nparcelHelpers.defineInteropFlag(exports);\nparcelHelpers.export(exports, \"default\", ()=>artplayerPluginAsr);\nvar _styleLess = require(\"bundle-text:./style.less\");\nvar _styleLessDefault = parcelHelpers.interopDefault(_styleLess);\nfunction artplayerPluginAsr(option = {}) {\n const { length = 3, interval = 100, sampleRate = 16000, autoHideTimeout = 10000, onAudioChunk = ()=>null } = option;\n return (art)=>{\n let started = false;\n let audioCtx = null;\n let sourceNode = null;\n let recorderNode = null;\n let gainNode = null;\n let bufferChunks = [];\n let timer = null;\n let workletLoaded = false;\n let hideTimer = null;\n let mediaStream = null;\n let mediaStreamSource = null;\n const $asr = art.layers.add({\n name: 'asr',\n html: ''\n });\n function splitByPunctuation(text) {\n return text// eslint-disable-next-line no-useless-escape\n .split(/(?<=[、。!?!?\\.])\\s*/u).map((s)=>s.trim()).filter(Boolean).slice(-length);\n }\n function hide() {\n $asr.style.display = 'none';\n }\n function append(subtitle) {\n if (typeof subtitle !== 'string') return;\n clearTimeout(hideTimer);\n hideTimer = setTimeout(hide, autoHideTimeout);\n $asr.style.display = '';\n $asr.innerHTML = splitByPunctuation(subtitle).map((line)=>`
${line}
`).join('');\n }\n const recorderProcessorCode = `\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n `;\n const createWorkletBlobUrl = ()=>{\n const blob = new Blob([\n recorderProcessorCode\n ], {\n type: 'application/javascript'\n });\n return URL.createObjectURL(blob);\n };\n function floatTo16BitPCM(float32Array) {\n const len = float32Array.length;\n const buffer = new ArrayBuffer(len * 2);\n const view = new DataView(buffer);\n for(let i = 0; i < len; i++){\n let s = Math.max(-1, Math.min(1, float32Array[i]));\n view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n }\n return buffer;\n }\n async function setupAudioContext() {\n if (audioCtx) return audioCtx;\n audioCtx = new (window.AudioContext || window.webkitAudioContext)({\n sampleRate\n });\n if (audioCtx.state === 'suspended') await audioCtx.resume();\n return audioCtx;\n }\n async function setupAudioSource() {\n if (!sourceNode && art.video) try {\n sourceNode = audioCtx.createMediaElementSource(art.video);\n return sourceNode;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Direct connection failed, trying fallback...', err);\n }\n try {\n if (!mediaStream) mediaStream = await captureAudioFromVideo(art.video);\n if (mediaStream) {\n mediaStreamSource = audioCtx.createMediaStreamSource(mediaStream);\n return mediaStreamSource;\n }\n } catch (err) {\n console.warn('[artplayerPluginAsr] MediaStream fallback failed:', err);\n }\n return null;\n }\n async function captureAudioFromVideo(videoElement) {\n try {\n if (videoElement.captureStream) return videoElement.captureStream();\n if (videoElement.mozCaptureStream) return videoElement.mozCaptureStream();\n console.warn('[artplayerPluginAsr] captureStream not supported');\n return null;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Error capturing stream:', err);\n return null;\n }\n }\n async function startCapture() {\n if (started) return;\n try {\n await setupAudioContext();\n const audioSource = await setupAudioSource();\n if (!audioSource) throw new Error('Could not establish audio source');\n if (!workletLoaded) {\n const blobUrl = createWorkletBlobUrl();\n await audioCtx.audioWorklet.addModule(blobUrl);\n URL.revokeObjectURL(blobUrl);\n workletLoaded = true;\n }\n gainNode = audioCtx.createGain();\n gainNode.gain.value = 1;\n recorderNode = new AudioWorkletNode(audioCtx, 'recorder-processor');\n recorderNode.port.onmessage = (event)=>{\n bufferChunks.push(new Float32Array(event.data));\n };\n audioSource.connect(recorderNode);\n audioSource.connect(gainNode);\n gainNode.connect(audioCtx.destination);\n const CHUNK_SAMPLES = sampleRate * (interval / 1000);\n timer = setInterval(async ()=>{\n if (bufferChunks.length === 0) return;\n let accumulated = new Float32Array(0);\n while(accumulated.length < CHUNK_SAMPLES && bufferChunks.length){\n const next = bufferChunks.shift();\n const tmp = new Float32Array(accumulated.length + next.length);\n tmp.set(accumulated, 0);\n tmp.set(next, accumulated.length);\n accumulated = tmp;\n }\n if (accumulated.length < CHUNK_SAMPLES) return;\n const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES);\n const buffer = floatTo16BitPCM(chunkToSend);\n const subtitle = await onAudioChunk(buffer);\n append(subtitle);\n }, interval);\n started = true;\n } catch (err) {\n console.error('[artplayerPluginAsr] Initialization failed:', err);\n await stopCapture();\n }\n }\n async function stopCapture() {\n if (!started) return;\n started = false;\n clearInterval(timer);\n timer = null;\n if (recorderNode) {\n recorderNode.disconnect();\n recorderNode.port.onmessage = null;\n recorderNode = null;\n }\n if (gainNode) {\n gainNode.disconnect();\n gainNode = null;\n }\n bufferChunks = [];\n }\n async function destroy() {\n await stopCapture();\n if (mediaStreamSource) {\n mediaStreamSource.disconnect();\n mediaStreamSource = null;\n }\n if (sourceNode) {\n sourceNode.disconnect();\n sourceNode = null;\n }\n if (mediaStream) {\n mediaStream.getTracks().forEach((track)=>track.stop());\n mediaStream = null;\n }\n if (audioCtx) {\n await audioCtx.close();\n audioCtx = null;\n }\n workletLoaded = false;\n }\n art.on('play', startCapture);\n art.on('pause', stopCapture);\n art.on('destroy', destroy);\n return {\n name: 'artplayerPluginAsr',\n stop: destroy,\n hide,\n append\n };\n };\n}\nif (typeof document !== 'undefined') {\n if (!document.getElementById('artplayer-plugin-asr')) {\n const $style = document.createElement('style');\n $style.id = 'artplayer-plugin-asr';\n $style.textContent = (0, _styleLessDefault.default);\n document.head.appendChild($style);\n }\n}\nif (typeof window !== 'undefined') window['artplayerPluginAsr'] = artplayerPluginAsr;\n\n},{\"bundle-text:./style.less\":\"dKHY3\",\"@parcel/transformer-js/src/esmodule-helpers.js\":\"5lQoW\"}],\"dKHY3\":[function(require,module,exports,__globalThis) {\nmodule.exports = \".art-video-player .art-layer-asr{z-index:150;justify-content:end;gap:var(--art-subtitle-gap);padding:0 2%;padding-bottom:var(--art-subtitle-bottom);transition:padding-bottom var(--art-transition-duration)ease;text-shadow:var(--art-subtitle-border)1px 0 1px,var(--art-subtitle-border)0 1px 1px,var(--art-subtitle-border)-1px 0 1px,var(--art-subtitle-border)0 -1px 1px,var(--art-subtitle-border)1px 1px 1px,var(--art-subtitle-border)-1px -1px 1px,var(--art-subtitle-border)1px -1px 1px,var(--art-subtitle-border)-1px 1px 1px;flex-direction:column;font-size:1rem;display:flex;position:absolute;inset:0;pointer-events:none!important}.art-video-player.art-control-show .art-layer-asr{padding-bottom:calc(var(--art-control-height) + var(--art-subtitle-bottom))}\";\n\n},{}],\"5lQoW\":[function(require,module,exports,__globalThis) {\nexports.interopDefault = function(a) {\n return a && a.__esModule ? a : {\n default: a\n };\n};\nexports.defineInteropFlag = function(a) {\n Object.defineProperty(a, '__esModule', {\n value: true\n });\n};\nexports.exportAll = function(source, dest) {\n Object.keys(source).forEach(function(key) {\n if (key === 'default' || key === '__esModule' || Object.prototype.hasOwnProperty.call(dest, key)) return;\n Object.defineProperty(dest, key, {\n enumerable: true,\n get: function() {\n return source[key];\n }\n });\n });\n return dest;\n};\nexports.export = function(dest, destName, get) {\n Object.defineProperty(dest, destName, {\n enumerable: true,\n get: get\n });\n};\n\n},{}]},[\"40eeC\"], \"40eeC\", \"parcelRequire4dc0\", {})\nlet {default: _default, } = parcelRequire4dc0(\"40eeC\");\nexport {_default as default, };\n\n//# sourceMappingURL=index.js.map\n","import style from 'bundle-text:./style.less';\n\nexport default function artplayerPluginAsr(option = {}) {\n const {\n length = 3,\n interval = 100,\n sampleRate = 16000,\n autoHideTimeout = 10000,\n onAudioChunk = () => null,\n } = option;\n\n return (art) => {\n let started = false;\n let audioCtx = null;\n let sourceNode = null;\n let recorderNode = null;\n let gainNode = null;\n let bufferChunks = [];\n let timer = null;\n let workletLoaded = false;\n let hideTimer = null;\n let mediaStream = null;\n let mediaStreamSource = null;\n\n const $asr = art.layers.add({\n name: 'asr',\n html: '',\n });\n\n function splitByPunctuation(text) {\n return (\n text\n // eslint-disable-next-line no-useless-escape\n .split(/(?<=[、。!?!?\\.])\\s*/u)\n .map((s) => s.trim())\n .filter(Boolean)\n .slice(-length)\n );\n }\n\n function hide() {\n $asr.style.display = 'none';\n }\n\n function append(subtitle) {\n if (typeof subtitle !== 'string') return;\n clearTimeout(hideTimer);\n hideTimer = setTimeout(hide, autoHideTimeout);\n $asr.style.display = '';\n $asr.innerHTML = splitByPunctuation(subtitle)\n .map((line) => `
${line}
`)\n .join('');\n }\n\n const recorderProcessorCode = `\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n `;\n\n const createWorkletBlobUrl = () => {\n const blob = new Blob([recorderProcessorCode], { type: 'application/javascript' });\n return URL.createObjectURL(blob);\n };\n\n function floatTo16BitPCM(float32Array) {\n const len = float32Array.length;\n const buffer = new ArrayBuffer(len * 2);\n const view = new DataView(buffer);\n for (let i = 0; i < len; i++) {\n let s = Math.max(-1, Math.min(1, float32Array[i]));\n view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n }\n return buffer;\n }\n\n async function setupAudioContext() {\n if (audioCtx) return audioCtx;\n audioCtx = new (window.AudioContext || window.webkitAudioContext)({ sampleRate });\n if (audioCtx.state === 'suspended') await audioCtx.resume();\n return audioCtx;\n }\n\n async function setupAudioSource() {\n if (!sourceNode && art.video) {\n try {\n sourceNode = audioCtx.createMediaElementSource(art.video);\n return sourceNode;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Direct connection failed, trying fallback...', err);\n }\n }\n\n try {\n if (!mediaStream) {\n mediaStream = await captureAudioFromVideo(art.video);\n }\n if (mediaStream) {\n mediaStreamSource = audioCtx.createMediaStreamSource(mediaStream);\n return mediaStreamSource;\n }\n } catch (err) {\n console.warn('[artplayerPluginAsr] MediaStream fallback failed:', err);\n }\n\n return null;\n }\n\n async function captureAudioFromVideo(videoElement) {\n try {\n if (videoElement.captureStream) return videoElement.captureStream();\n if (videoElement.mozCaptureStream) return videoElement.mozCaptureStream();\n console.warn('[artplayerPluginAsr] captureStream not supported');\n return null;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Error capturing stream:', err);\n return null;\n }\n }\n\n async function startCapture() {\n if (started) return;\n\n try {\n await setupAudioContext();\n const audioSource = await setupAudioSource();\n if (!audioSource) throw new Error('Could not establish audio source');\n\n if (!workletLoaded) {\n const blobUrl = createWorkletBlobUrl();\n await audioCtx.audioWorklet.addModule(blobUrl);\n URL.revokeObjectURL(blobUrl);\n workletLoaded = true;\n }\n\n gainNode = audioCtx.createGain();\n gainNode.gain.value = 1;\n recorderNode = new AudioWorkletNode(audioCtx, 'recorder-processor');\n recorderNode.port.onmessage = (event) => {\n bufferChunks.push(new Float32Array(event.data));\n };\n audioSource.connect(recorderNode);\n audioSource.connect(gainNode);\n gainNode.connect(audioCtx.destination);\n\n const CHUNK_SAMPLES = sampleRate * (interval / 1000);\n timer = setInterval(async () => {\n if (bufferChunks.length === 0) return;\n\n let accumulated = new Float32Array(0);\n while (accumulated.length < CHUNK_SAMPLES && bufferChunks.length) {\n const next = bufferChunks.shift();\n const tmp = new Float32Array(accumulated.length + next.length);\n tmp.set(accumulated, 0);\n tmp.set(next, accumulated.length);\n accumulated = tmp;\n }\n\n if (accumulated.length < CHUNK_SAMPLES) return;\n\n const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES);\n const buffer = floatTo16BitPCM(chunkToSend);\n const subtitle = await onAudioChunk(buffer);\n append(subtitle);\n }, interval);\n\n started = true;\n } catch (err) {\n console.error('[artplayerPluginAsr] Initialization failed:', err);\n await stopCapture();\n }\n }\n\n async function stopCapture() {\n if (!started) return;\n started = false;\n\n clearInterval(timer);\n timer = null;\n\n if (recorderNode) {\n recorderNode.disconnect();\n recorderNode.port.onmessage = null;\n recorderNode = null;\n }\n\n if (gainNode) {\n gainNode.disconnect();\n gainNode = null;\n }\n\n bufferChunks = [];\n }\n\n async function destroy() {\n await stopCapture();\n\n if (mediaStreamSource) {\n mediaStreamSource.disconnect();\n mediaStreamSource = null;\n }\n\n if (sourceNode) {\n sourceNode.disconnect();\n sourceNode = null;\n }\n\n if (mediaStream) {\n mediaStream.getTracks().forEach((track) => track.stop());\n mediaStream = null;\n }\n\n if (audioCtx) {\n await audioCtx.close();\n audioCtx = null;\n }\n\n workletLoaded = false;\n }\n\n art.on('play', startCapture);\n art.on('pause', stopCapture);\n art.on('destroy', destroy);\n\n return {\n name: 'artplayerPluginAsr',\n stop: destroy,\n hide,\n append,\n };\n };\n}\n\nif (typeof document !== 'undefined') {\n if (!document.getElementById('artplayer-plugin-asr')) {\n const $style = document.createElement('style');\n $style.id = 'artplayer-plugin-asr';\n $style.textContent = style;\n document.head.appendChild($style);\n }\n}\n\nif (typeof window !== 'undefined') {\n window['artplayerPluginAsr'] = artplayerPluginAsr;\n}\n","module.exports = \"704cf673cb407483\";","exports.interopDefault = function (a) {\n return a && a.__esModule ? a : {default: a};\n};\n\nexports.defineInteropFlag = function (a) {\n Object.defineProperty(a, '__esModule', {value: true});\n};\n\nexports.exportAll = function (source, dest) {\n Object.keys(source).forEach(function (key) {\n if (\n key === 'default' ||\n key === '__esModule' ||\n Object.prototype.hasOwnProperty.call(dest, key)\n ) {\n return;\n }\n\n Object.defineProperty(dest, key, {\n enumerable: true,\n get: function () {\n return source[key];\n },\n });\n });\n\n return dest;\n};\n\nexports.export = function (dest, destName, get) {\n Object.defineProperty(dest, destName, {\n enumerable: true,\n get: get,\n });\n};\n"],"names":["modules","entry","mainEntry","parcelRequireName","externals","distDir","publicUrl","devServer","globalObject","globalThis","self","window","global","previousRequire","importMap","i","cache","nodeRequire","module","require","bind","newRequire","name","jumped","currentRequire","err","Error","code","localRequire","resolve","x","id","Module","call","exports","res","isParcelRequire","moduleName","bundle","parent","register","Object","defineProperty","get","length","mainExports","define","amd","__globalThis","parcelHelpers","defineInteropFlag","export","artplayerPluginAsr","_styleLess","_styleLessDefault","interopDefault","option","interval","sampleRate","autoHideTimeout","onAudioChunk","art","started","audioCtx","sourceNode","recorderNode","gainNode","bufferChunks","timer","workletLoaded","hideTimer","mediaStream","mediaStreamSource","$asr","layers","add","html","hide","style","display","append","subtitle","clearTimeout","setTimeout","innerHTML","splitByPunctuation","text","split","map","s","trim","filter","Boolean","slice","line","join","recorderProcessorCode","createWorkletBlobUrl","blob","Blob","type","URL","createObjectURL","setupAudioContext","AudioContext","webkitAudioContext","state","resume","setupAudioSource","video","createMediaElementSource","console","warn","captureAudioFromVideo","createMediaStreamSource","videoElement","captureStream","mozCaptureStream","startCapture","audioSource","blobUrl","audioWorklet","addModule","revokeObjectURL","createGain","gain","value","AudioWorkletNode","port","onmessage","event","push","Float32Array","data","connect","destination","CHUNK_SAMPLES","setInterval","accumulated","next","shift","tmp","set","chunkToSend","buffer","floatTo16BitPCM","float32Array","len","ArrayBuffer","view","DataView","Math","max","min","setInt16","error","stopCapture","clearInterval","disconnect","destroy","getTracks","forEach","track","stop","close","on","document","getElementById","$style","createElement","textContent","default","head","appendChild","a","__esModule","exportAll","source","dest","keys","key","prototype","hasOwnProperty","enumerable","destName","_default","parcelRequire4dc0"],"version":3,"file":"index.js.map"} \ No newline at end of file diff --git a/docs/compiled/artplayer-plugin-asr.js b/docs/compiled/artplayer-plugin-asr.js index 9e570582e..8fc105dcd 100644 --- a/docs/compiled/artplayer-plugin-asr.js +++ b/docs/compiled/artplayer-plugin-asr.js @@ -5,4 +5,4 @@ * (c) 2017-2025 Harvey Zack * Released under the MIT License. */ -!function(e,t,r,n,o,a,i,l){var u="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof u[n]&&u[n],c=s.i||{},d=s.cache||{},p="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function f(t,r){if(!d[t]){if(!e[t]){if(o[t])return o[t];var a="function"==typeof u[n]&&u[n];if(!r&&a)return a(t,!0);if(s)return s(t,!0);if(p&&"string"==typeof t)return p(t);var i=Error("Cannot find module '"+t+"'");throw i.code="MODULE_NOT_FOUND",i}c.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},c.cache={};var l=d[t]=new f.Module(t);e[t][0].call(l.exports,c,l,l.exports,u)}return d[t].exports;function c(e){var t=c.resolve(e);return!1===t?{}:f(t)}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.require=p,this.exports={}},f.modules=e,f.cache=d,f.parent=s,f.distDir=void 0,f.publicUrl=void 0,f.devServer=void 0,f.i=c,f.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(f,"root",{get:function(){return u[n]}}),u[n]=f;for(var y=0;yl);var a=e("bundle-text:./style.less"),i=o.interopDefault(a);function l(e={}){let{hideTimeout:t=1e4,length:r=3,interval:n=100,sampleRate:o=16e3,onAudioChunk:a=()=>null}=e;return e=>{let i=!1,l=null,u=null,s=null,c=null,d=[],p=null,f=!1,y=null,b=null,m=null,g=e.layers.add({name:"asr",html:""});function v(){g.style.display="none"}function h(e){"string"==typeof e&&(clearTimeout(y),y=setTimeout(v,t),g.style.display="",g.innerHTML=e.split(/(?<=[、。!?!?\.])\s*/u).map(e=>e.trim()).filter(Boolean).slice(-r).map(e=>`
${e}
`).join(""))}let x=` class RecorderProcessor extends AudioWorkletProcessor { process(inputs) { const input = inputs[0]; if (input && input[0]) { this.port.postMessage(input[0]); } return true; } } registerProcessor('recorder-processor', RecorderProcessor); `,w=()=>{let e=new Blob([x],{type:"application/javascript"});return URL.createObjectURL(e)};async function M(){return l||"suspended"===(l=new(window.AudioContext||window.webkitAudioContext)({sampleRate:o})).state&&await l.resume(),l}async function P(){if(!u&&e.video)try{return u=l.createMediaElementSource(e.video)}catch(e){console.warn("[artplayerPluginAsr] Direct connection failed, trying fallback...",e)}try{if(b||(b=await j(e.video)),b)return m=l.createMediaStreamSource(b)}catch(e){console.warn("[artplayerPluginAsr] MediaStream fallback failed:",e)}return null}async function j(e){try{if(e.captureStream)return e.captureStream();if(e.mozCaptureStream)return e.mozCaptureStream();return console.warn("[artplayerPluginAsr] captureStream not supported"),null}catch(e){return console.warn("[artplayerPluginAsr] Error capturing stream:",e),null}}async function A(){if(!i)try{await M();let e=await P();if(!e)throw Error("Could not establish audio source");if(!f){let e=w();await l.audioWorklet.addModule(e),URL.revokeObjectURL(e),f=!0}(c=l.createGain()).gain.value=1,(s=new AudioWorkletNode(l,"recorder-processor")).port.onmessage=e=>{d.push(new Float32Array(e.data))},e.connect(s),e.connect(c),c.connect(l.destination);let t=n/1e3*o;p=setInterval(async()=>{if(0===d.length)return;let e=new Float32Array(0);for(;e.lengthe.stop()),b=null),l&&(await l.close(),l=null),f=!1}return e.on("play",A),e.on("pause",O),e.on("destroy",k),{name:"artplayerPluginAsr",stop:k,hide:v,append:h}}}if("undefined"!=typeof document&&!document.getElementById("artplayer-plugin-asr")){let e=document.createElement("style");e.id="artplayer-plugin-asr",e.textContent=i.default,document.head.appendChild(e)}"undefined"!=typeof window&&(window.artplayerPluginAsr=l)},{"bundle-text:./style.less":"bqyvG","@parcel/transformer-js/src/esmodule-helpers.js":"6ykb1"}],bqyvG:[function(e,t,r,n){t.exports=".art-video-player .art-layer-asr{z-index:150;justify-content:end;gap:var(--art-subtitle-gap);padding:0 2%;padding-bottom:var(--art-subtitle-bottom);transition:padding-bottom var(--art-transition-duration)ease;text-shadow:var(--art-subtitle-border)1px 0 1px,var(--art-subtitle-border)0 1px 1px,var(--art-subtitle-border)-1px 0 1px,var(--art-subtitle-border)0 -1px 1px,var(--art-subtitle-border)1px 1px 1px,var(--art-subtitle-border)-1px -1px 1px,var(--art-subtitle-border)1px -1px 1px,var(--art-subtitle-border)-1px 1px 1px;flex-direction:column;font-size:1rem;display:flex;position:absolute;inset:0;pointer-events:none!important}.art-video-player.art-control-show .art-layer-asr{padding-bottom:calc(var(--art-control-height) + var(--art-subtitle-bottom))}"},{}],"6ykb1":[function(e,t,r,n){r.interopDefault=function(e){return e&&e.__esModule?e:{default:e}},r.defineInteropFlag=function(e){Object.defineProperty(e,"__esModule",{value:!0})},r.exportAll=function(e,t){return Object.keys(e).forEach(function(r){"default"===r||"__esModule"===r||Object.prototype.hasOwnProperty.call(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:function(){return e[r]}})}),t},r.export=function(e,t,r){Object.defineProperty(e,t,{enumerable:!0,get:r})}},{}]},["1gnQM"],"1gnQM","parcelRequire4dc0",{}); \ No newline at end of file +!function(e,t,r,n,o,a,i,l){var u="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof u[n]&&u[n],c=s.i||{},d=s.cache||{},p="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function f(t,r){if(!d[t]){if(!e[t]){if(o[t])return o[t];var a="function"==typeof u[n]&&u[n];if(!r&&a)return a(t,!0);if(s)return s(t,!0);if(p&&"string"==typeof t)return p(t);var i=Error("Cannot find module '"+t+"'");throw i.code="MODULE_NOT_FOUND",i}c.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},c.cache={};var l=d[t]=new f.Module(t);e[t][0].call(l.exports,c,l,l.exports,u)}return d[t].exports;function c(e){var t=c.resolve(e);return!1===t?{}:f(t)}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.require=p,this.exports={}},f.modules=e,f.cache=d,f.parent=s,f.distDir=void 0,f.publicUrl=void 0,f.devServer=void 0,f.i=c,f.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(f,"root",{get:function(){return u[n]}}),u[n]=f;for(var y=0;yl);var a=e("bundle-text:./style.less"),i=o.interopDefault(a);function l(e={}){let{length:t=3,interval:r=100,sampleRate:n=16e3,autoHideTimeout:o=1e4,onAudioChunk:a=()=>null}=e;return e=>{let i=!1,l=null,u=null,s=null,c=null,d=[],p=null,f=!1,y=null,b=null,m=null,g=e.layers.add({name:"asr",html:""});function v(){g.style.display="none"}function h(e){"string"==typeof e&&(clearTimeout(y),y=setTimeout(v,o),g.style.display="",g.innerHTML=e.split(/(?<=[、。!?!?\.])\s*/u).map(e=>e.trim()).filter(Boolean).slice(-t).map(e=>`
${e}
`).join(""))}let x=` class RecorderProcessor extends AudioWorkletProcessor { process(inputs) { const input = inputs[0]; if (input && input[0]) { this.port.postMessage(input[0]); } return true; } } registerProcessor('recorder-processor', RecorderProcessor); `,w=()=>{let e=new Blob([x],{type:"application/javascript"});return URL.createObjectURL(e)};async function M(){return l||"suspended"===(l=new(window.AudioContext||window.webkitAudioContext)({sampleRate:n})).state&&await l.resume(),l}async function P(){if(!u&&e.video)try{return u=l.createMediaElementSource(e.video)}catch(e){console.warn("[artplayerPluginAsr] Direct connection failed, trying fallback...",e)}try{if(b||(b=await j(e.video)),b)return m=l.createMediaStreamSource(b)}catch(e){console.warn("[artplayerPluginAsr] MediaStream fallback failed:",e)}return null}async function j(e){try{if(e.captureStream)return e.captureStream();if(e.mozCaptureStream)return e.mozCaptureStream();return console.warn("[artplayerPluginAsr] captureStream not supported"),null}catch(e){return console.warn("[artplayerPluginAsr] Error capturing stream:",e),null}}async function A(){if(!i)try{await M();let e=await P();if(!e)throw Error("Could not establish audio source");if(!f){let e=w();await l.audioWorklet.addModule(e),URL.revokeObjectURL(e),f=!0}(c=l.createGain()).gain.value=1,(s=new AudioWorkletNode(l,"recorder-processor")).port.onmessage=e=>{d.push(new Float32Array(e.data))},e.connect(s),e.connect(c),c.connect(l.destination);let t=r/1e3*n;p=setInterval(async()=>{if(0===d.length)return;let e=new Float32Array(0);for(;e.lengthe.stop()),b=null),l&&(await l.close(),l=null),f=!1}return e.on("play",A),e.on("pause",O),e.on("destroy",k),{name:"artplayerPluginAsr",stop:k,hide:v,append:h}}}if("undefined"!=typeof document&&!document.getElementById("artplayer-plugin-asr")){let e=document.createElement("style");e.id="artplayer-plugin-asr",e.textContent=i.default,document.head.appendChild(e)}"undefined"!=typeof window&&(window.artplayerPluginAsr=l)},{"bundle-text:./style.less":"bqyvG","@parcel/transformer-js/src/esmodule-helpers.js":"6ykb1"}],bqyvG:[function(e,t,r,n){t.exports=".art-video-player .art-layer-asr{z-index:150;justify-content:end;gap:var(--art-subtitle-gap);padding:0 2%;padding-bottom:var(--art-subtitle-bottom);transition:padding-bottom var(--art-transition-duration)ease;text-shadow:var(--art-subtitle-border)1px 0 1px,var(--art-subtitle-border)0 1px 1px,var(--art-subtitle-border)-1px 0 1px,var(--art-subtitle-border)0 -1px 1px,var(--art-subtitle-border)1px 1px 1px,var(--art-subtitle-border)-1px -1px 1px,var(--art-subtitle-border)1px -1px 1px,var(--art-subtitle-border)-1px 1px 1px;flex-direction:column;font-size:1rem;display:flex;position:absolute;inset:0;pointer-events:none!important}.art-video-player.art-control-show .art-layer-asr{padding-bottom:calc(var(--art-control-height) + var(--art-subtitle-bottom))}"},{}],"6ykb1":[function(e,t,r,n){r.interopDefault=function(e){return e&&e.__esModule?e:{default:e}},r.defineInteropFlag=function(e){Object.defineProperty(e,"__esModule",{value:!0})},r.exportAll=function(e,t){return Object.keys(e).forEach(function(r){"default"===r||"__esModule"===r||Object.prototype.hasOwnProperty.call(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:function(){return e[r]}})}),t},r.export=function(e,t,r){Object.defineProperty(e,t,{enumerable:!0,get:r})}},{}]},["1gnQM"],"1gnQM","parcelRequire4dc0",{}); \ No newline at end of file diff --git a/docs/compiled/artplayer-plugin-asr.legacy.js b/docs/compiled/artplayer-plugin-asr.legacy.js index 5a2a575d0..7a406e290 100644 --- a/docs/compiled/artplayer-plugin-asr.legacy.js +++ b/docs/compiled/artplayer-plugin-asr.legacy.js @@ -5,4 +5,4 @@ * (c) 2017-2025 Harvey Zack * Released under the MIT License. */ -!function(e,t,r,n,o,i,a,u){var c="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof c[n]&&c[n],l=s.i||{},f=s.cache||{},p="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function d(t,r){if(!f[t]){if(!e[t]){if(o[t])return o[t];var i="function"==typeof c[n]&&c[n];if(!r&&i)return i(t,!0);if(s)return s(t,!0);if(p&&"string"==typeof t)return p(t);var a=Error("Cannot find module '"+t+"'");throw a.code="MODULE_NOT_FOUND",a}l.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},l.cache={};var u=f[t]=new d.Module(t);e[t][0].call(u.exports,l,u,u.exports,c)}return f[t].exports;function l(e){var t=l.resolve(e);return!1===t?{}:d(t)}}d.isParcelRequire=!0,d.Module=function(e){this.id=e,this.bundle=d,this.require=p,this.exports={}},d.modules=e,d.cache=f,d.parent=s,d.distDir=void 0,d.publicUrl=void 0,d.devServer=void 0,d.i=l,d.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(d,"root",{get:function(){return c[n]}}),c[n]=d;for(var y=0;y0&&void 0!==arguments[0]?arguments[0]:{},t=e.hideTimeout,r=void 0===t?1e4:t,n=e.length,o=void 0===n?3:n,u=e.interval,c=void 0===u?100:u,s=e.sampleRate,l=void 0===s?16e3:s,f=e.onAudioChunk,p=void 0===f?function(){return null}:f;return function(e){var t=!1,n=null,u=null,s=null,f=null,d=[],y=null,h=!1,_=null,v=null,b=null,m=e.layers.add({name:"asr",html:""});function w(){m.style.display="none"}function g(e){"string"==typeof e&&(clearTimeout(_),_=setTimeout(w,r),m.style.display="",m.innerHTML=e.split(RegExp("(?<=[、。!?!?\\.])\\s*","u")).map(function(e){return e.trim()}).filter(Boolean).slice(-o).map(function(e){return'
'.concat(e,"
")}).join(""))}var x=function(){var e=new Blob(["\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n "],{type:"application/javascript"});return URL.createObjectURL(e)};function j(){return(j=(0,i._)(function(){return(0,a._)(this,function(e){switch(e.label){case 0:if(n)return[2,n];if("suspended"!==(n=new(window.AudioContext||window.webkitAudioContext)({sampleRate:l})).state)return[3,2];return[4,n.resume()];case 1:e.sent(),e.label=2;case 2:return[2,n]}})})).apply(this,arguments)}function O(){return(O=(0,i._)(function(){return(0,a._)(this,function(t){switch(t.label){case 0:if(!u&&e.video)try{return u=n.createMediaElementSource(e.video),[2,u]}catch(e){console.warn("[artplayerPluginAsr] Direct connection failed, trying fallback...",e)}t.label=1;case 1:if(t.trys.push([1,4,,5]),v)return[3,3];return[4,function(e){return P.apply(this,arguments)}(e.video)];case 2:v=t.sent(),t.label=3;case 3:if(v)return[2,b=n.createMediaStreamSource(v)];return[3,5];case 4:return console.warn("[artplayerPluginAsr] MediaStream fallback failed:",t.sent()),[3,5];case 5:return[2,null]}})})).apply(this,arguments)}function P(){return(P=(0,i._)(function(e){return(0,a._)(this,function(t){try{if(e.captureStream)return[2,e.captureStream()];if(e.mozCaptureStream)return[2,e.mozCaptureStream()];return console.warn("[artplayerPluginAsr] captureStream not supported"),[2,null]}catch(e){return console.warn("[artplayerPluginAsr] Error capturing stream:",e),[2,null]}})})).apply(this,arguments)}function S(){return(S=(0,i._)(function(){var e,r,o;return(0,a._)(this,function(u){switch(u.label){case 0:if(t)return[2];u.label=1;case 1:return u.trys.push([1,6,,8]),[4,function(){return j.apply(this,arguments)}()];case 2:return u.sent(),[4,function(){return O.apply(this,arguments)}()];case 3:if(!(e=u.sent()))throw Error("Could not establish audio source");if(h)return[3,5];return r=x(),[4,n.audioWorklet.addModule(r)];case 4:u.sent(),URL.revokeObjectURL(r),h=!0,u.label=5;case 5:return(f=n.createGain()).gain.value=1,(s=new AudioWorkletNode(n,"recorder-processor")).port.onmessage=function(e){d.push(new Float32Array(e.data))},e.connect(s),e.connect(f),f.connect(n.destination),o=c/1e3*l,y=setInterval((0,i._)(function(){var e,t,r;return(0,a._)(this,function(n){switch(n.label){case 0:if(0===d.length)return[2];for(e=new Float32Array(0);e.lengtht.indexOf(n)&&(r[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,n=Object.getOwnPropertySymbols(e);ot.indexOf(n[o])&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(r[n[o]]=e[n[o]]);return r}function l(e,t,r,n){var o,a=arguments.length,u=a<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,r):n;if(("undefined"==typeof Reflect?"undefined":(0,i._)(Reflect))==="object"&&"function"==typeof Reflect.decorate)u=Reflect.decorate(e,t,r,n);else for(var c=e.length-1;c>=0;c--)(o=e[c])&&(u=(a<3?o(u):a>3?o(t,r,u):o(t,r))||u);return a>3&&u&&Object.defineProperty(t,r,u),u}function f(e,t){return function(r,n){t(r,n,e)}}function p(e,t,r,n,o,a){function u(e){if(void 0!==e&&"function"!=typeof e)throw TypeError("Function expected");return e}for(var c,s=n.kind,l="getter"===s?"get":"setter"===s?"set":"value",f=!t&&e?n.static?e:e.prototype:null,p=t||(f?Object.getOwnPropertyDescriptor(f,n.name):{}),d=!1,y=r.length-1;y>=0;y--){var h={};for(var _ in n)h[_]="access"===_?{}:n[_];for(var _ in n.access)h.access[_]=n.access[_];h.addInitializer=function(e){if(d)throw TypeError("Cannot add initializers after decoration has completed");a.push(u(e||null))};var v=(0,r[y])("accessor"===s?{get:p.get,set:p.set}:p[l],h);if("accessor"===s){if(void 0===v)continue;if(null===v||(void 0===v?"undefined":(0,i._)(v))!=="object")throw TypeError("Object expected");(c=u(v.get))&&(p.get=c),(c=u(v.set))&&(p.set=c),(c=u(v.init))&&o.unshift(c)}else(c=u(v))&&("field"===s?o.unshift(c):p[l]=c)}f&&Object.defineProperty(f,n.name,p),d=!0}function d(e,t,r){for(var n=arguments.length>2,o=0;o0&&o[o.length-1])&&(6===s[0]||2===s[0])){i=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function x(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,i=r.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(n=i.next()).done;)a.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=i.return)&&r.call(i)}finally{if(o)throw o.error}}return a}function j(){for(var e=[],t=0;t1||u(e,t)})},t&&(n[e]=t(n[e])))}function u(e,t){try{var r;(r=o[e](t)).value instanceof S?Promise.resolve(r.value.v).then(c,s):l(i[0][2],r)}catch(e){l(i[0][3],e)}}function c(e){u("next",e)}function s(e){u("throw",e)}function l(e,t){e(t),i.shift(),i.length&&u(i[0][0],i[0][1])}}function A(e){var t,r;return t={},n("next"),n("throw",function(e){throw e}),n("return"),t[Symbol.iterator]=function(){return this},t;function n(n,o){t[n]=e[n]?function(t){return(r=!r)?{value:S(e[n](t)),done:!1}:o?o(t):t}:o}}function T(e){if(!Symbol.asyncIterator)throw TypeError("Symbol.asyncIterator is not defined.");var t,r=e[Symbol.asyncIterator];return r?r.call(e):(e=g(e),t={},n("next"),n("throw"),n("return"),t[Symbol.asyncIterator]=function(){return this},t);function n(r){t[r]=e[r]&&function(t){return new Promise(function(n,o){var i,a,u;i=n,a=o,u=(t=e[r](t)).done,Promise.resolve(t.value).then(function(e){i({value:e,done:u})},a)})}}}function I(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}var R=Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t},D=function(e){return(D=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[t.length]=r);return t})(e)};function M(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r=D(e),n=0;n0&&void 0!==arguments[0]?arguments[0]:{},t=e.length,r=void 0===t?3:t,n=e.interval,o=void 0===n?100:n,u=e.sampleRate,c=void 0===u?16e3:u,s=e.autoHideTimeout,l=void 0===s?1e4:s,f=e.onAudioChunk,p=void 0===f?function(){return null}:f;return function(e){var t=!1,n=null,u=null,s=null,f=null,d=[],y=null,_=!1,h=null,v=null,b=null,m=e.layers.add({name:"asr",html:""});function w(){m.style.display="none"}function g(e){"string"==typeof e&&(clearTimeout(h),h=setTimeout(w,l),m.style.display="",m.innerHTML=e.split(RegExp("(?<=[、。!?!?\\.])\\s*","u")).map(function(e){return e.trim()}).filter(Boolean).slice(-r).map(function(e){return'
'.concat(e,"
")}).join(""))}var x=function(){var e=new Blob(["\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n "],{type:"application/javascript"});return URL.createObjectURL(e)};function j(){return(j=(0,i._)(function(){return(0,a._)(this,function(e){switch(e.label){case 0:if(n)return[2,n];if("suspended"!==(n=new(window.AudioContext||window.webkitAudioContext)({sampleRate:c})).state)return[3,2];return[4,n.resume()];case 1:e.sent(),e.label=2;case 2:return[2,n]}})})).apply(this,arguments)}function O(){return(O=(0,i._)(function(){return(0,a._)(this,function(t){switch(t.label){case 0:if(!u&&e.video)try{return u=n.createMediaElementSource(e.video),[2,u]}catch(e){console.warn("[artplayerPluginAsr] Direct connection failed, trying fallback...",e)}t.label=1;case 1:if(t.trys.push([1,4,,5]),v)return[3,3];return[4,function(e){return P.apply(this,arguments)}(e.video)];case 2:v=t.sent(),t.label=3;case 3:if(v)return[2,b=n.createMediaStreamSource(v)];return[3,5];case 4:return console.warn("[artplayerPluginAsr] MediaStream fallback failed:",t.sent()),[3,5];case 5:return[2,null]}})})).apply(this,arguments)}function P(){return(P=(0,i._)(function(e){return(0,a._)(this,function(t){try{if(e.captureStream)return[2,e.captureStream()];if(e.mozCaptureStream)return[2,e.mozCaptureStream()];return console.warn("[artplayerPluginAsr] captureStream not supported"),[2,null]}catch(e){return console.warn("[artplayerPluginAsr] Error capturing stream:",e),[2,null]}})})).apply(this,arguments)}function S(){return(S=(0,i._)(function(){var e,r,u;return(0,a._)(this,function(l){switch(l.label){case 0:if(t)return[2];l.label=1;case 1:return l.trys.push([1,6,,8]),[4,function(){return j.apply(this,arguments)}()];case 2:return l.sent(),[4,function(){return O.apply(this,arguments)}()];case 3:if(!(e=l.sent()))throw Error("Could not establish audio source");if(_)return[3,5];return r=x(),[4,n.audioWorklet.addModule(r)];case 4:l.sent(),URL.revokeObjectURL(r),_=!0,l.label=5;case 5:return(f=n.createGain()).gain.value=1,(s=new AudioWorkletNode(n,"recorder-processor")).port.onmessage=function(e){d.push(new Float32Array(e.data))},e.connect(s),e.connect(f),f.connect(n.destination),u=o/1e3*c,y=setInterval((0,i._)(function(){var e,t,r;return(0,a._)(this,function(n){switch(n.label){case 0:if(0===d.length)return[2];for(e=new Float32Array(0);e.lengtht.indexOf(n)&&(r[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,n=Object.getOwnPropertySymbols(e);ot.indexOf(n[o])&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(r[n[o]]=e[n[o]]);return r}function l(e,t,r,n){var o,a=arguments.length,u=a<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,r):n;if(("undefined"==typeof Reflect?"undefined":(0,i._)(Reflect))==="object"&&"function"==typeof Reflect.decorate)u=Reflect.decorate(e,t,r,n);else for(var c=e.length-1;c>=0;c--)(o=e[c])&&(u=(a<3?o(u):a>3?o(t,r,u):o(t,r))||u);return a>3&&u&&Object.defineProperty(t,r,u),u}function f(e,t){return function(r,n){t(r,n,e)}}function p(e,t,r,n,o,a){function u(e){if(void 0!==e&&"function"!=typeof e)throw TypeError("Function expected");return e}for(var c,s=n.kind,l="getter"===s?"get":"setter"===s?"set":"value",f=!t&&e?n.static?e:e.prototype:null,p=t||(f?Object.getOwnPropertyDescriptor(f,n.name):{}),d=!1,y=r.length-1;y>=0;y--){var _={};for(var h in n)_[h]="access"===h?{}:n[h];for(var h in n.access)_.access[h]=n.access[h];_.addInitializer=function(e){if(d)throw TypeError("Cannot add initializers after decoration has completed");a.push(u(e||null))};var v=(0,r[y])("accessor"===s?{get:p.get,set:p.set}:p[l],_);if("accessor"===s){if(void 0===v)continue;if(null===v||(void 0===v?"undefined":(0,i._)(v))!=="object")throw TypeError("Object expected");(c=u(v.get))&&(p.get=c),(c=u(v.set))&&(p.set=c),(c=u(v.init))&&o.unshift(c)}else(c=u(v))&&("field"===s?o.unshift(c):p[l]=c)}f&&Object.defineProperty(f,n.name,p),d=!0}function d(e,t,r){for(var n=arguments.length>2,o=0;o0&&o[o.length-1])&&(6===s[0]||2===s[0])){i=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function x(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,i=r.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(n=i.next()).done;)a.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=i.return)&&r.call(i)}finally{if(o)throw o.error}}return a}function j(){for(var e=[],t=0;t1||u(e,t)})},t&&(n[e]=t(n[e])))}function u(e,t){try{var r;(r=o[e](t)).value instanceof S?Promise.resolve(r.value.v).then(c,s):l(i[0][2],r)}catch(e){l(i[0][3],e)}}function c(e){u("next",e)}function s(e){u("throw",e)}function l(e,t){e(t),i.shift(),i.length&&u(i[0][0],i[0][1])}}function A(e){var t,r;return t={},n("next"),n("throw",function(e){throw e}),n("return"),t[Symbol.iterator]=function(){return this},t;function n(n,o){t[n]=e[n]?function(t){return(r=!r)?{value:S(e[n](t)),done:!1}:o?o(t):t}:o}}function T(e){if(!Symbol.asyncIterator)throw TypeError("Symbol.asyncIterator is not defined.");var t,r=e[Symbol.asyncIterator];return r?r.call(e):(e=g(e),t={},n("next"),n("throw"),n("return"),t[Symbol.asyncIterator]=function(){return this},t);function n(r){t[r]=e[r]&&function(t){return new Promise(function(n,o){var i,a,u;i=n,a=o,u=(t=e[r](t)).done,Promise.resolve(t.value).then(function(e){i({value:e,done:u})},a)})}}}function I(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}var R=Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t},D=function(e){return(D=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[t.length]=r);return t})(e)};function M(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r=D(e),n=0;nartplayerPluginAsr); var _styleLess = require("bundle-text:./style.less"); var _styleLessDefault = parcelHelpers.interopDefault(_styleLess); function artplayerPluginAsr(option = {}) { - const { hideTimeout = 10000, length = 3, interval = 100, sampleRate = 16000, onAudioChunk = ()=>null } = option; + const { length = 3, interval = 100, sampleRate = 16000, autoHideTimeout = 10000, onAudioChunk = ()=>null } = option; return (art)=>{ let started = false; let audioCtx = null; @@ -194,7 +194,7 @@ function artplayerPluginAsr(option = {}) { function append(subtitle) { if (typeof subtitle !== 'string') return; clearTimeout(hideTimer); - hideTimer = setTimeout(hide, hideTimeout); + hideTimer = setTimeout(hide, autoHideTimeout); $asr.style.display = ''; $asr.innerHTML = splitByPunctuation(subtitle).map((line)=>`
${line}
`).join(''); } @@ -277,18 +277,15 @@ function artplayerPluginAsr(option = {}) { URL.revokeObjectURL(blobUrl); workletLoaded = true; } - // 创建输出音频的 GainNode(正常播放) gainNode = audioCtx.createGain(); gainNode.gain.value = 1; recorderNode = new AudioWorkletNode(audioCtx, 'recorder-processor'); recorderNode.port.onmessage = (event)=>{ bufferChunks.push(new Float32Array(event.data)); }; - // 分流:识别和播放 audioSource.connect(recorderNode); audioSource.connect(gainNode); - gainNode.connect(audioCtx.destination); // 正常声音输出 - // recorderNode 不连接 destination,避免输出干扰 + gainNode.connect(audioCtx.destination); const CHUNK_SAMPLES = sampleRate * (interval / 1000); timer = setInterval(async ()=>{ if (bufferChunks.length === 0) return; @@ -302,8 +299,8 @@ function artplayerPluginAsr(option = {}) { } if (accumulated.length < CHUNK_SAMPLES) return; const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES); - const pcm = floatTo16BitPCM(chunkToSend); - const subtitle = await onAudioChunk(pcm); + const buffer = floatTo16BitPCM(chunkToSend); + const subtitle = await onAudioChunk(buffer); append(subtitle); }, interval); started = true; diff --git a/docs/uncompiled/artplayer-plugin-asr/index.js.map b/docs/uncompiled/artplayer-plugin-asr/index.js.map index 161d17fd0..e9be9b6d5 100644 --- a/docs/uncompiled/artplayer-plugin-asr/index.js.map +++ b/docs/uncompiled/artplayer-plugin-asr/index.js.map @@ -1 +1 @@ -{"mappings":"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","sources":["packages/artplayer-plugin-asr/src/index.js","node_modules/@parcel/runtime-js/lib/bundles/runtime-54f3e2ccbee34ab4.js","node_modules/@parcel/transformer-js/src/esmodule-helpers.js"],"sourcesContent":["import style from 'bundle-text:./style.less';\n\nexport default function artplayerPluginAsr(option = {}) {\n const { hideTimeout = 10000, length = 3, interval = 100, sampleRate = 16000, onAudioChunk = () => null } = option;\n\n return (art) => {\n let started = false;\n let audioCtx = null;\n let sourceNode = null;\n let recorderNode = null;\n let gainNode = null;\n let bufferChunks = [];\n let timer = null;\n let workletLoaded = false;\n let hideTimer = null;\n let mediaStream = null;\n let mediaStreamSource = null;\n\n const $asr = art.layers.add({\n name: 'asr',\n html: '',\n });\n\n function splitByPunctuation(text) {\n return (\n text\n // eslint-disable-next-line no-useless-escape\n .split(/(?<=[、。!?!?\\.])\\s*/u)\n .map((s) => s.trim())\n .filter(Boolean)\n .slice(-length)\n );\n }\n\n function hide() {\n $asr.style.display = 'none';\n }\n\n function append(subtitle) {\n if (typeof subtitle !== 'string') return;\n clearTimeout(hideTimer);\n hideTimer = setTimeout(hide, hideTimeout);\n $asr.style.display = '';\n $asr.innerHTML = splitByPunctuation(subtitle)\n .map((line) => `
${line}
`)\n .join('');\n }\n\n const recorderProcessorCode = `\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n `;\n\n const createWorkletBlobUrl = () => {\n const blob = new Blob([recorderProcessorCode], { type: 'application/javascript' });\n return URL.createObjectURL(blob);\n };\n\n function floatTo16BitPCM(float32Array) {\n const len = float32Array.length;\n const buffer = new ArrayBuffer(len * 2);\n const view = new DataView(buffer);\n for (let i = 0; i < len; i++) {\n let s = Math.max(-1, Math.min(1, float32Array[i]));\n view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n }\n return buffer;\n }\n\n async function setupAudioContext() {\n if (audioCtx) return audioCtx;\n audioCtx = new (window.AudioContext || window.webkitAudioContext)({ sampleRate });\n if (audioCtx.state === 'suspended') await audioCtx.resume();\n return audioCtx;\n }\n\n async function setupAudioSource() {\n if (!sourceNode && art.video) {\n try {\n sourceNode = audioCtx.createMediaElementSource(art.video);\n return sourceNode;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Direct connection failed, trying fallback...', err);\n }\n }\n\n try {\n if (!mediaStream) {\n mediaStream = await captureAudioFromVideo(art.video);\n }\n if (mediaStream) {\n mediaStreamSource = audioCtx.createMediaStreamSource(mediaStream);\n return mediaStreamSource;\n }\n } catch (err) {\n console.warn('[artplayerPluginAsr] MediaStream fallback failed:', err);\n }\n\n return null;\n }\n\n async function captureAudioFromVideo(videoElement) {\n try {\n if (videoElement.captureStream) return videoElement.captureStream();\n if (videoElement.mozCaptureStream) return videoElement.mozCaptureStream();\n console.warn('[artplayerPluginAsr] captureStream not supported');\n return null;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Error capturing stream:', err);\n return null;\n }\n }\n\n async function startCapture() {\n if (started) return;\n\n try {\n await setupAudioContext();\n const audioSource = await setupAudioSource();\n if (!audioSource) throw new Error('Could not establish audio source');\n\n if (!workletLoaded) {\n const blobUrl = createWorkletBlobUrl();\n await audioCtx.audioWorklet.addModule(blobUrl);\n URL.revokeObjectURL(blobUrl);\n workletLoaded = true;\n }\n\n // 创建输出音频的 GainNode(正常播放)\n gainNode = audioCtx.createGain();\n gainNode.gain.value = 1;\n\n recorderNode = new AudioWorkletNode(audioCtx, 'recorder-processor');\n recorderNode.port.onmessage = (event) => {\n bufferChunks.push(new Float32Array(event.data));\n };\n\n // 分流:识别和播放\n audioSource.connect(recorderNode);\n audioSource.connect(gainNode);\n\n gainNode.connect(audioCtx.destination); // 正常声音输出\n // recorderNode 不连接 destination,避免输出干扰\n\n const CHUNK_SAMPLES = sampleRate * (interval / 1000);\n timer = setInterval(async () => {\n if (bufferChunks.length === 0) return;\n\n let accumulated = new Float32Array(0);\n while (accumulated.length < CHUNK_SAMPLES && bufferChunks.length) {\n const next = bufferChunks.shift();\n const tmp = new Float32Array(accumulated.length + next.length);\n tmp.set(accumulated, 0);\n tmp.set(next, accumulated.length);\n accumulated = tmp;\n }\n\n if (accumulated.length < CHUNK_SAMPLES) return;\n\n const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES);\n const pcm = floatTo16BitPCM(chunkToSend);\n const subtitle = await onAudioChunk(pcm);\n append(subtitle);\n }, interval);\n\n started = true;\n } catch (err) {\n console.error('[artplayerPluginAsr] Initialization failed:', err);\n await stopCapture();\n }\n }\n\n async function stopCapture() {\n if (!started) return;\n started = false;\n\n clearInterval(timer);\n timer = null;\n\n if (recorderNode) {\n recorderNode.disconnect();\n recorderNode.port.onmessage = null;\n recorderNode = null;\n }\n\n if (gainNode) {\n gainNode.disconnect();\n gainNode = null;\n }\n\n bufferChunks = [];\n }\n\n async function destroy() {\n await stopCapture();\n\n if (mediaStreamSource) {\n mediaStreamSource.disconnect();\n mediaStreamSource = null;\n }\n\n if (sourceNode) {\n sourceNode.disconnect();\n sourceNode = null;\n }\n\n if (mediaStream) {\n mediaStream.getTracks().forEach((track) => track.stop());\n mediaStream = null;\n }\n\n if (audioCtx) {\n await audioCtx.close();\n audioCtx = null;\n }\n\n workletLoaded = false;\n }\n\n art.on('play', startCapture);\n art.on('pause', stopCapture);\n art.on('destroy', destroy);\n\n return {\n name: 'artplayerPluginAsr',\n stop: destroy,\n hide,\n append,\n };\n };\n}\n\nif (typeof document !== 'undefined') {\n if (!document.getElementById('artplayer-plugin-asr')) {\n const $style = document.createElement('style');\n $style.id = 'artplayer-plugin-asr';\n $style.textContent = style;\n document.head.appendChild($style);\n }\n}\n\nif (typeof window !== 'undefined') {\n window['artplayerPluginAsr'] = artplayerPluginAsr;\n}\n","module.exports = \"c5e0457df51aebc9\";","exports.interopDefault = function (a) {\n return a && a.__esModule ? a : {default: a};\n};\n\nexports.defineInteropFlag = function (a) {\n Object.defineProperty(a, '__esModule', {value: true});\n};\n\nexports.exportAll = function (source, dest) {\n Object.keys(source).forEach(function (key) {\n if (\n key === 'default' ||\n key === '__esModule' ||\n Object.prototype.hasOwnProperty.call(dest, key)\n ) {\n return;\n }\n\n Object.defineProperty(dest, key, {\n enumerable: true,\n get: function () {\n return source[key];\n },\n });\n });\n\n return dest;\n};\n\nexports.export = function (dest, destName, get) {\n Object.defineProperty(dest, destName, {\n enumerable: true,\n get: get,\n });\n};\n"],"names":[],"version":3,"file":"index.js.map","sourceRoot":"../../../"} \ No newline at end of file +{"mappings":"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","sources":["packages/artplayer-plugin-asr/src/index.js","node_modules/@parcel/runtime-js/lib/bundles/runtime-54f3e2ccbee34ab4.js","node_modules/@parcel/transformer-js/src/esmodule-helpers.js"],"sourcesContent":["import style from 'bundle-text:./style.less';\n\nexport default function artplayerPluginAsr(option = {}) {\n const {\n length = 3,\n interval = 100,\n sampleRate = 16000,\n autoHideTimeout = 10000,\n onAudioChunk = () => null,\n } = option;\n\n return (art) => {\n let started = false;\n let audioCtx = null;\n let sourceNode = null;\n let recorderNode = null;\n let gainNode = null;\n let bufferChunks = [];\n let timer = null;\n let workletLoaded = false;\n let hideTimer = null;\n let mediaStream = null;\n let mediaStreamSource = null;\n\n const $asr = art.layers.add({\n name: 'asr',\n html: '',\n });\n\n function splitByPunctuation(text) {\n return (\n text\n // eslint-disable-next-line no-useless-escape\n .split(/(?<=[、。!?!?\\.])\\s*/u)\n .map((s) => s.trim())\n .filter(Boolean)\n .slice(-length)\n );\n }\n\n function hide() {\n $asr.style.display = 'none';\n }\n\n function append(subtitle) {\n if (typeof subtitle !== 'string') return;\n clearTimeout(hideTimer);\n hideTimer = setTimeout(hide, autoHideTimeout);\n $asr.style.display = '';\n $asr.innerHTML = splitByPunctuation(subtitle)\n .map((line) => `
${line}
`)\n .join('');\n }\n\n const recorderProcessorCode = `\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n `;\n\n const createWorkletBlobUrl = () => {\n const blob = new Blob([recorderProcessorCode], { type: 'application/javascript' });\n return URL.createObjectURL(blob);\n };\n\n function floatTo16BitPCM(float32Array) {\n const len = float32Array.length;\n const buffer = new ArrayBuffer(len * 2);\n const view = new DataView(buffer);\n for (let i = 0; i < len; i++) {\n let s = Math.max(-1, Math.min(1, float32Array[i]));\n view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n }\n return buffer;\n }\n\n async function setupAudioContext() {\n if (audioCtx) return audioCtx;\n audioCtx = new (window.AudioContext || window.webkitAudioContext)({ sampleRate });\n if (audioCtx.state === 'suspended') await audioCtx.resume();\n return audioCtx;\n }\n\n async function setupAudioSource() {\n if (!sourceNode && art.video) {\n try {\n sourceNode = audioCtx.createMediaElementSource(art.video);\n return sourceNode;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Direct connection failed, trying fallback...', err);\n }\n }\n\n try {\n if (!mediaStream) {\n mediaStream = await captureAudioFromVideo(art.video);\n }\n if (mediaStream) {\n mediaStreamSource = audioCtx.createMediaStreamSource(mediaStream);\n return mediaStreamSource;\n }\n } catch (err) {\n console.warn('[artplayerPluginAsr] MediaStream fallback failed:', err);\n }\n\n return null;\n }\n\n async function captureAudioFromVideo(videoElement) {\n try {\n if (videoElement.captureStream) return videoElement.captureStream();\n if (videoElement.mozCaptureStream) return videoElement.mozCaptureStream();\n console.warn('[artplayerPluginAsr] captureStream not supported');\n return null;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Error capturing stream:', err);\n return null;\n }\n }\n\n async function startCapture() {\n if (started) return;\n\n try {\n await setupAudioContext();\n const audioSource = await setupAudioSource();\n if (!audioSource) throw new Error('Could not establish audio source');\n\n if (!workletLoaded) {\n const blobUrl = createWorkletBlobUrl();\n await audioCtx.audioWorklet.addModule(blobUrl);\n URL.revokeObjectURL(blobUrl);\n workletLoaded = true;\n }\n\n gainNode = audioCtx.createGain();\n gainNode.gain.value = 1;\n recorderNode = new AudioWorkletNode(audioCtx, 'recorder-processor');\n recorderNode.port.onmessage = (event) => {\n bufferChunks.push(new Float32Array(event.data));\n };\n audioSource.connect(recorderNode);\n audioSource.connect(gainNode);\n gainNode.connect(audioCtx.destination);\n\n const CHUNK_SAMPLES = sampleRate * (interval / 1000);\n timer = setInterval(async () => {\n if (bufferChunks.length === 0) return;\n\n let accumulated = new Float32Array(0);\n while (accumulated.length < CHUNK_SAMPLES && bufferChunks.length) {\n const next = bufferChunks.shift();\n const tmp = new Float32Array(accumulated.length + next.length);\n tmp.set(accumulated, 0);\n tmp.set(next, accumulated.length);\n accumulated = tmp;\n }\n\n if (accumulated.length < CHUNK_SAMPLES) return;\n\n const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES);\n const buffer = floatTo16BitPCM(chunkToSend);\n const subtitle = await onAudioChunk(buffer);\n append(subtitle);\n }, interval);\n\n started = true;\n } catch (err) {\n console.error('[artplayerPluginAsr] Initialization failed:', err);\n await stopCapture();\n }\n }\n\n async function stopCapture() {\n if (!started) return;\n started = false;\n\n clearInterval(timer);\n timer = null;\n\n if (recorderNode) {\n recorderNode.disconnect();\n recorderNode.port.onmessage = null;\n recorderNode = null;\n }\n\n if (gainNode) {\n gainNode.disconnect();\n gainNode = null;\n }\n\n bufferChunks = [];\n }\n\n async function destroy() {\n await stopCapture();\n\n if (mediaStreamSource) {\n mediaStreamSource.disconnect();\n mediaStreamSource = null;\n }\n\n if (sourceNode) {\n sourceNode.disconnect();\n sourceNode = null;\n }\n\n if (mediaStream) {\n mediaStream.getTracks().forEach((track) => track.stop());\n mediaStream = null;\n }\n\n if (audioCtx) {\n await audioCtx.close();\n audioCtx = null;\n }\n\n workletLoaded = false;\n }\n\n art.on('play', startCapture);\n art.on('pause', stopCapture);\n art.on('destroy', destroy);\n\n return {\n name: 'artplayerPluginAsr',\n stop: destroy,\n hide,\n append,\n };\n };\n}\n\nif (typeof document !== 'undefined') {\n if (!document.getElementById('artplayer-plugin-asr')) {\n const $style = document.createElement('style');\n $style.id = 'artplayer-plugin-asr';\n $style.textContent = style;\n document.head.appendChild($style);\n }\n}\n\nif (typeof window !== 'undefined') {\n window['artplayerPluginAsr'] = artplayerPluginAsr;\n}\n","module.exports = \"c5e0457df51aebc9\";","exports.interopDefault = function (a) {\n return a && a.__esModule ? a : {default: a};\n};\n\nexports.defineInteropFlag = function (a) {\n Object.defineProperty(a, '__esModule', {value: true});\n};\n\nexports.exportAll = function (source, dest) {\n Object.keys(source).forEach(function (key) {\n if (\n key === 'default' ||\n key === '__esModule' ||\n Object.prototype.hasOwnProperty.call(dest, key)\n ) {\n return;\n }\n\n Object.defineProperty(dest, key, {\n enumerable: true,\n get: function () {\n return source[key];\n },\n });\n });\n\n return dest;\n};\n\nexports.export = function (dest, destName, get) {\n Object.defineProperty(dest, destName, {\n enumerable: true,\n get: get,\n });\n};\n"],"names":[],"version":3,"file":"index.js.map","sourceRoot":"../../../"} \ No newline at end of file diff --git a/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.esm.js b/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.esm.js index 7224d7ef9..84d9e864f 100644 --- a/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.esm.js +++ b/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.esm.js @@ -5,5 +5,5 @@ * (c) 2017-2025 Harvey Zack * Released under the MIT License. */ -!function(e,t,r,n,o,a,l,i){var u="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof u[n]&&u[n],c=s.i||{},d=s.cache||{},p="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function f(t,r){if(!d[t]){if(!e[t]){if(o[t])return o[t];var a="function"==typeof u[n]&&u[n];if(!r&&a)return a(t,!0);if(s)return s(t,!0);if(p&&"string"==typeof t)return p(t);var l=Error("Cannot find module '"+t+"'");throw l.code="MODULE_NOT_FOUND",l}c.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},c.cache={};var i=d[t]=new f.Module(t);e[t][0].call(i.exports,c,i,i.exports,u)}return d[t].exports;function c(e){var t=c.resolve(e);return!1===t?{}:f(t)}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.require=p,this.exports={}},f.modules=e,f.cache=d,f.parent=s,f.distDir=void 0,f.publicUrl=void 0,f.devServer=void 0,f.i=c,f.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(f,"root",{get:function(){return u[n]}}),u[n]=f;for(var y=0;yi);var a=e("bundle-text:./style.less"),l=o.interopDefault(a);function i(e={}){let{hideTimeout:t=1e4,length:r=3,interval:n=100,sampleRate:o=16e3,onAudioChunk:a=()=>null}=e;return e=>{let l=!1,i=null,u=null,s=null,c=null,d=[],p=null,f=!1,y=null,m=null,b=null,g=e.layers.add({name:"asr",html:""});function v(){g.style.display="none"}function x(e){"string"==typeof e&&(clearTimeout(y),y=setTimeout(v,t),g.style.display="",g.innerHTML=e.split(/(?<=[、。!?!?\.])\s*/u).map(e=>e.trim()).filter(Boolean).slice(-r).map(e=>`
${e}
`).join(""))}let h=` class RecorderProcessor extends AudioWorkletProcessor { process(inputs) { const input = inputs[0]; if (input && input[0]) { this.port.postMessage(input[0]); } return true; } } registerProcessor('recorder-processor', RecorderProcessor); `,w=()=>{let e=new Blob([h],{type:"application/javascript"});return URL.createObjectURL(e)};async function P(){return i||"suspended"===(i=new(window.AudioContext||window.webkitAudioContext)({sampleRate:o})).state&&await i.resume(),i}async function j(){if(!u&&e.video)try{return u=i.createMediaElementSource(e.video)}catch(e){console.warn("[artplayerPluginAsr] Direct connection failed, trying fallback...",e)}try{if(m||(m=await A(e.video)),m)return b=i.createMediaStreamSource(m)}catch(e){console.warn("[artplayerPluginAsr] MediaStream fallback failed:",e)}return null}async function A(e){try{if(e.captureStream)return e.captureStream();if(e.mozCaptureStream)return e.mozCaptureStream();return console.warn("[artplayerPluginAsr] captureStream not supported"),null}catch(e){return console.warn("[artplayerPluginAsr] Error capturing stream:",e),null}}async function M(){if(!l)try{await P();let e=await j();if(!e)throw Error("Could not establish audio source");if(!f){let e=w();await i.audioWorklet.addModule(e),URL.revokeObjectURL(e),f=!0}(c=i.createGain()).gain.value=1,(s=new AudioWorkletNode(i,"recorder-processor")).port.onmessage=e=>{d.push(new Float32Array(e.data))},e.connect(s),e.connect(c),c.connect(i.destination);let t=n/1e3*o;p=setInterval(async()=>{if(0===d.length)return;let e=new Float32Array(0);for(;e.lengthe.stop()),m=null),i&&(await i.close(),i=null),f=!1}return e.on("play",M),e.on("pause",C),e.on("destroy",O),{name:"artplayerPluginAsr",stop:O,hide:v,append:x}}}if("undefined"!=typeof document&&!document.getElementById("artplayer-plugin-asr")){let e=document.createElement("style");e.id="artplayer-plugin-asr",e.textContent=l.default,document.head.appendChild(e)}"undefined"!=typeof window&&(window.artplayerPluginAsr=i)},{"bundle-text:./style.less":"dKHY3","@parcel/transformer-js/src/esmodule-helpers.js":"5lQoW"}],dKHY3:[function(e,t,r,n){t.exports=".art-video-player .art-layer-asr{z-index:150;justify-content:end;gap:var(--art-subtitle-gap);padding:0 2%;padding-bottom:var(--art-subtitle-bottom);transition:padding-bottom var(--art-transition-duration)ease;text-shadow:var(--art-subtitle-border)1px 0 1px,var(--art-subtitle-border)0 1px 1px,var(--art-subtitle-border)-1px 0 1px,var(--art-subtitle-border)0 -1px 1px,var(--art-subtitle-border)1px 1px 1px,var(--art-subtitle-border)-1px -1px 1px,var(--art-subtitle-border)1px -1px 1px,var(--art-subtitle-border)-1px 1px 1px;flex-direction:column;font-size:1rem;display:flex;position:absolute;inset:0;pointer-events:none!important}.art-video-player.art-control-show .art-layer-asr{padding-bottom:calc(var(--art-control-height) + var(--art-subtitle-bottom))}"},{}],"5lQoW":[function(e,t,r,n){r.interopDefault=function(e){return e&&e.__esModule?e:{default:e}},r.defineInteropFlag=function(e){Object.defineProperty(e,"__esModule",{value:!0})},r.exportAll=function(e,t){return Object.keys(e).forEach(function(r){"default"===r||"__esModule"===r||Object.prototype.hasOwnProperty.call(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:function(){return e[r]}})}),t},r.export=function(e,t,r){Object.defineProperty(e,t,{enumerable:!0,get:r})}},{}]},["40eeC"],"40eeC","parcelRequire4dc0",{});let{default:e}=parcelRequire4dc0("40eeC");export{e as default}; +!function(e,t,r,n,o,a,l,i){var u="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof u[n]&&u[n],c=s.i||{},d=s.cache||{},p="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function f(t,r){if(!d[t]){if(!e[t]){if(o[t])return o[t];var a="function"==typeof u[n]&&u[n];if(!r&&a)return a(t,!0);if(s)return s(t,!0);if(p&&"string"==typeof t)return p(t);var l=Error("Cannot find module '"+t+"'");throw l.code="MODULE_NOT_FOUND",l}c.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},c.cache={};var i=d[t]=new f.Module(t);e[t][0].call(i.exports,c,i,i.exports,u)}return d[t].exports;function c(e){var t=c.resolve(e);return!1===t?{}:f(t)}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.require=p,this.exports={}},f.modules=e,f.cache=d,f.parent=s,f.distDir=void 0,f.publicUrl=void 0,f.devServer=void 0,f.i=c,f.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(f,"root",{get:function(){return u[n]}}),u[n]=f;for(var y=0;yi);var a=e("bundle-text:./style.less"),l=o.interopDefault(a);function i(e={}){let{length:t=3,interval:r=100,sampleRate:n=16e3,autoHideTimeout:o=1e4,onAudioChunk:a=()=>null}=e;return e=>{let l=!1,i=null,u=null,s=null,c=null,d=[],p=null,f=!1,y=null,m=null,b=null,g=e.layers.add({name:"asr",html:""});function v(){g.style.display="none"}function x(e){"string"==typeof e&&(clearTimeout(y),y=setTimeout(v,o),g.style.display="",g.innerHTML=e.split(/(?<=[、。!?!?\.])\s*/u).map(e=>e.trim()).filter(Boolean).slice(-t).map(e=>`
${e}
`).join(""))}let h=` class RecorderProcessor extends AudioWorkletProcessor { process(inputs) { const input = inputs[0]; if (input && input[0]) { this.port.postMessage(input[0]); } return true; } } registerProcessor('recorder-processor', RecorderProcessor); `,w=()=>{let e=new Blob([h],{type:"application/javascript"});return URL.createObjectURL(e)};async function P(){return i||"suspended"===(i=new(window.AudioContext||window.webkitAudioContext)({sampleRate:n})).state&&await i.resume(),i}async function j(){if(!u&&e.video)try{return u=i.createMediaElementSource(e.video)}catch(e){console.warn("[artplayerPluginAsr] Direct connection failed, trying fallback...",e)}try{if(m||(m=await A(e.video)),m)return b=i.createMediaStreamSource(m)}catch(e){console.warn("[artplayerPluginAsr] MediaStream fallback failed:",e)}return null}async function A(e){try{if(e.captureStream)return e.captureStream();if(e.mozCaptureStream)return e.mozCaptureStream();return console.warn("[artplayerPluginAsr] captureStream not supported"),null}catch(e){return console.warn("[artplayerPluginAsr] Error capturing stream:",e),null}}async function M(){if(!l)try{await P();let e=await j();if(!e)throw Error("Could not establish audio source");if(!f){let e=w();await i.audioWorklet.addModule(e),URL.revokeObjectURL(e),f=!0}(c=i.createGain()).gain.value=1,(s=new AudioWorkletNode(i,"recorder-processor")).port.onmessage=e=>{d.push(new Float32Array(e.data))},e.connect(s),e.connect(c),c.connect(i.destination);let t=r/1e3*n;p=setInterval(async()=>{if(0===d.length)return;let e=new Float32Array(0);for(;e.lengthe.stop()),m=null),i&&(await i.close(),i=null),f=!1}return e.on("play",M),e.on("pause",C),e.on("destroy",O),{name:"artplayerPluginAsr",stop:O,hide:v,append:x}}}if("undefined"!=typeof document&&!document.getElementById("artplayer-plugin-asr")){let e=document.createElement("style");e.id="artplayer-plugin-asr",e.textContent=l.default,document.head.appendChild(e)}"undefined"!=typeof window&&(window.artplayerPluginAsr=i)},{"bundle-text:./style.less":"dKHY3","@parcel/transformer-js/src/esmodule-helpers.js":"5lQoW"}],dKHY3:[function(e,t,r,n){t.exports=".art-video-player .art-layer-asr{z-index:150;justify-content:end;gap:var(--art-subtitle-gap);padding:0 2%;padding-bottom:var(--art-subtitle-bottom);transition:padding-bottom var(--art-transition-duration)ease;text-shadow:var(--art-subtitle-border)1px 0 1px,var(--art-subtitle-border)0 1px 1px,var(--art-subtitle-border)-1px 0 1px,var(--art-subtitle-border)0 -1px 1px,var(--art-subtitle-border)1px 1px 1px,var(--art-subtitle-border)-1px -1px 1px,var(--art-subtitle-border)1px -1px 1px,var(--art-subtitle-border)-1px 1px 1px;flex-direction:column;font-size:1rem;display:flex;position:absolute;inset:0;pointer-events:none!important}.art-video-player.art-control-show .art-layer-asr{padding-bottom:calc(var(--art-control-height) + var(--art-subtitle-bottom))}"},{}],"5lQoW":[function(e,t,r,n){r.interopDefault=function(e){return e&&e.__esModule?e:{default:e}},r.defineInteropFlag=function(e){Object.defineProperty(e,"__esModule",{value:!0})},r.exportAll=function(e,t){return Object.keys(e).forEach(function(r){"default"===r||"__esModule"===r||Object.prototype.hasOwnProperty.call(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:function(){return e[r]}})}),t},r.export=function(e,t,r){Object.defineProperty(e,t,{enumerable:!0,get:r})}},{}]},["40eeC"],"40eeC","parcelRequire4dc0",{});let{default:e}=parcelRequire4dc0("40eeC");export{e as default}; //# sourceMappingURL=artplayer-plugin-asr.esm.js.map \ No newline at end of file diff --git a/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.esm.js.map b/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.esm.js.map index 92fe74b29..270af49da 100644 --- a/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.esm.js.map +++ b/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.esm.js.map @@ -1 +1 @@ -{"mappings":"C,A,S,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,E,I,E,A,a,O,W,W,A,a,O,K,K,A,a,O,O,O,A,a,O,O,O,C,E,E,A,Y,O,C,C,E,E,C,C,E,C,E,E,C,E,C,E,E,E,K,E,C,E,E,A,a,O,Q,A,Y,O,O,O,E,O,O,C,I,C,Q,S,E,C,C,C,E,G,C,C,C,E,C,C,G,C,C,C,E,C,C,G,C,C,E,C,O,C,C,E,C,I,E,A,Y,O,C,C,E,E,C,C,E,C,G,C,G,E,O,E,E,C,G,G,E,O,E,E,C,G,G,G,A,U,O,E,O,E,G,I,E,A,M,uB,E,I,O,E,I,C,mB,C,C,E,O,C,S,C,E,I,E,C,C,E,C,E,C,E,C,O,A,M,E,E,C,E,E,K,C,C,E,I,E,C,C,E,C,I,E,M,C,G,C,C,E,C,E,C,I,C,E,O,C,E,E,E,O,C,E,C,O,C,C,E,C,O,C,S,E,C,E,I,E,E,O,C,G,M,A,C,I,E,C,E,E,E,C,C,E,e,C,C,E,E,M,C,S,C,E,I,C,E,C,E,I,C,M,C,E,I,C,O,C,E,I,C,O,C,C,C,E,E,O,C,E,E,K,C,E,E,M,C,E,E,O,C,K,E,E,S,C,K,E,E,S,C,K,E,E,C,C,E,E,Q,C,S,C,C,C,E,C,C,E,C,C,S,C,C,C,E,E,O,C,C,E,C,E,A,E,O,c,C,E,O,C,I,W,O,C,C,E,A,C,G,C,C,E,C,E,I,I,E,E,E,E,M,C,I,E,C,C,E,E,G,E,C,I,E,E,E,A,C,U,O,S,A,a,O,O,O,O,C,E,A,Y,O,Q,O,G,E,O,W,O,C,E,C,E,C,Q,C,S,C,C,C,C,C,C,C,E,I,E,E,kD,E,iB,C,GCEwB,EAAA,MAAA,CAAA,EAAA,UAAA,IAAA,GAFxB,IAAA,EAAA,EAAA,4B,E,E,c,C,GAEe,SAAS,EAAmB,EAAS,CAAC,CAAC,EAClD,GAAM,CAAE,YAAA,EAAc,GAAK,CAAE,OAAA,EAAS,CAAC,CAAE,SAAA,EAAW,GAAG,CAAE,WAAA,EAAa,IAAK,CAAE,aAAA,EAAe,IAAM,IAAI,CAAE,CAAG,EAE3G,OAAO,AAAC,IACJ,IAAI,EAAU,CAAA,EACV,EAAW,KACX,EAAa,KACb,EAAe,KACf,EAAW,KACX,EAAe,EAAE,CACjB,EAAQ,KACR,EAAgB,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","sources":["","packages/artplayer-plugin-asr/src/index.js","node_modules/@parcel/runtime-js/lib/bundles/runtime-8d01a8f56d551fc8.js","node_modules/@parcel/transformer-js/src/esmodule-helpers.js"],"sourcesContent":["// modules are defined as an array\n// [ module function, map of requires ]\n//\n// map of requires is short require name -> numeric require\n//\n// anything defined in a previous bundle is accessed via the\n// orig method which is the require for previous bundles\n\n(function (\n modules,\n entry,\n mainEntry,\n parcelRequireName,\n externals,\n distDir,\n publicUrl,\n devServer\n) {\n /* eslint-disable no-undef */\n var globalObject =\n typeof globalThis !== 'undefined'\n ? globalThis\n : typeof self !== 'undefined'\n ? self\n : typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined'\n ? global\n : {};\n /* eslint-enable no-undef */\n\n // Save the require from previous bundle to this closure if any\n var previousRequire =\n typeof globalObject[parcelRequireName] === 'function' &&\n globalObject[parcelRequireName];\n\n var importMap = previousRequire.i || {};\n var cache = previousRequire.cache || {};\n // Do not use `require` to prevent Webpack from trying to bundle this call\n var nodeRequire =\n typeof module !== 'undefined' &&\n typeof module.require === 'function' &&\n module.require.bind(module);\n\n function newRequire(name, jumped) {\n if (!cache[name]) {\n if (!modules[name]) {\n if (externals[name]) {\n return externals[name];\n }\n // if we cannot find the module within our internal map or\n // cache jump to the current global require ie. the last bundle\n // that was added to the page.\n var currentRequire =\n typeof globalObject[parcelRequireName] === 'function' &&\n globalObject[parcelRequireName];\n if (!jumped && currentRequire) {\n return currentRequire(name, true);\n }\n\n // If there are other bundles on this page the require from the\n // previous one is saved to 'previousRequire'. Repeat this as\n // many times as there are bundles until the module is found or\n // we exhaust the require chain.\n if (previousRequire) {\n return previousRequire(name, true);\n }\n\n // Try the node require function if it exists.\n if (nodeRequire && typeof name === 'string') {\n return nodeRequire(name);\n }\n\n var err = new Error(\"Cannot find module '\" + name + \"'\");\n err.code = 'MODULE_NOT_FOUND';\n throw err;\n }\n\n localRequire.resolve = resolve;\n localRequire.cache = {};\n\n var module = (cache[name] = new newRequire.Module(name));\n\n modules[name][0].call(\n module.exports,\n localRequire,\n module,\n module.exports,\n globalObject\n );\n }\n\n return cache[name].exports;\n\n function localRequire(x) {\n var res = localRequire.resolve(x);\n return res === false ? {} : newRequire(res);\n }\n\n function resolve(x) {\n var id = modules[name][1][x];\n return id != null ? id : x;\n }\n }\n\n function Module(moduleName) {\n this.id = moduleName;\n this.bundle = newRequire;\n this.require = nodeRequire;\n this.exports = {};\n }\n\n newRequire.isParcelRequire = true;\n newRequire.Module = Module;\n newRequire.modules = modules;\n newRequire.cache = cache;\n newRequire.parent = previousRequire;\n newRequire.distDir = distDir;\n newRequire.publicUrl = publicUrl;\n newRequire.devServer = devServer;\n newRequire.i = importMap;\n newRequire.register = function (id, exports) {\n modules[id] = [\n function (require, module) {\n module.exports = exports;\n },\n {},\n ];\n };\n\n // Only insert newRequire.load when it is actually used.\n // The code in this file is linted against ES5, so dynamic import is not allowed.\n // INSERT_LOAD_HERE\n\n Object.defineProperty(newRequire, 'root', {\n get: function () {\n return globalObject[parcelRequireName];\n },\n });\n\n globalObject[parcelRequireName] = newRequire;\n\n for (var i = 0; i < entry.length; i++) {\n newRequire(entry[i]);\n }\n\n if (mainEntry) {\n // Expose entry point to Node, AMD or browser globals\n // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js\n var mainExports = newRequire(mainEntry);\n\n // CommonJS\n if (typeof exports === 'object' && typeof module !== 'undefined') {\n module.exports = mainExports;\n\n // RequireJS\n } else if (typeof define === 'function' && define.amd) {\n define(function () {\n return mainExports;\n });\n }\n }\n})({\"40eeC\":[function(require,module,exports,__globalThis) {\nvar parcelHelpers = require(\"@parcel/transformer-js/src/esmodule-helpers.js\");\nparcelHelpers.defineInteropFlag(exports);\nparcelHelpers.export(exports, \"default\", ()=>artplayerPluginAsr);\nvar _styleLess = require(\"bundle-text:./style.less\");\nvar _styleLessDefault = parcelHelpers.interopDefault(_styleLess);\nfunction artplayerPluginAsr(option = {}) {\n const { hideTimeout = 10000, length = 3, interval = 100, sampleRate = 16000, onAudioChunk = ()=>null } = option;\n return (art)=>{\n let started = false;\n let audioCtx = null;\n let sourceNode = null;\n let recorderNode = null;\n let gainNode = null;\n let bufferChunks = [];\n let timer = null;\n let workletLoaded = false;\n let hideTimer = null;\n let mediaStream = null;\n let mediaStreamSource = null;\n const $asr = art.layers.add({\n name: 'asr',\n html: ''\n });\n function splitByPunctuation(text) {\n return text// eslint-disable-next-line no-useless-escape\n .split(/(?<=[、。!?!?\\.])\\s*/u).map((s)=>s.trim()).filter(Boolean).slice(-length);\n }\n function hide() {\n $asr.style.display = 'none';\n }\n function append(subtitle) {\n if (typeof subtitle !== 'string') return;\n clearTimeout(hideTimer);\n hideTimer = setTimeout(hide, hideTimeout);\n $asr.style.display = '';\n $asr.innerHTML = splitByPunctuation(subtitle).map((line)=>`
${line}
`).join('');\n }\n const recorderProcessorCode = `\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n `;\n const createWorkletBlobUrl = ()=>{\n const blob = new Blob([\n recorderProcessorCode\n ], {\n type: 'application/javascript'\n });\n return URL.createObjectURL(blob);\n };\n function floatTo16BitPCM(float32Array) {\n const len = float32Array.length;\n const buffer = new ArrayBuffer(len * 2);\n const view = new DataView(buffer);\n for(let i = 0; i < len; i++){\n let s = Math.max(-1, Math.min(1, float32Array[i]));\n view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n }\n return buffer;\n }\n async function setupAudioContext() {\n if (audioCtx) return audioCtx;\n audioCtx = new (window.AudioContext || window.webkitAudioContext)({\n sampleRate\n });\n if (audioCtx.state === 'suspended') await audioCtx.resume();\n return audioCtx;\n }\n async function setupAudioSource() {\n if (!sourceNode && art.video) try {\n sourceNode = audioCtx.createMediaElementSource(art.video);\n return sourceNode;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Direct connection failed, trying fallback...', err);\n }\n try {\n if (!mediaStream) mediaStream = await captureAudioFromVideo(art.video);\n if (mediaStream) {\n mediaStreamSource = audioCtx.createMediaStreamSource(mediaStream);\n return mediaStreamSource;\n }\n } catch (err) {\n console.warn('[artplayerPluginAsr] MediaStream fallback failed:', err);\n }\n return null;\n }\n async function captureAudioFromVideo(videoElement) {\n try {\n if (videoElement.captureStream) return videoElement.captureStream();\n if (videoElement.mozCaptureStream) return videoElement.mozCaptureStream();\n console.warn('[artplayerPluginAsr] captureStream not supported');\n return null;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Error capturing stream:', err);\n return null;\n }\n }\n async function startCapture() {\n if (started) return;\n try {\n await setupAudioContext();\n const audioSource = await setupAudioSource();\n if (!audioSource) throw new Error('Could not establish audio source');\n if (!workletLoaded) {\n const blobUrl = createWorkletBlobUrl();\n await audioCtx.audioWorklet.addModule(blobUrl);\n URL.revokeObjectURL(blobUrl);\n workletLoaded = true;\n }\n // 创建输出音频的 GainNode(正常播放)\n gainNode = audioCtx.createGain();\n gainNode.gain.value = 1;\n recorderNode = new AudioWorkletNode(audioCtx, 'recorder-processor');\n recorderNode.port.onmessage = (event)=>{\n bufferChunks.push(new Float32Array(event.data));\n };\n // 分流:识别和播放\n audioSource.connect(recorderNode);\n audioSource.connect(gainNode);\n gainNode.connect(audioCtx.destination); // 正常声音输出\n // recorderNode 不连接 destination,避免输出干扰\n const CHUNK_SAMPLES = sampleRate * (interval / 1000);\n timer = setInterval(async ()=>{\n if (bufferChunks.length === 0) return;\n let accumulated = new Float32Array(0);\n while(accumulated.length < CHUNK_SAMPLES && bufferChunks.length){\n const next = bufferChunks.shift();\n const tmp = new Float32Array(accumulated.length + next.length);\n tmp.set(accumulated, 0);\n tmp.set(next, accumulated.length);\n accumulated = tmp;\n }\n if (accumulated.length < CHUNK_SAMPLES) return;\n const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES);\n const pcm = floatTo16BitPCM(chunkToSend);\n const subtitle = await onAudioChunk(pcm);\n append(subtitle);\n }, interval);\n started = true;\n } catch (err) {\n console.error('[artplayerPluginAsr] Initialization failed:', err);\n await stopCapture();\n }\n }\n async function stopCapture() {\n if (!started) return;\n started = false;\n clearInterval(timer);\n timer = null;\n if (recorderNode) {\n recorderNode.disconnect();\n recorderNode.port.onmessage = null;\n recorderNode = null;\n }\n if (gainNode) {\n gainNode.disconnect();\n gainNode = null;\n }\n bufferChunks = [];\n }\n async function destroy() {\n await stopCapture();\n if (mediaStreamSource) {\n mediaStreamSource.disconnect();\n mediaStreamSource = null;\n }\n if (sourceNode) {\n sourceNode.disconnect();\n sourceNode = null;\n }\n if (mediaStream) {\n mediaStream.getTracks().forEach((track)=>track.stop());\n mediaStream = null;\n }\n if (audioCtx) {\n await audioCtx.close();\n audioCtx = null;\n }\n workletLoaded = false;\n }\n art.on('play', startCapture);\n art.on('pause', stopCapture);\n art.on('destroy', destroy);\n return {\n name: 'artplayerPluginAsr',\n stop: destroy,\n hide,\n append\n };\n };\n}\nif (typeof document !== 'undefined') {\n if (!document.getElementById('artplayer-plugin-asr')) {\n const $style = document.createElement('style');\n $style.id = 'artplayer-plugin-asr';\n $style.textContent = (0, _styleLessDefault.default);\n document.head.appendChild($style);\n }\n}\nif (typeof window !== 'undefined') window['artplayerPluginAsr'] = artplayerPluginAsr;\n\n},{\"bundle-text:./style.less\":\"dKHY3\",\"@parcel/transformer-js/src/esmodule-helpers.js\":\"5lQoW\"}],\"dKHY3\":[function(require,module,exports,__globalThis) {\nmodule.exports = \".art-video-player .art-layer-asr{z-index:150;justify-content:end;gap:var(--art-subtitle-gap);padding:0 2%;padding-bottom:var(--art-subtitle-bottom);transition:padding-bottom var(--art-transition-duration)ease;text-shadow:var(--art-subtitle-border)1px 0 1px,var(--art-subtitle-border)0 1px 1px,var(--art-subtitle-border)-1px 0 1px,var(--art-subtitle-border)0 -1px 1px,var(--art-subtitle-border)1px 1px 1px,var(--art-subtitle-border)-1px -1px 1px,var(--art-subtitle-border)1px -1px 1px,var(--art-subtitle-border)-1px 1px 1px;flex-direction:column;font-size:1rem;display:flex;position:absolute;inset:0;pointer-events:none!important}.art-video-player.art-control-show .art-layer-asr{padding-bottom:calc(var(--art-control-height) + var(--art-subtitle-bottom))}\";\n\n},{}],\"5lQoW\":[function(require,module,exports,__globalThis) {\nexports.interopDefault = function(a) {\n return a && a.__esModule ? a : {\n default: a\n };\n};\nexports.defineInteropFlag = function(a) {\n Object.defineProperty(a, '__esModule', {\n value: true\n });\n};\nexports.exportAll = function(source, dest) {\n Object.keys(source).forEach(function(key) {\n if (key === 'default' || key === '__esModule' || Object.prototype.hasOwnProperty.call(dest, key)) return;\n Object.defineProperty(dest, key, {\n enumerable: true,\n get: function() {\n return source[key];\n }\n });\n });\n return dest;\n};\nexports.export = function(dest, destName, get) {\n Object.defineProperty(dest, destName, {\n enumerable: true,\n get: get\n });\n};\n\n},{}]},[\"40eeC\"], \"40eeC\", \"parcelRequire4dc0\", {})\nlet {default: _default, } = parcelRequire4dc0(\"40eeC\");\nexport {_default as default, };\n\n//# sourceMappingURL=index.js.map\n","import style from 'bundle-text:./style.less';\n\nexport default function artplayerPluginAsr(option = {}) {\n const { hideTimeout = 10000, length = 3, interval = 100, sampleRate = 16000, onAudioChunk = () => null } = option;\n\n return (art) => {\n let started = false;\n let audioCtx = null;\n let sourceNode = null;\n let recorderNode = null;\n let gainNode = null;\n let bufferChunks = [];\n let timer = null;\n let workletLoaded = false;\n let hideTimer = null;\n let mediaStream = null;\n let mediaStreamSource = null;\n\n const $asr = art.layers.add({\n name: 'asr',\n html: '',\n });\n\n function splitByPunctuation(text) {\n return (\n text\n // eslint-disable-next-line no-useless-escape\n .split(/(?<=[、。!?!?\\.])\\s*/u)\n .map((s) => s.trim())\n .filter(Boolean)\n .slice(-length)\n );\n }\n\n function hide() {\n $asr.style.display = 'none';\n }\n\n function append(subtitle) {\n if (typeof subtitle !== 'string') return;\n clearTimeout(hideTimer);\n hideTimer = setTimeout(hide, hideTimeout);\n $asr.style.display = '';\n $asr.innerHTML = splitByPunctuation(subtitle)\n .map((line) => `
${line}
`)\n .join('');\n }\n\n const recorderProcessorCode = `\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n `;\n\n const createWorkletBlobUrl = () => {\n const blob = new Blob([recorderProcessorCode], { type: 'application/javascript' });\n return URL.createObjectURL(blob);\n };\n\n function floatTo16BitPCM(float32Array) {\n const len = float32Array.length;\n const buffer = new ArrayBuffer(len * 2);\n const view = new DataView(buffer);\n for (let i = 0; i < len; i++) {\n let s = Math.max(-1, Math.min(1, float32Array[i]));\n view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n }\n return buffer;\n }\n\n async function setupAudioContext() {\n if (audioCtx) return audioCtx;\n audioCtx = new (window.AudioContext || window.webkitAudioContext)({ sampleRate });\n if (audioCtx.state === 'suspended') await audioCtx.resume();\n return audioCtx;\n }\n\n async function setupAudioSource() {\n if (!sourceNode && art.video) {\n try {\n sourceNode = audioCtx.createMediaElementSource(art.video);\n return sourceNode;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Direct connection failed, trying fallback...', err);\n }\n }\n\n try {\n if (!mediaStream) {\n mediaStream = await captureAudioFromVideo(art.video);\n }\n if (mediaStream) {\n mediaStreamSource = audioCtx.createMediaStreamSource(mediaStream);\n return mediaStreamSource;\n }\n } catch (err) {\n console.warn('[artplayerPluginAsr] MediaStream fallback failed:', err);\n }\n\n return null;\n }\n\n async function captureAudioFromVideo(videoElement) {\n try {\n if (videoElement.captureStream) return videoElement.captureStream();\n if (videoElement.mozCaptureStream) return videoElement.mozCaptureStream();\n console.warn('[artplayerPluginAsr] captureStream not supported');\n return null;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Error capturing stream:', err);\n return null;\n }\n }\n\n async function startCapture() {\n if (started) return;\n\n try {\n await setupAudioContext();\n const audioSource = await setupAudioSource();\n if (!audioSource) throw new Error('Could not establish audio source');\n\n if (!workletLoaded) {\n const blobUrl = createWorkletBlobUrl();\n await audioCtx.audioWorklet.addModule(blobUrl);\n URL.revokeObjectURL(blobUrl);\n workletLoaded = true;\n }\n\n // 创建输出音频的 GainNode(正常播放)\n gainNode = audioCtx.createGain();\n gainNode.gain.value = 1;\n\n recorderNode = new AudioWorkletNode(audioCtx, 'recorder-processor');\n recorderNode.port.onmessage = (event) => {\n bufferChunks.push(new Float32Array(event.data));\n };\n\n // 分流:识别和播放\n audioSource.connect(recorderNode);\n audioSource.connect(gainNode);\n\n gainNode.connect(audioCtx.destination); // 正常声音输出\n // recorderNode 不连接 destination,避免输出干扰\n\n const CHUNK_SAMPLES = sampleRate * (interval / 1000);\n timer = setInterval(async () => {\n if (bufferChunks.length === 0) return;\n\n let accumulated = new Float32Array(0);\n while (accumulated.length < CHUNK_SAMPLES && bufferChunks.length) {\n const next = bufferChunks.shift();\n const tmp = new Float32Array(accumulated.length + next.length);\n tmp.set(accumulated, 0);\n tmp.set(next, accumulated.length);\n accumulated = tmp;\n }\n\n if (accumulated.length < CHUNK_SAMPLES) return;\n\n const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES);\n const pcm = floatTo16BitPCM(chunkToSend);\n const subtitle = await onAudioChunk(pcm);\n append(subtitle);\n }, interval);\n\n started = true;\n } catch (err) {\n console.error('[artplayerPluginAsr] Initialization failed:', err);\n await stopCapture();\n }\n }\n\n async function stopCapture() {\n if (!started) return;\n started = false;\n\n clearInterval(timer);\n timer = null;\n\n if (recorderNode) {\n recorderNode.disconnect();\n recorderNode.port.onmessage = null;\n recorderNode = null;\n }\n\n if (gainNode) {\n gainNode.disconnect();\n gainNode = null;\n }\n\n bufferChunks = [];\n }\n\n async function destroy() {\n await stopCapture();\n\n if (mediaStreamSource) {\n mediaStreamSource.disconnect();\n mediaStreamSource = null;\n }\n\n if (sourceNode) {\n sourceNode.disconnect();\n sourceNode = null;\n }\n\n if (mediaStream) {\n mediaStream.getTracks().forEach((track) => track.stop());\n mediaStream = null;\n }\n\n if (audioCtx) {\n await audioCtx.close();\n audioCtx = null;\n }\n\n workletLoaded = false;\n }\n\n art.on('play', startCapture);\n art.on('pause', stopCapture);\n art.on('destroy', destroy);\n\n return {\n name: 'artplayerPluginAsr',\n stop: destroy,\n hide,\n append,\n };\n };\n}\n\nif (typeof document !== 'undefined') {\n if (!document.getElementById('artplayer-plugin-asr')) {\n const $style = document.createElement('style');\n $style.id = 'artplayer-plugin-asr';\n $style.textContent = style;\n document.head.appendChild($style);\n }\n}\n\nif (typeof window !== 'undefined') {\n window['artplayerPluginAsr'] = artplayerPluginAsr;\n}\n","module.exports = \"704cf673cb407483\";","exports.interopDefault = function (a) {\n return a && a.__esModule ? a : {default: a};\n};\n\nexports.defineInteropFlag = function (a) {\n Object.defineProperty(a, '__esModule', {value: true});\n};\n\nexports.exportAll = function (source, dest) {\n Object.keys(source).forEach(function (key) {\n if (\n key === 'default' ||\n key === '__esModule' ||\n Object.prototype.hasOwnProperty.call(dest, key)\n ) {\n return;\n }\n\n Object.defineProperty(dest, key, {\n enumerable: true,\n get: function () {\n return source[key];\n },\n });\n });\n\n return dest;\n};\n\nexports.export = function (dest, destName, get) {\n Object.defineProperty(dest, destName, {\n enumerable: true,\n get: get,\n });\n};\n"],"names":["modules","entry","mainEntry","parcelRequireName","externals","distDir","publicUrl","devServer","globalObject","globalThis","self","window","global","previousRequire","importMap","i","cache","nodeRequire","module","require","bind","newRequire","name","jumped","currentRequire","err","Error","code","localRequire","resolve","x","id","Module","call","exports","res","isParcelRequire","moduleName","bundle","parent","register","Object","defineProperty","get","length","mainExports","define","amd","__globalThis","parcelHelpers","defineInteropFlag","export","artplayerPluginAsr","_styleLess","_styleLessDefault","interopDefault","option","hideTimeout","interval","sampleRate","onAudioChunk","art","started","audioCtx","sourceNode","recorderNode","gainNode","bufferChunks","timer","workletLoaded","hideTimer","mediaStream","mediaStreamSource","$asr","layers","add","html","hide","style","display","append","subtitle","clearTimeout","setTimeout","innerHTML","splitByPunctuation","text","split","map","s","trim","filter","Boolean","slice","line","join","recorderProcessorCode","createWorkletBlobUrl","blob","Blob","type","URL","createObjectURL","setupAudioContext","AudioContext","webkitAudioContext","state","resume","setupAudioSource","video","createMediaElementSource","console","warn","captureAudioFromVideo","createMediaStreamSource","videoElement","captureStream","mozCaptureStream","startCapture","audioSource","blobUrl","audioWorklet","addModule","revokeObjectURL","createGain","gain","value","AudioWorkletNode","port","onmessage","event","push","Float32Array","data","connect","destination","CHUNK_SAMPLES","setInterval","accumulated","next","shift","tmp","set","chunkToSend","pcm","floatTo16BitPCM","float32Array","len","buffer","ArrayBuffer","view","DataView","Math","max","min","setInt16","error","stopCapture","clearInterval","disconnect","destroy","getTracks","forEach","track","stop","close","on","document","getElementById","$style","createElement","textContent","default","head","appendChild","a","__esModule","exportAll","source","dest","keys","key","prototype","hasOwnProperty","enumerable","destName","_default","parcelRequire4dc0"],"version":3,"file":"index.js.map"} \ No newline at end of file +{"mappings":"C,A,S,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,E,I,E,A,a,O,W,W,A,a,O,K,K,A,a,O,O,O,A,a,O,O,O,C,E,E,A,Y,O,C,C,E,E,C,C,E,C,E,E,C,E,C,E,E,E,K,E,C,E,E,A,a,O,Q,A,Y,O,O,O,E,O,O,C,I,C,Q,S,E,C,C,C,E,G,C,C,C,E,C,C,G,C,C,C,E,C,C,G,C,C,E,C,O,C,C,E,C,I,E,A,Y,O,C,C,E,E,C,C,E,C,G,C,G,E,O,E,E,C,G,G,E,O,E,E,C,G,G,G,A,U,O,E,O,E,G,I,E,A,M,uB,E,I,O,E,I,C,mB,C,C,E,O,C,S,C,E,I,E,C,C,E,C,E,C,E,C,O,A,M,E,E,C,E,E,K,C,C,E,I,E,C,C,E,C,I,E,M,C,G,C,C,E,C,E,C,I,C,E,O,C,E,E,E,O,C,E,C,O,C,C,E,C,O,C,S,E,C,E,I,E,E,O,C,G,M,A,C,I,E,C,E,E,E,C,C,E,e,C,C,E,E,M,C,S,C,E,I,C,E,C,E,I,C,M,C,E,I,C,O,C,E,I,C,O,C,C,C,E,E,O,C,E,E,K,C,E,E,M,C,E,E,O,C,K,E,E,S,C,K,E,E,S,C,K,E,E,C,C,E,E,Q,C,S,C,C,C,E,C,C,E,C,C,S,C,C,C,E,E,O,C,C,E,C,E,A,E,O,c,C,E,O,C,I,W,O,C,C,E,A,C,G,C,C,E,C,E,I,I,E,E,E,E,M,C,I,E,C,C,E,E,G,E,C,I,E,E,E,A,C,U,O,S,A,a,O,O,O,O,C,E,A,Y,O,Q,O,G,E,O,W,O,C,E,C,E,C,Q,C,S,C,C,C,C,C,C,C,E,I,E,E,kD,E,iB,C,GCEwB,EAAA,MAAA,CAAA,EAAA,UAAA,IAAA,GAFxB,IAAA,EAAA,EAAA,4B,E,E,c,C,GAEe,SAAS,EAAmB,EAAS,CAAC,CAAC,EAClD,GAAM,CACF,OAAA,EAAS,CAAC,CACV,SAAA,EAAW,GAAG,CACd,WAAA,EAAa,IAAK,CAClB,gBAAA,EAAkB,GAAK,CACvB,aAAA,EAAe,IAAM,IAAI,CAC5B,CAAG,EAEJ,OAAO,AAAC,IACJ,IAAI,EAAU,CAAA,EACV,EAAW,KACX,EAAa,KACb,EAAe,KACf,EAAW,KACX,EAAe,EAAE,CACjB,EAAQ,KACR,EA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","sources":["","packages/artplayer-plugin-asr/src/index.js","node_modules/@parcel/runtime-js/lib/bundles/runtime-8d01a8f56d551fc8.js","node_modules/@parcel/transformer-js/src/esmodule-helpers.js"],"sourcesContent":["// modules are defined as an array\n// [ module function, map of requires ]\n//\n// map of requires is short require name -> numeric require\n//\n// anything defined in a previous bundle is accessed via the\n// orig method which is the require for previous bundles\n\n(function (\n modules,\n entry,\n mainEntry,\n parcelRequireName,\n externals,\n distDir,\n publicUrl,\n devServer\n) {\n /* eslint-disable no-undef */\n var globalObject =\n typeof globalThis !== 'undefined'\n ? globalThis\n : typeof self !== 'undefined'\n ? self\n : typeof window !== 'undefined'\n ? window\n : typeof global !== 'undefined'\n ? global\n : {};\n /* eslint-enable no-undef */\n\n // Save the require from previous bundle to this closure if any\n var previousRequire =\n typeof globalObject[parcelRequireName] === 'function' &&\n globalObject[parcelRequireName];\n\n var importMap = previousRequire.i || {};\n var cache = previousRequire.cache || {};\n // Do not use `require` to prevent Webpack from trying to bundle this call\n var nodeRequire =\n typeof module !== 'undefined' &&\n typeof module.require === 'function' &&\n module.require.bind(module);\n\n function newRequire(name, jumped) {\n if (!cache[name]) {\n if (!modules[name]) {\n if (externals[name]) {\n return externals[name];\n }\n // if we cannot find the module within our internal map or\n // cache jump to the current global require ie. the last bundle\n // that was added to the page.\n var currentRequire =\n typeof globalObject[parcelRequireName] === 'function' &&\n globalObject[parcelRequireName];\n if (!jumped && currentRequire) {\n return currentRequire(name, true);\n }\n\n // If there are other bundles on this page the require from the\n // previous one is saved to 'previousRequire'. Repeat this as\n // many times as there are bundles until the module is found or\n // we exhaust the require chain.\n if (previousRequire) {\n return previousRequire(name, true);\n }\n\n // Try the node require function if it exists.\n if (nodeRequire && typeof name === 'string') {\n return nodeRequire(name);\n }\n\n var err = new Error(\"Cannot find module '\" + name + \"'\");\n err.code = 'MODULE_NOT_FOUND';\n throw err;\n }\n\n localRequire.resolve = resolve;\n localRequire.cache = {};\n\n var module = (cache[name] = new newRequire.Module(name));\n\n modules[name][0].call(\n module.exports,\n localRequire,\n module,\n module.exports,\n globalObject\n );\n }\n\n return cache[name].exports;\n\n function localRequire(x) {\n var res = localRequire.resolve(x);\n return res === false ? {} : newRequire(res);\n }\n\n function resolve(x) {\n var id = modules[name][1][x];\n return id != null ? id : x;\n }\n }\n\n function Module(moduleName) {\n this.id = moduleName;\n this.bundle = newRequire;\n this.require = nodeRequire;\n this.exports = {};\n }\n\n newRequire.isParcelRequire = true;\n newRequire.Module = Module;\n newRequire.modules = modules;\n newRequire.cache = cache;\n newRequire.parent = previousRequire;\n newRequire.distDir = distDir;\n newRequire.publicUrl = publicUrl;\n newRequire.devServer = devServer;\n newRequire.i = importMap;\n newRequire.register = function (id, exports) {\n modules[id] = [\n function (require, module) {\n module.exports = exports;\n },\n {},\n ];\n };\n\n // Only insert newRequire.load when it is actually used.\n // The code in this file is linted against ES5, so dynamic import is not allowed.\n // INSERT_LOAD_HERE\n\n Object.defineProperty(newRequire, 'root', {\n get: function () {\n return globalObject[parcelRequireName];\n },\n });\n\n globalObject[parcelRequireName] = newRequire;\n\n for (var i = 0; i < entry.length; i++) {\n newRequire(entry[i]);\n }\n\n if (mainEntry) {\n // Expose entry point to Node, AMD or browser globals\n // Based on https://github.com/ForbesLindesay/umd/blob/master/template.js\n var mainExports = newRequire(mainEntry);\n\n // CommonJS\n if (typeof exports === 'object' && typeof module !== 'undefined') {\n module.exports = mainExports;\n\n // RequireJS\n } else if (typeof define === 'function' && define.amd) {\n define(function () {\n return mainExports;\n });\n }\n }\n})({\"40eeC\":[function(require,module,exports,__globalThis) {\nvar parcelHelpers = require(\"@parcel/transformer-js/src/esmodule-helpers.js\");\nparcelHelpers.defineInteropFlag(exports);\nparcelHelpers.export(exports, \"default\", ()=>artplayerPluginAsr);\nvar _styleLess = require(\"bundle-text:./style.less\");\nvar _styleLessDefault = parcelHelpers.interopDefault(_styleLess);\nfunction artplayerPluginAsr(option = {}) {\n const { length = 3, interval = 100, sampleRate = 16000, autoHideTimeout = 10000, onAudioChunk = ()=>null } = option;\n return (art)=>{\n let started = false;\n let audioCtx = null;\n let sourceNode = null;\n let recorderNode = null;\n let gainNode = null;\n let bufferChunks = [];\n let timer = null;\n let workletLoaded = false;\n let hideTimer = null;\n let mediaStream = null;\n let mediaStreamSource = null;\n const $asr = art.layers.add({\n name: 'asr',\n html: ''\n });\n function splitByPunctuation(text) {\n return text// eslint-disable-next-line no-useless-escape\n .split(/(?<=[、。!?!?\\.])\\s*/u).map((s)=>s.trim()).filter(Boolean).slice(-length);\n }\n function hide() {\n $asr.style.display = 'none';\n }\n function append(subtitle) {\n if (typeof subtitle !== 'string') return;\n clearTimeout(hideTimer);\n hideTimer = setTimeout(hide, autoHideTimeout);\n $asr.style.display = '';\n $asr.innerHTML = splitByPunctuation(subtitle).map((line)=>`
${line}
`).join('');\n }\n const recorderProcessorCode = `\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n `;\n const createWorkletBlobUrl = ()=>{\n const blob = new Blob([\n recorderProcessorCode\n ], {\n type: 'application/javascript'\n });\n return URL.createObjectURL(blob);\n };\n function floatTo16BitPCM(float32Array) {\n const len = float32Array.length;\n const buffer = new ArrayBuffer(len * 2);\n const view = new DataView(buffer);\n for(let i = 0; i < len; i++){\n let s = Math.max(-1, Math.min(1, float32Array[i]));\n view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n }\n return buffer;\n }\n async function setupAudioContext() {\n if (audioCtx) return audioCtx;\n audioCtx = new (window.AudioContext || window.webkitAudioContext)({\n sampleRate\n });\n if (audioCtx.state === 'suspended') await audioCtx.resume();\n return audioCtx;\n }\n async function setupAudioSource() {\n if (!sourceNode && art.video) try {\n sourceNode = audioCtx.createMediaElementSource(art.video);\n return sourceNode;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Direct connection failed, trying fallback...', err);\n }\n try {\n if (!mediaStream) mediaStream = await captureAudioFromVideo(art.video);\n if (mediaStream) {\n mediaStreamSource = audioCtx.createMediaStreamSource(mediaStream);\n return mediaStreamSource;\n }\n } catch (err) {\n console.warn('[artplayerPluginAsr] MediaStream fallback failed:', err);\n }\n return null;\n }\n async function captureAudioFromVideo(videoElement) {\n try {\n if (videoElement.captureStream) return videoElement.captureStream();\n if (videoElement.mozCaptureStream) return videoElement.mozCaptureStream();\n console.warn('[artplayerPluginAsr] captureStream not supported');\n return null;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Error capturing stream:', err);\n return null;\n }\n }\n async function startCapture() {\n if (started) return;\n try {\n await setupAudioContext();\n const audioSource = await setupAudioSource();\n if (!audioSource) throw new Error('Could not establish audio source');\n if (!workletLoaded) {\n const blobUrl = createWorkletBlobUrl();\n await audioCtx.audioWorklet.addModule(blobUrl);\n URL.revokeObjectURL(blobUrl);\n workletLoaded = true;\n }\n gainNode = audioCtx.createGain();\n gainNode.gain.value = 1;\n recorderNode = new AudioWorkletNode(audioCtx, 'recorder-processor');\n recorderNode.port.onmessage = (event)=>{\n bufferChunks.push(new Float32Array(event.data));\n };\n audioSource.connect(recorderNode);\n audioSource.connect(gainNode);\n gainNode.connect(audioCtx.destination);\n const CHUNK_SAMPLES = sampleRate * (interval / 1000);\n timer = setInterval(async ()=>{\n if (bufferChunks.length === 0) return;\n let accumulated = new Float32Array(0);\n while(accumulated.length < CHUNK_SAMPLES && bufferChunks.length){\n const next = bufferChunks.shift();\n const tmp = new Float32Array(accumulated.length + next.length);\n tmp.set(accumulated, 0);\n tmp.set(next, accumulated.length);\n accumulated = tmp;\n }\n if (accumulated.length < CHUNK_SAMPLES) return;\n const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES);\n const buffer = floatTo16BitPCM(chunkToSend);\n const subtitle = await onAudioChunk(buffer);\n append(subtitle);\n }, interval);\n started = true;\n } catch (err) {\n console.error('[artplayerPluginAsr] Initialization failed:', err);\n await stopCapture();\n }\n }\n async function stopCapture() {\n if (!started) return;\n started = false;\n clearInterval(timer);\n timer = null;\n if (recorderNode) {\n recorderNode.disconnect();\n recorderNode.port.onmessage = null;\n recorderNode = null;\n }\n if (gainNode) {\n gainNode.disconnect();\n gainNode = null;\n }\n bufferChunks = [];\n }\n async function destroy() {\n await stopCapture();\n if (mediaStreamSource) {\n mediaStreamSource.disconnect();\n mediaStreamSource = null;\n }\n if (sourceNode) {\n sourceNode.disconnect();\n sourceNode = null;\n }\n if (mediaStream) {\n mediaStream.getTracks().forEach((track)=>track.stop());\n mediaStream = null;\n }\n if (audioCtx) {\n await audioCtx.close();\n audioCtx = null;\n }\n workletLoaded = false;\n }\n art.on('play', startCapture);\n art.on('pause', stopCapture);\n art.on('destroy', destroy);\n return {\n name: 'artplayerPluginAsr',\n stop: destroy,\n hide,\n append\n };\n };\n}\nif (typeof document !== 'undefined') {\n if (!document.getElementById('artplayer-plugin-asr')) {\n const $style = document.createElement('style');\n $style.id = 'artplayer-plugin-asr';\n $style.textContent = (0, _styleLessDefault.default);\n document.head.appendChild($style);\n }\n}\nif (typeof window !== 'undefined') window['artplayerPluginAsr'] = artplayerPluginAsr;\n\n},{\"bundle-text:./style.less\":\"dKHY3\",\"@parcel/transformer-js/src/esmodule-helpers.js\":\"5lQoW\"}],\"dKHY3\":[function(require,module,exports,__globalThis) {\nmodule.exports = \".art-video-player .art-layer-asr{z-index:150;justify-content:end;gap:var(--art-subtitle-gap);padding:0 2%;padding-bottom:var(--art-subtitle-bottom);transition:padding-bottom var(--art-transition-duration)ease;text-shadow:var(--art-subtitle-border)1px 0 1px,var(--art-subtitle-border)0 1px 1px,var(--art-subtitle-border)-1px 0 1px,var(--art-subtitle-border)0 -1px 1px,var(--art-subtitle-border)1px 1px 1px,var(--art-subtitle-border)-1px -1px 1px,var(--art-subtitle-border)1px -1px 1px,var(--art-subtitle-border)-1px 1px 1px;flex-direction:column;font-size:1rem;display:flex;position:absolute;inset:0;pointer-events:none!important}.art-video-player.art-control-show .art-layer-asr{padding-bottom:calc(var(--art-control-height) + var(--art-subtitle-bottom))}\";\n\n},{}],\"5lQoW\":[function(require,module,exports,__globalThis) {\nexports.interopDefault = function(a) {\n return a && a.__esModule ? a : {\n default: a\n };\n};\nexports.defineInteropFlag = function(a) {\n Object.defineProperty(a, '__esModule', {\n value: true\n });\n};\nexports.exportAll = function(source, dest) {\n Object.keys(source).forEach(function(key) {\n if (key === 'default' || key === '__esModule' || Object.prototype.hasOwnProperty.call(dest, key)) return;\n Object.defineProperty(dest, key, {\n enumerable: true,\n get: function() {\n return source[key];\n }\n });\n });\n return dest;\n};\nexports.export = function(dest, destName, get) {\n Object.defineProperty(dest, destName, {\n enumerable: true,\n get: get\n });\n};\n\n},{}]},[\"40eeC\"], \"40eeC\", \"parcelRequire4dc0\", {})\nlet {default: _default, } = parcelRequire4dc0(\"40eeC\");\nexport {_default as default, };\n\n//# sourceMappingURL=index.js.map\n","import style from 'bundle-text:./style.less';\n\nexport default function artplayerPluginAsr(option = {}) {\n const {\n length = 3,\n interval = 100,\n sampleRate = 16000,\n autoHideTimeout = 10000,\n onAudioChunk = () => null,\n } = option;\n\n return (art) => {\n let started = false;\n let audioCtx = null;\n let sourceNode = null;\n let recorderNode = null;\n let gainNode = null;\n let bufferChunks = [];\n let timer = null;\n let workletLoaded = false;\n let hideTimer = null;\n let mediaStream = null;\n let mediaStreamSource = null;\n\n const $asr = art.layers.add({\n name: 'asr',\n html: '',\n });\n\n function splitByPunctuation(text) {\n return (\n text\n // eslint-disable-next-line no-useless-escape\n .split(/(?<=[、。!?!?\\.])\\s*/u)\n .map((s) => s.trim())\n .filter(Boolean)\n .slice(-length)\n );\n }\n\n function hide() {\n $asr.style.display = 'none';\n }\n\n function append(subtitle) {\n if (typeof subtitle !== 'string') return;\n clearTimeout(hideTimer);\n hideTimer = setTimeout(hide, autoHideTimeout);\n $asr.style.display = '';\n $asr.innerHTML = splitByPunctuation(subtitle)\n .map((line) => `
${line}
`)\n .join('');\n }\n\n const recorderProcessorCode = `\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n `;\n\n const createWorkletBlobUrl = () => {\n const blob = new Blob([recorderProcessorCode], { type: 'application/javascript' });\n return URL.createObjectURL(blob);\n };\n\n function floatTo16BitPCM(float32Array) {\n const len = float32Array.length;\n const buffer = new ArrayBuffer(len * 2);\n const view = new DataView(buffer);\n for (let i = 0; i < len; i++) {\n let s = Math.max(-1, Math.min(1, float32Array[i]));\n view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n }\n return buffer;\n }\n\n async function setupAudioContext() {\n if (audioCtx) return audioCtx;\n audioCtx = new (window.AudioContext || window.webkitAudioContext)({ sampleRate });\n if (audioCtx.state === 'suspended') await audioCtx.resume();\n return audioCtx;\n }\n\n async function setupAudioSource() {\n if (!sourceNode && art.video) {\n try {\n sourceNode = audioCtx.createMediaElementSource(art.video);\n return sourceNode;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Direct connection failed, trying fallback...', err);\n }\n }\n\n try {\n if (!mediaStream) {\n mediaStream = await captureAudioFromVideo(art.video);\n }\n if (mediaStream) {\n mediaStreamSource = audioCtx.createMediaStreamSource(mediaStream);\n return mediaStreamSource;\n }\n } catch (err) {\n console.warn('[artplayerPluginAsr] MediaStream fallback failed:', err);\n }\n\n return null;\n }\n\n async function captureAudioFromVideo(videoElement) {\n try {\n if (videoElement.captureStream) return videoElement.captureStream();\n if (videoElement.mozCaptureStream) return videoElement.mozCaptureStream();\n console.warn('[artplayerPluginAsr] captureStream not supported');\n return null;\n } catch (err) {\n console.warn('[artplayerPluginAsr] Error capturing stream:', err);\n return null;\n }\n }\n\n async function startCapture() {\n if (started) return;\n\n try {\n await setupAudioContext();\n const audioSource = await setupAudioSource();\n if (!audioSource) throw new Error('Could not establish audio source');\n\n if (!workletLoaded) {\n const blobUrl = createWorkletBlobUrl();\n await audioCtx.audioWorklet.addModule(blobUrl);\n URL.revokeObjectURL(blobUrl);\n workletLoaded = true;\n }\n\n gainNode = audioCtx.createGain();\n gainNode.gain.value = 1;\n recorderNode = new AudioWorkletNode(audioCtx, 'recorder-processor');\n recorderNode.port.onmessage = (event) => {\n bufferChunks.push(new Float32Array(event.data));\n };\n audioSource.connect(recorderNode);\n audioSource.connect(gainNode);\n gainNode.connect(audioCtx.destination);\n\n const CHUNK_SAMPLES = sampleRate * (interval / 1000);\n timer = setInterval(async () => {\n if (bufferChunks.length === 0) return;\n\n let accumulated = new Float32Array(0);\n while (accumulated.length < CHUNK_SAMPLES && bufferChunks.length) {\n const next = bufferChunks.shift();\n const tmp = new Float32Array(accumulated.length + next.length);\n tmp.set(accumulated, 0);\n tmp.set(next, accumulated.length);\n accumulated = tmp;\n }\n\n if (accumulated.length < CHUNK_SAMPLES) return;\n\n const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES);\n const buffer = floatTo16BitPCM(chunkToSend);\n const subtitle = await onAudioChunk(buffer);\n append(subtitle);\n }, interval);\n\n started = true;\n } catch (err) {\n console.error('[artplayerPluginAsr] Initialization failed:', err);\n await stopCapture();\n }\n }\n\n async function stopCapture() {\n if (!started) return;\n started = false;\n\n clearInterval(timer);\n timer = null;\n\n if (recorderNode) {\n recorderNode.disconnect();\n recorderNode.port.onmessage = null;\n recorderNode = null;\n }\n\n if (gainNode) {\n gainNode.disconnect();\n gainNode = null;\n }\n\n bufferChunks = [];\n }\n\n async function destroy() {\n await stopCapture();\n\n if (mediaStreamSource) {\n mediaStreamSource.disconnect();\n mediaStreamSource = null;\n }\n\n if (sourceNode) {\n sourceNode.disconnect();\n sourceNode = null;\n }\n\n if (mediaStream) {\n mediaStream.getTracks().forEach((track) => track.stop());\n mediaStream = null;\n }\n\n if (audioCtx) {\n await audioCtx.close();\n audioCtx = null;\n }\n\n workletLoaded = false;\n }\n\n art.on('play', startCapture);\n art.on('pause', stopCapture);\n art.on('destroy', destroy);\n\n return {\n name: 'artplayerPluginAsr',\n stop: destroy,\n hide,\n append,\n };\n };\n}\n\nif (typeof document !== 'undefined') {\n if (!document.getElementById('artplayer-plugin-asr')) {\n const $style = document.createElement('style');\n $style.id = 'artplayer-plugin-asr';\n $style.textContent = style;\n document.head.appendChild($style);\n }\n}\n\nif (typeof window !== 'undefined') {\n window['artplayerPluginAsr'] = artplayerPluginAsr;\n}\n","module.exports = \"704cf673cb407483\";","exports.interopDefault = function (a) {\n return a && a.__esModule ? a : {default: a};\n};\n\nexports.defineInteropFlag = function (a) {\n Object.defineProperty(a, '__esModule', {value: true});\n};\n\nexports.exportAll = function (source, dest) {\n Object.keys(source).forEach(function (key) {\n if (\n key === 'default' ||\n key === '__esModule' ||\n Object.prototype.hasOwnProperty.call(dest, key)\n ) {\n return;\n }\n\n Object.defineProperty(dest, key, {\n enumerable: true,\n get: function () {\n return source[key];\n },\n });\n });\n\n return dest;\n};\n\nexports.export = function (dest, destName, get) {\n Object.defineProperty(dest, destName, {\n enumerable: true,\n get: get,\n });\n};\n"],"names":["modules","entry","mainEntry","parcelRequireName","externals","distDir","publicUrl","devServer","globalObject","globalThis","self","window","global","previousRequire","importMap","i","cache","nodeRequire","module","require","bind","newRequire","name","jumped","currentRequire","err","Error","code","localRequire","resolve","x","id","Module","call","exports","res","isParcelRequire","moduleName","bundle","parent","register","Object","defineProperty","get","length","mainExports","define","amd","__globalThis","parcelHelpers","defineInteropFlag","export","artplayerPluginAsr","_styleLess","_styleLessDefault","interopDefault","option","interval","sampleRate","autoHideTimeout","onAudioChunk","art","started","audioCtx","sourceNode","recorderNode","gainNode","bufferChunks","timer","workletLoaded","hideTimer","mediaStream","mediaStreamSource","$asr","layers","add","html","hide","style","display","append","subtitle","clearTimeout","setTimeout","innerHTML","splitByPunctuation","text","split","map","s","trim","filter","Boolean","slice","line","join","recorderProcessorCode","createWorkletBlobUrl","blob","Blob","type","URL","createObjectURL","setupAudioContext","AudioContext","webkitAudioContext","state","resume","setupAudioSource","video","createMediaElementSource","console","warn","captureAudioFromVideo","createMediaStreamSource","videoElement","captureStream","mozCaptureStream","startCapture","audioSource","blobUrl","audioWorklet","addModule","revokeObjectURL","createGain","gain","value","AudioWorkletNode","port","onmessage","event","push","Float32Array","data","connect","destination","CHUNK_SAMPLES","setInterval","accumulated","next","shift","tmp","set","chunkToSend","buffer","floatTo16BitPCM","float32Array","len","ArrayBuffer","view","DataView","Math","max","min","setInt16","error","stopCapture","clearInterval","disconnect","destroy","getTracks","forEach","track","stop","close","on","document","getElementById","$style","createElement","textContent","default","head","appendChild","a","__esModule","exportAll","source","dest","keys","key","prototype","hasOwnProperty","enumerable","destName","_default","parcelRequire4dc0"],"version":3,"file":"index.js.map"} \ No newline at end of file diff --git a/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.js b/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.js index 9e570582e..8fc105dcd 100644 --- a/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.js +++ b/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.js @@ -5,4 +5,4 @@ * (c) 2017-2025 Harvey Zack * Released under the MIT License. */ -!function(e,t,r,n,o,a,i,l){var u="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof u[n]&&u[n],c=s.i||{},d=s.cache||{},p="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function f(t,r){if(!d[t]){if(!e[t]){if(o[t])return o[t];var a="function"==typeof u[n]&&u[n];if(!r&&a)return a(t,!0);if(s)return s(t,!0);if(p&&"string"==typeof t)return p(t);var i=Error("Cannot find module '"+t+"'");throw i.code="MODULE_NOT_FOUND",i}c.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},c.cache={};var l=d[t]=new f.Module(t);e[t][0].call(l.exports,c,l,l.exports,u)}return d[t].exports;function c(e){var t=c.resolve(e);return!1===t?{}:f(t)}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.require=p,this.exports={}},f.modules=e,f.cache=d,f.parent=s,f.distDir=void 0,f.publicUrl=void 0,f.devServer=void 0,f.i=c,f.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(f,"root",{get:function(){return u[n]}}),u[n]=f;for(var y=0;yl);var a=e("bundle-text:./style.less"),i=o.interopDefault(a);function l(e={}){let{hideTimeout:t=1e4,length:r=3,interval:n=100,sampleRate:o=16e3,onAudioChunk:a=()=>null}=e;return e=>{let i=!1,l=null,u=null,s=null,c=null,d=[],p=null,f=!1,y=null,b=null,m=null,g=e.layers.add({name:"asr",html:""});function v(){g.style.display="none"}function h(e){"string"==typeof e&&(clearTimeout(y),y=setTimeout(v,t),g.style.display="",g.innerHTML=e.split(/(?<=[、。!?!?\.])\s*/u).map(e=>e.trim()).filter(Boolean).slice(-r).map(e=>`
${e}
`).join(""))}let x=` class RecorderProcessor extends AudioWorkletProcessor { process(inputs) { const input = inputs[0]; if (input && input[0]) { this.port.postMessage(input[0]); } return true; } } registerProcessor('recorder-processor', RecorderProcessor); `,w=()=>{let e=new Blob([x],{type:"application/javascript"});return URL.createObjectURL(e)};async function M(){return l||"suspended"===(l=new(window.AudioContext||window.webkitAudioContext)({sampleRate:o})).state&&await l.resume(),l}async function P(){if(!u&&e.video)try{return u=l.createMediaElementSource(e.video)}catch(e){console.warn("[artplayerPluginAsr] Direct connection failed, trying fallback...",e)}try{if(b||(b=await j(e.video)),b)return m=l.createMediaStreamSource(b)}catch(e){console.warn("[artplayerPluginAsr] MediaStream fallback failed:",e)}return null}async function j(e){try{if(e.captureStream)return e.captureStream();if(e.mozCaptureStream)return e.mozCaptureStream();return console.warn("[artplayerPluginAsr] captureStream not supported"),null}catch(e){return console.warn("[artplayerPluginAsr] Error capturing stream:",e),null}}async function A(){if(!i)try{await M();let e=await P();if(!e)throw Error("Could not establish audio source");if(!f){let e=w();await l.audioWorklet.addModule(e),URL.revokeObjectURL(e),f=!0}(c=l.createGain()).gain.value=1,(s=new AudioWorkletNode(l,"recorder-processor")).port.onmessage=e=>{d.push(new Float32Array(e.data))},e.connect(s),e.connect(c),c.connect(l.destination);let t=n/1e3*o;p=setInterval(async()=>{if(0===d.length)return;let e=new Float32Array(0);for(;e.lengthe.stop()),b=null),l&&(await l.close(),l=null),f=!1}return e.on("play",A),e.on("pause",O),e.on("destroy",k),{name:"artplayerPluginAsr",stop:k,hide:v,append:h}}}if("undefined"!=typeof document&&!document.getElementById("artplayer-plugin-asr")){let e=document.createElement("style");e.id="artplayer-plugin-asr",e.textContent=i.default,document.head.appendChild(e)}"undefined"!=typeof window&&(window.artplayerPluginAsr=l)},{"bundle-text:./style.less":"bqyvG","@parcel/transformer-js/src/esmodule-helpers.js":"6ykb1"}],bqyvG:[function(e,t,r,n){t.exports=".art-video-player .art-layer-asr{z-index:150;justify-content:end;gap:var(--art-subtitle-gap);padding:0 2%;padding-bottom:var(--art-subtitle-bottom);transition:padding-bottom var(--art-transition-duration)ease;text-shadow:var(--art-subtitle-border)1px 0 1px,var(--art-subtitle-border)0 1px 1px,var(--art-subtitle-border)-1px 0 1px,var(--art-subtitle-border)0 -1px 1px,var(--art-subtitle-border)1px 1px 1px,var(--art-subtitle-border)-1px -1px 1px,var(--art-subtitle-border)1px -1px 1px,var(--art-subtitle-border)-1px 1px 1px;flex-direction:column;font-size:1rem;display:flex;position:absolute;inset:0;pointer-events:none!important}.art-video-player.art-control-show .art-layer-asr{padding-bottom:calc(var(--art-control-height) + var(--art-subtitle-bottom))}"},{}],"6ykb1":[function(e,t,r,n){r.interopDefault=function(e){return e&&e.__esModule?e:{default:e}},r.defineInteropFlag=function(e){Object.defineProperty(e,"__esModule",{value:!0})},r.exportAll=function(e,t){return Object.keys(e).forEach(function(r){"default"===r||"__esModule"===r||Object.prototype.hasOwnProperty.call(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:function(){return e[r]}})}),t},r.export=function(e,t,r){Object.defineProperty(e,t,{enumerable:!0,get:r})}},{}]},["1gnQM"],"1gnQM","parcelRequire4dc0",{}); \ No newline at end of file +!function(e,t,r,n,o,a,i,l){var u="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof u[n]&&u[n],c=s.i||{},d=s.cache||{},p="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function f(t,r){if(!d[t]){if(!e[t]){if(o[t])return o[t];var a="function"==typeof u[n]&&u[n];if(!r&&a)return a(t,!0);if(s)return s(t,!0);if(p&&"string"==typeof t)return p(t);var i=Error("Cannot find module '"+t+"'");throw i.code="MODULE_NOT_FOUND",i}c.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},c.cache={};var l=d[t]=new f.Module(t);e[t][0].call(l.exports,c,l,l.exports,u)}return d[t].exports;function c(e){var t=c.resolve(e);return!1===t?{}:f(t)}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.require=p,this.exports={}},f.modules=e,f.cache=d,f.parent=s,f.distDir=void 0,f.publicUrl=void 0,f.devServer=void 0,f.i=c,f.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(f,"root",{get:function(){return u[n]}}),u[n]=f;for(var y=0;yl);var a=e("bundle-text:./style.less"),i=o.interopDefault(a);function l(e={}){let{length:t=3,interval:r=100,sampleRate:n=16e3,autoHideTimeout:o=1e4,onAudioChunk:a=()=>null}=e;return e=>{let i=!1,l=null,u=null,s=null,c=null,d=[],p=null,f=!1,y=null,b=null,m=null,g=e.layers.add({name:"asr",html:""});function v(){g.style.display="none"}function h(e){"string"==typeof e&&(clearTimeout(y),y=setTimeout(v,o),g.style.display="",g.innerHTML=e.split(/(?<=[、。!?!?\.])\s*/u).map(e=>e.trim()).filter(Boolean).slice(-t).map(e=>`
${e}
`).join(""))}let x=` class RecorderProcessor extends AudioWorkletProcessor { process(inputs) { const input = inputs[0]; if (input && input[0]) { this.port.postMessage(input[0]); } return true; } } registerProcessor('recorder-processor', RecorderProcessor); `,w=()=>{let e=new Blob([x],{type:"application/javascript"});return URL.createObjectURL(e)};async function M(){return l||"suspended"===(l=new(window.AudioContext||window.webkitAudioContext)({sampleRate:n})).state&&await l.resume(),l}async function P(){if(!u&&e.video)try{return u=l.createMediaElementSource(e.video)}catch(e){console.warn("[artplayerPluginAsr] Direct connection failed, trying fallback...",e)}try{if(b||(b=await j(e.video)),b)return m=l.createMediaStreamSource(b)}catch(e){console.warn("[artplayerPluginAsr] MediaStream fallback failed:",e)}return null}async function j(e){try{if(e.captureStream)return e.captureStream();if(e.mozCaptureStream)return e.mozCaptureStream();return console.warn("[artplayerPluginAsr] captureStream not supported"),null}catch(e){return console.warn("[artplayerPluginAsr] Error capturing stream:",e),null}}async function A(){if(!i)try{await M();let e=await P();if(!e)throw Error("Could not establish audio source");if(!f){let e=w();await l.audioWorklet.addModule(e),URL.revokeObjectURL(e),f=!0}(c=l.createGain()).gain.value=1,(s=new AudioWorkletNode(l,"recorder-processor")).port.onmessage=e=>{d.push(new Float32Array(e.data))},e.connect(s),e.connect(c),c.connect(l.destination);let t=r/1e3*n;p=setInterval(async()=>{if(0===d.length)return;let e=new Float32Array(0);for(;e.lengthe.stop()),b=null),l&&(await l.close(),l=null),f=!1}return e.on("play",A),e.on("pause",O),e.on("destroy",k),{name:"artplayerPluginAsr",stop:k,hide:v,append:h}}}if("undefined"!=typeof document&&!document.getElementById("artplayer-plugin-asr")){let e=document.createElement("style");e.id="artplayer-plugin-asr",e.textContent=i.default,document.head.appendChild(e)}"undefined"!=typeof window&&(window.artplayerPluginAsr=l)},{"bundle-text:./style.less":"bqyvG","@parcel/transformer-js/src/esmodule-helpers.js":"6ykb1"}],bqyvG:[function(e,t,r,n){t.exports=".art-video-player .art-layer-asr{z-index:150;justify-content:end;gap:var(--art-subtitle-gap);padding:0 2%;padding-bottom:var(--art-subtitle-bottom);transition:padding-bottom var(--art-transition-duration)ease;text-shadow:var(--art-subtitle-border)1px 0 1px,var(--art-subtitle-border)0 1px 1px,var(--art-subtitle-border)-1px 0 1px,var(--art-subtitle-border)0 -1px 1px,var(--art-subtitle-border)1px 1px 1px,var(--art-subtitle-border)-1px -1px 1px,var(--art-subtitle-border)1px -1px 1px,var(--art-subtitle-border)-1px 1px 1px;flex-direction:column;font-size:1rem;display:flex;position:absolute;inset:0;pointer-events:none!important}.art-video-player.art-control-show .art-layer-asr{padding-bottom:calc(var(--art-control-height) + var(--art-subtitle-bottom))}"},{}],"6ykb1":[function(e,t,r,n){r.interopDefault=function(e){return e&&e.__esModule?e:{default:e}},r.defineInteropFlag=function(e){Object.defineProperty(e,"__esModule",{value:!0})},r.exportAll=function(e,t){return Object.keys(e).forEach(function(r){"default"===r||"__esModule"===r||Object.prototype.hasOwnProperty.call(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:function(){return e[r]}})}),t},r.export=function(e,t,r){Object.defineProperty(e,t,{enumerable:!0,get:r})}},{}]},["1gnQM"],"1gnQM","parcelRequire4dc0",{}); \ No newline at end of file diff --git a/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.legacy.js b/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.legacy.js index 5a2a575d0..7a406e290 100644 --- a/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.legacy.js +++ b/packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.legacy.js @@ -5,4 +5,4 @@ * (c) 2017-2025 Harvey Zack * Released under the MIT License. */ -!function(e,t,r,n,o,i,a,u){var c="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof c[n]&&c[n],l=s.i||{},f=s.cache||{},p="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function d(t,r){if(!f[t]){if(!e[t]){if(o[t])return o[t];var i="function"==typeof c[n]&&c[n];if(!r&&i)return i(t,!0);if(s)return s(t,!0);if(p&&"string"==typeof t)return p(t);var a=Error("Cannot find module '"+t+"'");throw a.code="MODULE_NOT_FOUND",a}l.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},l.cache={};var u=f[t]=new d.Module(t);e[t][0].call(u.exports,l,u,u.exports,c)}return f[t].exports;function l(e){var t=l.resolve(e);return!1===t?{}:d(t)}}d.isParcelRequire=!0,d.Module=function(e){this.id=e,this.bundle=d,this.require=p,this.exports={}},d.modules=e,d.cache=f,d.parent=s,d.distDir=void 0,d.publicUrl=void 0,d.devServer=void 0,d.i=l,d.register=function(t,r){e[t]=[function(e,t){t.exports=r},{}]},Object.defineProperty(d,"root",{get:function(){return c[n]}}),c[n]=d;for(var y=0;y0&&void 0!==arguments[0]?arguments[0]:{},t=e.hideTimeout,r=void 0===t?1e4:t,n=e.length,o=void 0===n?3:n,u=e.interval,c=void 0===u?100:u,s=e.sampleRate,l=void 0===s?16e3:s,f=e.onAudioChunk,p=void 0===f?function(){return null}:f;return function(e){var t=!1,n=null,u=null,s=null,f=null,d=[],y=null,h=!1,_=null,v=null,b=null,m=e.layers.add({name:"asr",html:""});function w(){m.style.display="none"}function g(e){"string"==typeof e&&(clearTimeout(_),_=setTimeout(w,r),m.style.display="",m.innerHTML=e.split(RegExp("(?<=[、。!?!?\\.])\\s*","u")).map(function(e){return e.trim()}).filter(Boolean).slice(-o).map(function(e){return'
'.concat(e,"
")}).join(""))}var x=function(){var e=new Blob(["\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n "],{type:"application/javascript"});return URL.createObjectURL(e)};function j(){return(j=(0,i._)(function(){return(0,a._)(this,function(e){switch(e.label){case 0:if(n)return[2,n];if("suspended"!==(n=new(window.AudioContext||window.webkitAudioContext)({sampleRate:l})).state)return[3,2];return[4,n.resume()];case 1:e.sent(),e.label=2;case 2:return[2,n]}})})).apply(this,arguments)}function O(){return(O=(0,i._)(function(){return(0,a._)(this,function(t){switch(t.label){case 0:if(!u&&e.video)try{return u=n.createMediaElementSource(e.video),[2,u]}catch(e){console.warn("[artplayerPluginAsr] Direct connection failed, trying fallback...",e)}t.label=1;case 1:if(t.trys.push([1,4,,5]),v)return[3,3];return[4,function(e){return P.apply(this,arguments)}(e.video)];case 2:v=t.sent(),t.label=3;case 3:if(v)return[2,b=n.createMediaStreamSource(v)];return[3,5];case 4:return console.warn("[artplayerPluginAsr] MediaStream fallback failed:",t.sent()),[3,5];case 5:return[2,null]}})})).apply(this,arguments)}function P(){return(P=(0,i._)(function(e){return(0,a._)(this,function(t){try{if(e.captureStream)return[2,e.captureStream()];if(e.mozCaptureStream)return[2,e.mozCaptureStream()];return console.warn("[artplayerPluginAsr] captureStream not supported"),[2,null]}catch(e){return console.warn("[artplayerPluginAsr] Error capturing stream:",e),[2,null]}})})).apply(this,arguments)}function S(){return(S=(0,i._)(function(){var e,r,o;return(0,a._)(this,function(u){switch(u.label){case 0:if(t)return[2];u.label=1;case 1:return u.trys.push([1,6,,8]),[4,function(){return j.apply(this,arguments)}()];case 2:return u.sent(),[4,function(){return O.apply(this,arguments)}()];case 3:if(!(e=u.sent()))throw Error("Could not establish audio source");if(h)return[3,5];return r=x(),[4,n.audioWorklet.addModule(r)];case 4:u.sent(),URL.revokeObjectURL(r),h=!0,u.label=5;case 5:return(f=n.createGain()).gain.value=1,(s=new AudioWorkletNode(n,"recorder-processor")).port.onmessage=function(e){d.push(new Float32Array(e.data))},e.connect(s),e.connect(f),f.connect(n.destination),o=c/1e3*l,y=setInterval((0,i._)(function(){var e,t,r;return(0,a._)(this,function(n){switch(n.label){case 0:if(0===d.length)return[2];for(e=new Float32Array(0);e.lengtht.indexOf(n)&&(r[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,n=Object.getOwnPropertySymbols(e);ot.indexOf(n[o])&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(r[n[o]]=e[n[o]]);return r}function l(e,t,r,n){var o,a=arguments.length,u=a<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,r):n;if(("undefined"==typeof Reflect?"undefined":(0,i._)(Reflect))==="object"&&"function"==typeof Reflect.decorate)u=Reflect.decorate(e,t,r,n);else for(var c=e.length-1;c>=0;c--)(o=e[c])&&(u=(a<3?o(u):a>3?o(t,r,u):o(t,r))||u);return a>3&&u&&Object.defineProperty(t,r,u),u}function f(e,t){return function(r,n){t(r,n,e)}}function p(e,t,r,n,o,a){function u(e){if(void 0!==e&&"function"!=typeof e)throw TypeError("Function expected");return e}for(var c,s=n.kind,l="getter"===s?"get":"setter"===s?"set":"value",f=!t&&e?n.static?e:e.prototype:null,p=t||(f?Object.getOwnPropertyDescriptor(f,n.name):{}),d=!1,y=r.length-1;y>=0;y--){var h={};for(var _ in n)h[_]="access"===_?{}:n[_];for(var _ in n.access)h.access[_]=n.access[_];h.addInitializer=function(e){if(d)throw TypeError("Cannot add initializers after decoration has completed");a.push(u(e||null))};var v=(0,r[y])("accessor"===s?{get:p.get,set:p.set}:p[l],h);if("accessor"===s){if(void 0===v)continue;if(null===v||(void 0===v?"undefined":(0,i._)(v))!=="object")throw TypeError("Object expected");(c=u(v.get))&&(p.get=c),(c=u(v.set))&&(p.set=c),(c=u(v.init))&&o.unshift(c)}else(c=u(v))&&("field"===s?o.unshift(c):p[l]=c)}f&&Object.defineProperty(f,n.name,p),d=!0}function d(e,t,r){for(var n=arguments.length>2,o=0;o0&&o[o.length-1])&&(6===s[0]||2===s[0])){i=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function x(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,i=r.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(n=i.next()).done;)a.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=i.return)&&r.call(i)}finally{if(o)throw o.error}}return a}function j(){for(var e=[],t=0;t1||u(e,t)})},t&&(n[e]=t(n[e])))}function u(e,t){try{var r;(r=o[e](t)).value instanceof S?Promise.resolve(r.value.v).then(c,s):l(i[0][2],r)}catch(e){l(i[0][3],e)}}function c(e){u("next",e)}function s(e){u("throw",e)}function l(e,t){e(t),i.shift(),i.length&&u(i[0][0],i[0][1])}}function A(e){var t,r;return t={},n("next"),n("throw",function(e){throw e}),n("return"),t[Symbol.iterator]=function(){return this},t;function n(n,o){t[n]=e[n]?function(t){return(r=!r)?{value:S(e[n](t)),done:!1}:o?o(t):t}:o}}function T(e){if(!Symbol.asyncIterator)throw TypeError("Symbol.asyncIterator is not defined.");var t,r=e[Symbol.asyncIterator];return r?r.call(e):(e=g(e),t={},n("next"),n("throw"),n("return"),t[Symbol.asyncIterator]=function(){return this},t);function n(r){t[r]=e[r]&&function(t){return new Promise(function(n,o){var i,a,u;i=n,a=o,u=(t=e[r](t)).done,Promise.resolve(t.value).then(function(e){i({value:e,done:u})},a)})}}}function I(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}var R=Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t},D=function(e){return(D=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[t.length]=r);return t})(e)};function M(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r=D(e),n=0;n0&&void 0!==arguments[0]?arguments[0]:{},t=e.length,r=void 0===t?3:t,n=e.interval,o=void 0===n?100:n,u=e.sampleRate,c=void 0===u?16e3:u,s=e.autoHideTimeout,l=void 0===s?1e4:s,f=e.onAudioChunk,p=void 0===f?function(){return null}:f;return function(e){var t=!1,n=null,u=null,s=null,f=null,d=[],y=null,_=!1,h=null,v=null,b=null,m=e.layers.add({name:"asr",html:""});function w(){m.style.display="none"}function g(e){"string"==typeof e&&(clearTimeout(h),h=setTimeout(w,l),m.style.display="",m.innerHTML=e.split(RegExp("(?<=[、。!?!?\\.])\\s*","u")).map(function(e){return e.trim()}).filter(Boolean).slice(-r).map(function(e){return'
'.concat(e,"
")}).join(""))}var x=function(){var e=new Blob(["\n class RecorderProcessor extends AudioWorkletProcessor {\n process(inputs) {\n const input = inputs[0];\n if (input && input[0]) {\n this.port.postMessage(input[0]);\n }\n return true;\n }\n }\n registerProcessor('recorder-processor', RecorderProcessor);\n "],{type:"application/javascript"});return URL.createObjectURL(e)};function j(){return(j=(0,i._)(function(){return(0,a._)(this,function(e){switch(e.label){case 0:if(n)return[2,n];if("suspended"!==(n=new(window.AudioContext||window.webkitAudioContext)({sampleRate:c})).state)return[3,2];return[4,n.resume()];case 1:e.sent(),e.label=2;case 2:return[2,n]}})})).apply(this,arguments)}function O(){return(O=(0,i._)(function(){return(0,a._)(this,function(t){switch(t.label){case 0:if(!u&&e.video)try{return u=n.createMediaElementSource(e.video),[2,u]}catch(e){console.warn("[artplayerPluginAsr] Direct connection failed, trying fallback...",e)}t.label=1;case 1:if(t.trys.push([1,4,,5]),v)return[3,3];return[4,function(e){return P.apply(this,arguments)}(e.video)];case 2:v=t.sent(),t.label=3;case 3:if(v)return[2,b=n.createMediaStreamSource(v)];return[3,5];case 4:return console.warn("[artplayerPluginAsr] MediaStream fallback failed:",t.sent()),[3,5];case 5:return[2,null]}})})).apply(this,arguments)}function P(){return(P=(0,i._)(function(e){return(0,a._)(this,function(t){try{if(e.captureStream)return[2,e.captureStream()];if(e.mozCaptureStream)return[2,e.mozCaptureStream()];return console.warn("[artplayerPluginAsr] captureStream not supported"),[2,null]}catch(e){return console.warn("[artplayerPluginAsr] Error capturing stream:",e),[2,null]}})})).apply(this,arguments)}function S(){return(S=(0,i._)(function(){var e,r,u;return(0,a._)(this,function(l){switch(l.label){case 0:if(t)return[2];l.label=1;case 1:return l.trys.push([1,6,,8]),[4,function(){return j.apply(this,arguments)}()];case 2:return l.sent(),[4,function(){return O.apply(this,arguments)}()];case 3:if(!(e=l.sent()))throw Error("Could not establish audio source");if(_)return[3,5];return r=x(),[4,n.audioWorklet.addModule(r)];case 4:l.sent(),URL.revokeObjectURL(r),_=!0,l.label=5;case 5:return(f=n.createGain()).gain.value=1,(s=new AudioWorkletNode(n,"recorder-processor")).port.onmessage=function(e){d.push(new Float32Array(e.data))},e.connect(s),e.connect(f),f.connect(n.destination),u=o/1e3*c,y=setInterval((0,i._)(function(){var e,t,r;return(0,a._)(this,function(n){switch(n.label){case 0:if(0===d.length)return[2];for(e=new Float32Array(0);e.lengtht.indexOf(n)&&(r[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,n=Object.getOwnPropertySymbols(e);ot.indexOf(n[o])&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(r[n[o]]=e[n[o]]);return r}function l(e,t,r,n){var o,a=arguments.length,u=a<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,r):n;if(("undefined"==typeof Reflect?"undefined":(0,i._)(Reflect))==="object"&&"function"==typeof Reflect.decorate)u=Reflect.decorate(e,t,r,n);else for(var c=e.length-1;c>=0;c--)(o=e[c])&&(u=(a<3?o(u):a>3?o(t,r,u):o(t,r))||u);return a>3&&u&&Object.defineProperty(t,r,u),u}function f(e,t){return function(r,n){t(r,n,e)}}function p(e,t,r,n,o,a){function u(e){if(void 0!==e&&"function"!=typeof e)throw TypeError("Function expected");return e}for(var c,s=n.kind,l="getter"===s?"get":"setter"===s?"set":"value",f=!t&&e?n.static?e:e.prototype:null,p=t||(f?Object.getOwnPropertyDescriptor(f,n.name):{}),d=!1,y=r.length-1;y>=0;y--){var _={};for(var h in n)_[h]="access"===h?{}:n[h];for(var h in n.access)_.access[h]=n.access[h];_.addInitializer=function(e){if(d)throw TypeError("Cannot add initializers after decoration has completed");a.push(u(e||null))};var v=(0,r[y])("accessor"===s?{get:p.get,set:p.set}:p[l],_);if("accessor"===s){if(void 0===v)continue;if(null===v||(void 0===v?"undefined":(0,i._)(v))!=="object")throw TypeError("Object expected");(c=u(v.get))&&(p.get=c),(c=u(v.set))&&(p.set=c),(c=u(v.init))&&o.unshift(c)}else(c=u(v))&&("field"===s?o.unshift(c):p[l]=c)}f&&Object.defineProperty(f,n.name,p),d=!0}function d(e,t,r){for(var n=arguments.length>2,o=0;o0&&o[o.length-1])&&(6===s[0]||2===s[0])){i=0;continue}if(3===s[0]&&(!o||s[1]>o[0]&&s[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function x(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,i=r.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(n=i.next()).done;)a.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=i.return)&&r.call(i)}finally{if(o)throw o.error}}return a}function j(){for(var e=[],t=0;t1||u(e,t)})},t&&(n[e]=t(n[e])))}function u(e,t){try{var r;(r=o[e](t)).value instanceof S?Promise.resolve(r.value.v).then(c,s):l(i[0][2],r)}catch(e){l(i[0][3],e)}}function c(e){u("next",e)}function s(e){u("throw",e)}function l(e,t){e(t),i.shift(),i.length&&u(i[0][0],i[0][1])}}function A(e){var t,r;return t={},n("next"),n("throw",function(e){throw e}),n("return"),t[Symbol.iterator]=function(){return this},t;function n(n,o){t[n]=e[n]?function(t){return(r=!r)?{value:S(e[n](t)),done:!1}:o?o(t):t}:o}}function T(e){if(!Symbol.asyncIterator)throw TypeError("Symbol.asyncIterator is not defined.");var t,r=e[Symbol.asyncIterator];return r?r.call(e):(e=g(e),t={},n("next"),n("throw"),n("return"),t[Symbol.asyncIterator]=function(){return this},t);function n(r){t[r]=e[r]&&function(t){return new Promise(function(n,o){var i,a,u;i=n,a=o,u=(t=e[r](t)).done,Promise.resolve(t.value).then(function(e){i({value:e,done:u})},a)})}}}function I(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}var R=Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t},D=function(e){return(D=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[t.length]=r);return t})(e)};function M(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r=D(e),n=0;n null } = option; + const { + length = 3, + interval = 100, + sampleRate = 16000, + autoHideTimeout = 10000, + onAudioChunk = () => null, + } = option; return (art) => { let started = false; @@ -39,7 +45,7 @@ export default function artplayerPluginAsr(option = {}) { function append(subtitle) { if (typeof subtitle !== 'string') return; clearTimeout(hideTimer); - hideTimer = setTimeout(hide, hideTimeout); + hideTimer = setTimeout(hide, autoHideTimeout); $asr.style.display = ''; $asr.innerHTML = splitByPunctuation(subtitle) .map((line) => `
${line}
`) @@ -134,21 +140,15 @@ export default function artplayerPluginAsr(option = {}) { workletLoaded = true; } - // 创建输出音频的 GainNode(正常播放) gainNode = audioCtx.createGain(); gainNode.gain.value = 1; - recorderNode = new AudioWorkletNode(audioCtx, 'recorder-processor'); recorderNode.port.onmessage = (event) => { bufferChunks.push(new Float32Array(event.data)); }; - - // 分流:识别和播放 audioSource.connect(recorderNode); audioSource.connect(gainNode); - - gainNode.connect(audioCtx.destination); // 正常声音输出 - // recorderNode 不连接 destination,避免输出干扰 + gainNode.connect(audioCtx.destination); const CHUNK_SAMPLES = sampleRate * (interval / 1000); timer = setInterval(async () => { @@ -166,8 +166,8 @@ export default function artplayerPluginAsr(option = {}) { if (accumulated.length < CHUNK_SAMPLES) return; const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES); - const pcm = floatTo16BitPCM(chunkToSend); - const subtitle = await onAudioChunk(pcm); + const buffer = floatTo16BitPCM(chunkToSend); + const subtitle = await onAudioChunk(buffer); append(subtitle); }, interval);