fix: rename cleanupTimeout to hideTimeout for consistency in ASR plugin

Refactor artplayerPluginAsr: Enhance audio capture and processing

- Introduced gainNode for audio output management.
- Added mediaStream and mediaStreamSource for fallback audio capture.
- Refactored startCapture and stopCapture functions for better clarity and error handling.
- Improved audio source setup with a dedicated function for capturing audio from video.
- Ensured proper disconnection of audio nodes and cleanup of resources on destroy.

feat: enhance ASR plugin with improved subtitle handling and styling

fix: rename autoClearTimer to hideTimer for consistency in ASR plugin

Update asr.js

feat: refactor ASR plugin to improve audio chunk handling and WebSocket management

Update asr.js

fix: rename autoClearTimeout to cleanupTimeout for consistency

Update asr.js

feat: refactor ASR handling and improve WebSocket management

Update index.js

feat: add append and clear functions to enhance audio chunk handling

Update asr.js

Update asr.js

feat: release version 2.0.0 of artplayer-plugin-asr

- Implemented core functionality for audio recording using AudioWorklet.
- Added support for configurable audio capture interval and sample rate.
- Introduced WAV encoding for recorded audio chunks.
- Created a new plugin structure with proper TypeScript definitions.
- Added legacy support for older environments.
- Updated package.json with necessary metadata and export configurations.
- Included comprehensive inline documentation for better maintainability.
This commit is contained in:
Harvey Zack committed 2025-05-23 00:09:13 +08:00
1 parent 6c4e9f7e78
commit 5d7710979d
22 files changed
+893 -1

No files matched your search

+57
View File
@@ -0,0 +1,57 @@
var art = new Artplayer({
container: '.artplayer-app',
url: '/assets/sample/video.mp4',
autoSize: true,
fullscreen: true,
fullscreenWeb: true,
plugins: [
artplayerPluginAsr({
length: 3,
interval: 40,
sampleRate: 16000,
hideTimeout: 10000,
// Use your AI tool to convert buffer into subtitles
onAudioChunk: (buffer) => tencentASR(buffer),
}),
]
});
var ws = null;
var loading = false;
async function tencentASR(buffer) {
if (loading) return;
if (!ws) {
loading = true;
const api = 'https://api.aimu.app/asr/tencent?engine_model_type=16k_ja';
const { url } = await (await fetch(api)).json();
ws = new WebSocket(url);
ws.binaryType = 'arraybuffer';
ws.onmessage = (event) => {
const { code, result } = JSON.parse(event.data);
if (code === 0) {
const subtitle = result?.voice_text_str;
art.plugins.artplayerPluginAsr.append(subtitle);
} else {
ws.close();
ws = null;
}
};
loading = false;
}
if (ws.readyState === WebSocket.OPEN) {
ws.send(buffer);
} else {
console.warn('WebSocket is not open');
}
}
art.on('destroy', () => {
try {
ws.send(JSON.stringify({ type: 'end' }));
ws.close();
} catch {}
ws = null;
});
+1
View File
@@ -48,6 +48,7 @@
var libUris = [
'./assets/ts/artplayer-plugin-ads.d.ts',
'./assets/ts/artplayer-plugin-asr.d.ts',
'./assets/ts/artplayer-plugin-ambilight.d.ts',
'./assets/ts/artplayer-plugin-auto-thumbnail.d.ts',
'./assets/ts/artplayer-plugin-chapter.d.ts',
+20
View File
@@ -0,0 +1,20 @@
import type Artplayer from 'artplayer';
export = artplayerPluginAsr;
export as namespace artplayerPluginAsr;
interface AsrPluginOption {
length?: number;
interval?: number;
sampleRate?: number;
hideTimeout?: number;
onAudioChunk?: (buffer: ArrayBuffer) => void | Promise<void>;
}
interface AsrPluginInstance {
name: 'artplayerPluginAsr';
hide: () => void;
append: () => void;
}
declare function artplayerPluginAsr(option?: AsrPluginOption): (art: Artplayer) => AsrPluginInstance;
-1
View File
@@ -58,7 +58,6 @@ export type Utils = {
export type Template = {
readonly $container: HTMLDivElement;
readonly $original: HTMLDivElement;
readonly $player: HTMLDivElement;
readonly $video: HTMLVideoElement;
readonly $track: HTMLTrackElement;
@@ -0,0 +1,9 @@
/*!
* artplayer-plugin-asr.js v2.0.0
* Github: https://github.com/zhw2590582/ArtPlayer
* (c) 2017-2025 Harvey Zack
* Released under the MIT License.
*/
!function(e,t,n,r,o,i,u,l){var a="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof a[r]&&a[r],d=s.i||{},f=s.cache||{},c="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function p(t,n){if(!f[t]){if(!e[t]){if(o[t])return o[t];var i="function"==typeof a[r]&&a[r];if(!n&&i)return i(t,!0);if(s)return s(t,!0);if(c&&"string"==typeof t)return c(t);var u=Error("Cannot find module '"+t+"'");throw u.code="MODULE_NOT_FOUND",u}d.resolve=function(n){var r=e[t][1][n];return null!=r?r:n},d.cache={};var l=f[t]=new p.Module(t);e[t][0].call(l.exports,d,l,l.exports,a)}return f[t].exports;function d(e){var t=d.resolve(e);return!1===t?{}:p(t)}}p.isParcelRequire=!0,p.Module=function(e){this.id=e,this.bundle=p,this.require=c,this.exports={}},p.modules=e,p.cache=f,p.parent=s,p.distDir=void 0,p.publicUrl=void 0,p.devServer=void 0,p.i=d,p.register=function(t,n){e[t]=[function(e,t){t.exports=n},{}]},Object.defineProperty(p,"root",{get:function(){return a[r]}}),a[r]=p;for(var y=0;y<t.length;y++)p(t[y]);if(n){var w=p(n);"object"==typeof exports&&"undefined"!=typeof module?module.exports=w:"function"==typeof define&&define.amd&&define(function(){return w})}}({"40eeC":[function(e,t,n,r){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");function i(e={}){let{interval:t=5e3,sampleRate:n=16e3,callback:r=()=>null}=e;return e=>{let o=!1,i=null,u=null,l=null,a=[],s=null,d=` 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); `,f=()=>{let e=new Blob([d],{type:"application/javascript"});return URL.createObjectURL(e)};async function c(){if(o)return;o=!0,"suspended"===(i=new(window.AudioContext||window.webkitAudioContext)({sampleRate:n})).state&&await i.resume(),u||(u=i.createMediaElementSource(e.video)).connect(i.destination);let d=f();await i.audioWorklet.addModule(d),URL.revokeObjectURL(d),(l=new AudioWorkletNode(i,"recorder-processor")).port.onmessage=e=>{a.push(new Float32Array(e.data))},u.connect(l).connect(i.destination),s=setInterval(async()=>{if(0===a.length)return;let e=function(e,t){let n=function(e){let t=new Float32Array(e.reduce((e,t)=>e+t.length,0)),n=0;return e.forEach(e=>{t.set(e,n),n+=e.length}),t}(e),r=2*n.length,o=new ArrayBuffer(44+r),i=new DataView(o);function u(e,t){for(let n=0;n<t.length;n++)i.setUint8(e+n,t.charCodeAt(n))}u(0,"RIFF"),i.setUint32(4,36+r,!0),u(8,"WAVE"),u(12,"fmt "),i.setUint32(16,16,!0),i.setUint16(20,1,!0),i.setUint16(22,1,!0),i.setUint32(24,t,!0),i.setUint32(28,2*t,!0),i.setUint16(32,2,!0),i.setUint16(34,16,!0),u(36,"data"),i.setUint32(40,r,!0);let l=function(e){let t=e.length,n=new ArrayBuffer(2*t),r=new DataView(n);for(let n=0;n<t;n++){let t=Math.max(-1,Math.min(1,e[n]));r.setInt16(2*n,t<0?32768*t:32767*t,!0)}return n}(n);return new Uint8Array(o).set(new Uint8Array(l),44),new Blob([i],{type:"audio/wav"})}(a,i.sampleRate),t=await e.arrayBuffer();await r(t),a=[]},t)}function p(){o&&(o=!1,s&&clearInterval(s),l&&l.disconnect(),l=null,a=[])}return e.on("play",c),e.on("pause",p),e.on("destroy",p),{name:"artplayerPluginAsr",destroy:p}}}o.defineInteropFlag(n),o.export(n,"default",()=>i),"undefined"!=typeof window&&(window.artplayerPluginAsr=i)},{"@parcel/transformer-js/src/esmodule-helpers.js":"5lQoW"}],"5lQoW":[function(e,t,n,r){n.interopDefault=function(e){return e&&e.__esModule?e:{default:e}},n.defineInteropFlag=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.exportAll=function(e,t){return Object.keys(e).forEach(function(n){"default"===n||"__esModule"===n||Object.prototype.hasOwnProperty.call(t,n)||Object.defineProperty(t,n,{enumerable:!0,get:function(){return e[n]}})}),t},n.export=function(e,t,n){Object.defineProperty(e,t,{enumerable:!0,get:n})}},{}]},["40eeC"],"40eeC","parcelRequire4dc0",{});let{default:e}=parcelRequire4dc0("40eeC");export{e as default};
//# sourceMappingURL=artplayer-plugin-asr.esm.js.map
@@ -0,0 +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,kDCAe,SAAS,EAAmB,EAAS,CAAC,CAAC,EAClD,GAAM,CAAE,SAAA,EAAW,GAAI,CAAE,WAAA,EAAa,IAAK,CAAE,SAAA,EAAW,IAAM,IAAI,CAAE,CAAG,EAEvE,OAAO,AAAC,IACJ,IAAI,EAAU,CAAA,EACV,EAAW,KACX,EAAa,KACb,EAAe,KACf,EAAe,EAAE,CACjB,EAAQ,KAEN,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,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","sources":["<anon>","packages/artplayer-plugin-asr/src/index.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 Line truncated
+8
View File
@@ -0,0 +1,8 @@
/*!
* artplayer-plugin-asr.js v2.0.0
* Github: https://github.com/zhw2590582/ArtPlayer
* (c) 2017-2025 Harvey Zack
* Released under the MIT License.
*/
!function(e,t,n,r,o,i,u,l){var a="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof a[r]&&a[r],f=s.i||{},c=s.cache||{},d="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function p(t,n){if(!c[t]){if(!e[t]){if(o[t])return o[t];var i="function"==typeof a[r]&&a[r];if(!n&&i)return i(t,!0);if(s)return s(t,!0);if(d&&"string"==typeof t)return d(t);var u=Error("Cannot find module '"+t+"'");throw u.code="MODULE_NOT_FOUND",u}f.resolve=function(n){var r=e[t][1][n];return null!=r?r:n},f.cache={};var l=c[t]=new p.Module(t);e[t][0].call(l.exports,f,l,l.exports,a)}return c[t].exports;function f(e){var t=f.resolve(e);return!1===t?{}:p(t)}}p.isParcelRequire=!0,p.Module=function(e){this.id=e,this.bundle=p,this.require=d,this.exports={}},p.modules=e,p.cache=c,p.parent=s,p.distDir=void 0,p.publicUrl=void 0,p.devServer=void 0,p.i=f,p.register=function(t,n){e[t]=[function(e,t){t.exports=n},{}]},Object.defineProperty(p,"root",{get:function(){return a[r]}}),a[r]=p;for(var y=0;y<t.length;y++)p(t[y]);if(n){var w=p(n);"object"==typeof exports&&"undefined"!=typeof module?module.exports=w:"function"==typeof define&&define.amd&&define(function(){return w})}}({"1gnQM":[function(e,t,n,r){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");function i(e={}){let{interval:t=5e3,sampleRate:n=16e3,callback:r=()=>null}=e;return e=>{let o=!1,i=null,u=null,l=null,a=[],s=null,f=` 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); `,c=()=>{let e=new Blob([f],{type:"application/javascript"});return URL.createObjectURL(e)};async function d(){if(o)return;o=!0,"suspended"===(i=new(window.AudioContext||window.webkitAudioContext)({sampleRate:n})).state&&await i.resume(),u||(u=i.createMediaElementSource(e.video)).connect(i.destination);let f=c();await i.audioWorklet.addModule(f),URL.revokeObjectURL(f),(l=new AudioWorkletNode(i,"recorder-processor")).port.onmessage=e=>{a.push(new Float32Array(e.data))},u.connect(l).connect(i.destination),s=setInterval(async()=>{if(0===a.length)return;let e=function(e,t){let n=function(e){let t=new Float32Array(e.reduce((e,t)=>e+t.length,0)),n=0;return e.forEach(e=>{t.set(e,n),n+=e.length}),t}(e),r=2*n.length,o=new ArrayBuffer(44+r),i=new DataView(o);function u(e,t){for(let n=0;n<t.length;n++)i.setUint8(e+n,t.charCodeAt(n))}u(0,"RIFF"),i.setUint32(4,36+r,!0),u(8,"WAVE"),u(12,"fmt "),i.setUint32(16,16,!0),i.setUint16(20,1,!0),i.setUint16(22,1,!0),i.setUint32(24,t,!0),i.setUint32(28,2*t,!0),i.setUint16(32,2,!0),i.setUint16(34,16,!0),u(36,"data"),i.setUint32(40,r,!0);let l=function(e){let t=e.length,n=new ArrayBuffer(2*t),r=new DataView(n);for(let n=0;n<t;n++){let t=Math.max(-1,Math.min(1,e[n]));r.setInt16(2*n,t<0?32768*t:32767*t,!0)}return n}(n);return new Uint8Array(o).set(new Uint8Array(l),44),new Blob([i],{type:"audio/wav"})}(a,i.sampleRate),t=await e.arrayBuffer();await r(t),a=[]},t)}function p(){o&&(o=!1,s&&clearInterval(s),l&&l.disconnect(),l=null,a=[])}return e.on("play",d),e.on("pause",p),e.on("destroy",p),{name:"artplayerPluginAsr",destroy:p}}}o.defineInteropFlag(n),o.export(n,"default",()=>i),"undefined"!=typeof window&&(window.artplayerPluginAsr=i)},{"@parcel/transformer-js/src/esmodule-helpers.js":"6ykb1"}],"6ykb1":[function(e,t,n,r){n.interopDefault=function(e){return e&&e.__esModule?e:{default:e}},n.defineInteropFlag=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.exportAll=function(e,t){return Object.keys(e).forEach(function(n){"default"===n||"__esModule"===n||Object.prototype.hasOwnProperty.call(t,n)||Object.defineProperty(t,n,{enumerable:!0,get:function(){return e[n]}})}),t},n.export=function(e,t,n){Object.defineProperty(e,t,{enumerable:!0,get:n})}},{}]},["1gnQM"],"1gnQM","parcelRequire4dc0",{});
@@ -0,0 +1,8 @@
/*!
* artplayer-plugin-asr.js v2.0.0
* Github: https://github.com/zhw2590582/ArtPlayer
* (c) 2017-2025 Harvey Zack
* Released under the MIT License.
*/
!function(e,t,r,n,o,i,u,a){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],f=s.i||{},l=s.cache||{},p="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function d(t,r){if(!l[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 u=Error("Cannot find module '"+t+"'");throw u.code="MODULE_NOT_FOUND",u}f.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},f.cache={};var a=l[t]=new d.Module(t);e[t][0].call(a.exports,f,a,a.exports,c)}return l[t].exports;function f(e){var t=f.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=l,d.parent=s,d.distDir=void 0,d.publicUrl=void 0,d.devServer=void 0,d.i=f,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;y<t.length;y++)d(t[y]);if(r){var _=d(r);"object"==typeof exports&&"undefined"!=typeof module?module.exports=_:"function"==typeof define&&define.amd&&define(function(){return _})}}({"98QZN":[function(e,t,r,n){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");o.defineInteropFlag(r),o.export(r,"default",function(){return a});var i=e("@swc/helpers/cjs/_async_to_generator.cjs"),u=e("@swc/helpers/cjs/_ts_generator.cjs");function a(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.interval,r=void 0===t?5e3:t,n=e.sampleRate,o=void 0===n?16e3:n,a=e.callback,c=void 0===a?function(){return null}:a;return function(e){var t=!1,n=null,a=null,s=null,f=[],l=null,p=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 d(){return(d=(0,i._)(function(){var d;return(0,u._)(this,function(y){switch(y.label){case 0:if(t)return[2];if(t=!0,"suspended"!==(n=new(window.AudioContext||window.webkitAudioContext)({sampleRate:o})).state)return[3,2];return[4,n.resume()];case 1:y.sent(),y.label=2;case 2:return a||(a=n.createMediaElementSource(e.video)).connect(n.destination),d=p(),[4,n.audioWorklet.addModule(d)];case 3:return y.sent(),URL.revokeObjectURL(d),(s=new AudioWorkletNode(n,"recorder-processor")).port.onmessage=function(e){f.push(new Float32Array(e.data))},a.connect(s).connect(n.destination),l=setInterval((0,i._)(function(){return(0,u._)(this,function(e){switch(e.label){case 0:if(0===f.length)return[2];return[4,(function(e,t){var r,n,o=(r=new Float32Array(e.reduce(function(e,t){return e+t.length},0)),n=0,e.forEach(function(e){r.set(e,n),n+=e.length}),r),i=2*o.length,u=new ArrayBuffer(44+i),a=new DataView(u);function c(e,t){for(var r=0;r<t.length;r++)a.setUint8(e+r,t.charCodeAt(r))}c(0,"RIFF"),a.setUint32(4,36+i,!0),c(8,"WAVE"),c(12,"fmt "),a.setUint32(16,16,!0),a.setUint16(20,1,!0),a.setUint16(22,1,!0),a.setUint32(24,t,!0),a.setUint32(28,2*t,!0),a.setUint16(32,2,!0),a.setUint16(34,16,!0),c(36,"data"),a.setUint32(40,i,!0);var s=function(e){for(var t=e.length,r=new ArrayBuffer(2*t),n=new DataView(r),o=0;o<t;o++){var i=Math.max(-1,Math.min(1,e[o]));n.setInt16(2*o,i<0?32768*i:32767*i,!0)}return r}(o);return new Uint8Array(u).set(new Uint8Array(s),44),new Blob([a],{type:"audio/wav"})})(f,n.sampleRate).arrayBuffer()];case 1:return[4,c(e.sent())];case 2:return e.sent(),f=[],[2]}})}),r),[2]}})})).apply(this,arguments)}function y(){t&&(t=!1,l&&clearInterval(l),s&&s.disconnect(),s=null,f=[])}return e.on("play",function(){return d.apply(this,arguments)}),e.on("pause",y),e.on("destroy",y),{name:"artplayerPluginAsr",destroy:y}}}"undefined"!=typeof window&&(window.artplayerPluginAsr=a)},{"@swc/helpers/cjs/_async_to_generator.cjs":"cZn0e","@swc/helpers/cjs/_ts_generator.cjs":"eltGh","@parcel/transformer-js/src/esmodule-helpers.js":"qpMMf"}],cZn0e:[function(e,t,r,n){"use strict";function o(e,t,r,n,o,i,u){try{var a=e[i](u),c=a.value}catch(e){r(e);return}a.done?t(c):Promise.resolve(c).then(n,o)}r._=function(e){return function(){var t=this,r=arguments;return new Promise(function(n,i){var u=e.apply(t,r);function a(e){o(u,n,i,a,c,"next",e)}function c(e){o(u,n,i,a,c,"throw",e)}a(void 0)})}}},{}],eltGh:[function(e,t,r,n){"use strict";r._=e("eb260df52bffddd").__generator},{eb260df52bffddd:"6yrAu"}],"6yrAu":[function(e,t,r,n){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");o.defineInteropFlag(r),o.export(r,"__extends",function(){return a}),o.export(r,"__assign",function(){return c}),o.export(r,"__rest",function(){return s}),o.export(r,"__decorate",function(){return f}),o.export(r,"__param",function(){return l}),o.exLine truncated
+4
View File
@@ -107,6 +107,10 @@
<a
href="/?libs=./uncompiled/artplayer-plugin-ambilight/index.js&example=ambilight">artplayer-plugin-ambilight</a>
</li>
<li>
<a
href="/?libs=./uncompiled/artplayer-plugin-asr/index.js&example=asr">artplayer-plugin-asr</a>
</li>
</ul>
<ul>
<li class="title">Proxys</li>
@@ -0,0 +1,406 @@
// modules are defined as an array
// [ module function, map of requires ]
//
// map of requires is short require name -> numeric require
//
// anything defined in a previous bundle is accessed via the
// orig method which is the require for previous bundles
(function (
modules,
entry,
mainEntry,
parcelRequireName,
externals,
distDir,
publicUrl,
devServer
) {
/* eslint-disable no-undef */
var globalObject =
typeof globalThis !== 'undefined'
? globalThis
: typeof self !== 'undefined'
? self
: typeof window !== 'undefined'
? window
: typeof global !== 'undefined'
? global
: {};
/* eslint-enable no-undef */
// Save the require from previous bundle to this closure if any
var previousRequire =
typeof globalObject[parcelRequireName] === 'function' &&
globalObject[parcelRequireName];
var importMap = previousRequire.i || {};
var cache = previousRequire.cache || {};
// Do not use `require` to prevent Webpack from trying to bundle this call
var nodeRequire =
typeof module !== 'undefined' &&
typeof module.require === 'function' &&
module.require.bind(module);
function newRequire(name, jumped) {
if (!cache[name]) {
if (!modules[name]) {
if (externals[name]) {
return externals[name];
}
// if we cannot find the module within our internal map or
// cache jump to the current global require ie. the last bundle
// that was added to the page.
var currentRequire =
typeof globalObject[parcelRequireName] === 'function' &&
globalObject[parcelRequireName];
if (!jumped && currentRequire) {
return currentRequire(name, true);
}
// If there are other bundles on this page the require from the
// previous one is saved to 'previousRequire'. Repeat this as
// many times as there are bundles until the module is found or
// we exhaust the require chain.
if (previousRequire) {
return previousRequire(name, true);
}
// Try the node require function if it exists.
if (nodeRequire && typeof name === 'string') {
return nodeRequire(name);
}
var err = new Error("Cannot find module '" + name + "'");
err.code = 'MODULE_NOT_FOUND';
throw err;
}
localRequire.resolve = resolve;
localRequire.cache = {};
var module = (cache[name] = new newRequire.Module(name));
modules[name][0].call(
module.exports,
localRequire,
module,
module.exports,
globalObject
);
}
return cache[name].exports;
function localRequire(x) {
var res = localRequire.resolve(x);
return res === false ? {} : newRequire(res);
}
function resolve(x) {
var id = modules[name][1][x];
return id != null ? id : x;
}
}
function Module(moduleName) {
this.id = moduleName;
this.bundle = newRequire;
this.require = nodeRequire;
this.exports = {};
}
newRequire.isParcelRequire = true;
newRequire.Module = Module;
newRequire.modules = modules;
newRequire.cache = cache;
newRequire.parent = previousRequire;
newRequire.distDir = distDir;
newRequire.publicUrl = publicUrl;
newRequire.devServer = devServer;
newRequire.i = importMap;
newRequire.register = function (id, exports) {
modules[id] = [
function (require, module) {
module.exports = exports;
},
{},
];
};
// Only insert newRequire.load when it is actually used.
// The code in this file is linted against ES5, so dynamic import is not allowed.
// INSERT_LOAD_HERE
Object.defineProperty(newRequire, 'root', {
get: function () {
return globalObject[parcelRequireName];
},
});
globalObject[parcelRequireName] = newRequire;
for (var i = 0; i < entry.length; i++) {
newRequire(entry[i]);
}
if (mainEntry) {
// Expose entry point to Node, AMD or browser globals
// Based on https://github.com/ForbesLindesay/umd/blob/master/template.js
var mainExports = newRequire(mainEntry);
// CommonJS
if (typeof exports === 'object' && typeof module !== 'undefined') {
module.exports = mainExports;
// RequireJS
} else if (typeof define === 'function' && define.amd) {
define(function () {
return mainExports;
});
}
}
})({"eiaCd":[function(require,module,exports,__globalThis) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports);
parcelHelpers.export(exports, "default", ()=>artplayerPluginAsr);
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;
return (art)=>{
let started = false;
let audioCtx = null;
let sourceNode = null;
let recorderNode = null;
let gainNode = null;
let bufferChunks = [];
let timer = null;
let workletLoaded = false;
let hideTimer = null;
let mediaStream = null;
let mediaStreamSource = null;
const $asr = art.layers.add({
name: 'asr',
html: ''
});
function splitByPunctuation(text) {
return text.split(/(?<=[、。!?!?\.])\s*/u).map((s)=>s.trim()).filter(Boolean).slice(-length);
}
function hide() {
$asr.style.display = 'none';
}
function append(subtitle) {
if (typeof subtitle !== 'string') return;
clearTimeout(hideTimer);
hideTimer = setTimeout(hide, hideTimeout);
$asr.style.display = '';
$asr.innerHTML = splitByPunctuation(subtitle).map((line)=>`<div class="art-asr-line">${line}</div>`).join('');
}
const recorderProcessorCode = `
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);
`;
const createWorkletBlobUrl = ()=>{
const blob = new Blob([
recorderProcessorCode
], {
type: 'application/javascript'
});
return URL.createObjectURL(blob);
};
function floatTo16BitPCM(float32Array) {
const len = float32Array.length;
const buffer = new ArrayBuffer(len * 2);
const view = new DataView(buffer);
for(let i = 0; i < len; i++){
let s = Math.max(-1, Math.min(1, float32Array[i]));
view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);
}
return buffer;
}
async function setupAudioContext() {
if (audioCtx) return audioCtx;
audioCtx = new (window.AudioContext || window.webkitAudioContext)({
sampleRate
});
if (audioCtx.state === 'suspended') await audioCtx.resume();
return audioCtx;
}
async function setupAudioSource() {
if (!sourceNode && art.video) try {
sourceNode = audioCtx.createMediaElementSource(art.video);
return sourceNode;
} catch (err) {
console.warn('[artplayerPluginAsr] Direct connection failed, trying fallback...', err);
}
try {
if (!mediaStream) mediaStream = await captureAudioFromVideo(art.video);
if (mediaStream) {
mediaStreamSource = audioCtx.createMediaStreamSource(mediaStream);
return mediaStreamSource;
}
} catch (err) {
console.warn('[artplayerPluginAsr] MediaStream fallback failed:', err);
}
return null;
}
async function captureAudioFromVideo(videoElement) {
try {
if (videoElement.captureStream) return videoElement.captureStream();
if (videoElement.mozCaptureStream) return videoElement.mozCaptureStream();
console.warn('[artplayerPluginAsr] captureStream not supported');
return null;
} catch (err) {
console.warn('[artplayerPluginAsr] Error capturing stream:', err);
return null;
}
}
async function startCapture() {
if (started) return;
try {
await setupAudioContext();
const audioSource = await setupAudioSource();
if (!audioSource) throw new Error('Could not establish audio source');
if (!workletLoaded) {
const blobUrl = createWorkletBlobUrl();
await audioCtx.audioWorklet.addModule(blobUrl);
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,避免输出干扰
const CHUNK_SAMPLES = sampleRate * (interval / 1000);
timer = setInterval(async ()=>{
if (bufferChunks.length === 0) return;
let accumulated = new Float32Array(0);
while(accumulated.length < CHUNK_SAMPLES && bufferChunks.length){
const next = bufferChunks.shift();
const tmp = new Float32Array(accumulated.length + next.length);
tmp.set(accumulated, 0);
tmp.set(next, accumulated.length);
accumulated = tmp;
}
if (accumulated.length < CHUNK_SAMPLES) return;
const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES);
const pcm = floatTo16BitPCM(chunkToSend);
const subtitle = await onAudioChunk(pcm);
append(subtitle);
}, interval);
started = true;
} catch (err) {
console.error('[artplayerPluginAsr] Initialization failed:', err);
await stopCapture();
}
}
async function stopCapture() {
if (!started) return;
started = false;
clearInterval(timer);
timer = null;
if (recorderNode) {
recorderNode.disconnect();
recorderNode.port.onmessage = null;
recorderNode = null;
}
if (gainNode) {
gainNode.disconnect();
gainNode = null;
}
bufferChunks = [];
}
async function destroy() {
await stopCapture();
if (mediaStreamSource) {
mediaStreamSource.disconnect();
mediaStreamSource = null;
}
if (sourceNode) {
sourceNode.disconnect();
sourceNode = null;
}
if (mediaStream) {
mediaStream.getTracks().forEach((track)=>track.stop());
mediaStream = null;
}
if (audioCtx) {
await audioCtx.close();
audioCtx = null;
}
workletLoaded = false;
}
art.on('play', startCapture);
art.on('pause', stopCapture);
art.on('destroy', destroy);
return {
name: 'artplayerPluginAsr',
stop: destroy,
hide,
append
};
};
}
if (typeof document !== 'undefined') {
if (!document.getElementById('artplayer-plugin-asr')) {
const $style = document.createElement('style');
$style.id = 'artplayer-plugin-asr';
$style.textContent = (0, _styleLessDefault.default);
document.head.appendChild($style);
}
}
if (typeof window !== 'undefined') window['artplayerPluginAsr'] = artplayerPluginAsr;
},{"bundle-text:./style.less":"enAJa","@parcel/transformer-js/src/esmodule-helpers.js":"8oCsH"}],"enAJa":[function(require,module,exports,__globalThis) {
module.exports = ".art-video-player .art-layer-asr {\n z-index: 150;\n justify-content: end;\n gap: var(--art-subtitle-gap);\n padding: 0 2%;\n padding-bottom: var(--art-subtitle-bottom);\n transition: padding-bottom var(--art-transition-duration) ease;\n 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;\n flex-direction: column;\n font-size: 1rem;\n display: flex;\n position: absolute;\n inset: 0;\n pointer-events: none !important;\n}\n\n.art-video-player.art-control-show .art-layer-asr {\n padding-bottom: calc(var(--art-control-height) + var(--art-subtitle-bottom));\n}\n";
},{}],"8oCsH":[function(require,module,exports,__globalThis) {
exports.interopDefault = function(a) {
return a && a.__esModule ? a : {
default: a
};
};
exports.defineInteropFlag = function(a) {
Object.defineProperty(a, '__esModule', {
value: true
});
};
exports.exportAll = function(source, dest) {
Object.keys(source).forEach(function(key) {
if (key === 'default' || key === '__esModule' || Object.prototype.hasOwnProperty.call(dest, key)) return;
Object.defineProperty(dest, key, {
enumerable: true,
get: function() {
return source[key];
}
});
});
return dest;
};
exports.export = function(dest, destName, get) {
Object.defineProperty(dest, destName, {
enumerable: true,
get: get
});
};
},{}]},["eiaCd"], "eiaCd", "parcelRequire4dc0", {})
//# sourceMappingURL=index.js.map
@@ -0,0 +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 cLine truncated
+10
View File
@@ -0,0 +1,10 @@
node_modules
.DS_Store
yarn.lock
package-lock.json
test
coverage
.nyc_output
.parcel-cache
.cache
docs
+1
View File
@@ -0,0 +1 @@
package-lock=false
+11
View File
@@ -0,0 +1,11 @@
# artplayer-plugin-asr
Ads plugin for ArtPlayer
## Demo
[https://artplayer.org](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-asr/index.js&example=asr)
## License
MIT © Harvey Zack
@@ -0,0 +1,9 @@
/*!
* artplayer-plugin-asr.js v2.0.0
* Github: https://github.com/zhw2590582/ArtPlayer
* (c) 2017-2025 Harvey Zack
* Released under the MIT License.
*/
!function(e,t,n,r,o,i,u,l){var a="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof a[r]&&a[r],d=s.i||{},f=s.cache||{},c="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function p(t,n){if(!f[t]){if(!e[t]){if(o[t])return o[t];var i="function"==typeof a[r]&&a[r];if(!n&&i)return i(t,!0);if(s)return s(t,!0);if(c&&"string"==typeof t)return c(t);var u=Error("Cannot find module '"+t+"'");throw u.code="MODULE_NOT_FOUND",u}d.resolve=function(n){var r=e[t][1][n];return null!=r?r:n},d.cache={};var l=f[t]=new p.Module(t);e[t][0].call(l.exports,d,l,l.exports,a)}return f[t].exports;function d(e){var t=d.resolve(e);return!1===t?{}:p(t)}}p.isParcelRequire=!0,p.Module=function(e){this.id=e,this.bundle=p,this.require=c,this.exports={}},p.modules=e,p.cache=f,p.parent=s,p.distDir=void 0,p.publicUrl=void 0,p.devServer=void 0,p.i=d,p.register=function(t,n){e[t]=[function(e,t){t.exports=n},{}]},Object.defineProperty(p,"root",{get:function(){return a[r]}}),a[r]=p;for(var y=0;y<t.length;y++)p(t[y]);if(n){var w=p(n);"object"==typeof exports&&"undefined"!=typeof module?module.exports=w:"function"==typeof define&&define.amd&&define(function(){return w})}}({"40eeC":[function(e,t,n,r){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");function i(e={}){let{interval:t=5e3,sampleRate:n=16e3,callback:r=()=>null}=e;return e=>{let o=!1,i=null,u=null,l=null,a=[],s=null,d=` 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); `,f=()=>{let e=new Blob([d],{type:"application/javascript"});return URL.createObjectURL(e)};async function c(){if(o)return;o=!0,"suspended"===(i=new(window.AudioContext||window.webkitAudioContext)({sampleRate:n})).state&&await i.resume(),u||(u=i.createMediaElementSource(e.video)).connect(i.destination);let d=f();await i.audioWorklet.addModule(d),URL.revokeObjectURL(d),(l=new AudioWorkletNode(i,"recorder-processor")).port.onmessage=e=>{a.push(new Float32Array(e.data))},u.connect(l).connect(i.destination),s=setInterval(async()=>{if(0===a.length)return;let e=function(e,t){let n=function(e){let t=new Float32Array(e.reduce((e,t)=>e+t.length,0)),n=0;return e.forEach(e=>{t.set(e,n),n+=e.length}),t}(e),r=2*n.length,o=new ArrayBuffer(44+r),i=new DataView(o);function u(e,t){for(let n=0;n<t.length;n++)i.setUint8(e+n,t.charCodeAt(n))}u(0,"RIFF"),i.setUint32(4,36+r,!0),u(8,"WAVE"),u(12,"fmt "),i.setUint32(16,16,!0),i.setUint16(20,1,!0),i.setUint16(22,1,!0),i.setUint32(24,t,!0),i.setUint32(28,2*t,!0),i.setUint16(32,2,!0),i.setUint16(34,16,!0),u(36,"data"),i.setUint32(40,r,!0);let l=function(e){let t=e.length,n=new ArrayBuffer(2*t),r=new DataView(n);for(let n=0;n<t;n++){let t=Math.max(-1,Math.min(1,e[n]));r.setInt16(2*n,t<0?32768*t:32767*t,!0)}return n}(n);return new Uint8Array(o).set(new Uint8Array(l),44),new Blob([i],{type:"audio/wav"})}(a,i.sampleRate),t=await e.arrayBuffer();await r(t),a=[]},t)}function p(){o&&(o=!1,s&&clearInterval(s),l&&l.disconnect(),l=null,a=[])}return e.on("play",c),e.on("pause",p),e.on("destroy",p),{name:"artplayerPluginAsr",destroy:p}}}o.defineInteropFlag(n),o.export(n,"default",()=>i),"undefined"!=typeof window&&(window.artplayerPluginAsr=i)},{"@parcel/transformer-js/src/esmodule-helpers.js":"5lQoW"}],"5lQoW":[function(e,t,n,r){n.interopDefault=function(e){return e&&e.__esModule?e:{default:e}},n.defineInteropFlag=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.exportAll=function(e,t){return Object.keys(e).forEach(function(n){"default"===n||"__esModule"===n||Object.prototype.hasOwnProperty.call(t,n)||Object.defineProperty(t,n,{enumerable:!0,get:function(){return e[n]}})}),t},n.export=function(e,t,n){Object.defineProperty(e,t,{enumerable:!0,get:n})}},{}]},["40eeC"],"40eeC","parcelRequire4dc0",{});let{default:e}=parcelRequire4dc0("40eeC");export{e as default};
//# sourceMappingURL=artplayer-plugin-asr.esm.js.map
@@ -0,0 +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,kDCAe,SAAS,EAAmB,EAAS,CAAC,CAAC,EAClD,GAAM,CAAE,SAAA,EAAW,GAAI,CAAE,WAAA,EAAa,IAAK,CAAE,SAAA,EAAW,IAAM,IAAI,CAAE,CAAG,EAEvE,OAAO,AAAC,IACJ,IAAI,EAAU,CAAA,EACV,EAAW,KACX,EAAa,KACb,EAAe,KACf,EAAe,EAAE,CACjB,EAAQ,KAEN,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,EAwDA,eAAe,IACX,GAAI,EAAS,OACb,EAAU,CAAA,EAIN,AAAmB,cAAnB,AAFJ,CAAA,EAAW,GAAK,CAAA,OAAO,YAAY,EAAI,OAAO,kBAAkB,AAAlB,EAAoB,CAAE,WAAA,CAAW,EAAA,EAElE,KAAK,EACd,MAAM,EAAS,MAAM,GAGpB,GAED,AADA,CAAA,EAAa,EAAS,wBAAwB,CAAC,EAAI,KAAK,CAAA,EAC7C,OAAO,CAAC,EAAS,WAAW,EAG3C,IAAM,EAAU,GAChB,OAAM,EAAS,YAAY,CAAC,SAAS,CAAC,GACtC,IAAI,eAAe,CAAC,GAGpB,AADA,CAAA,EAAe,IAAI,iBAAiB,EAAU,qBAA9C,EACa,IAAI,CAAC,SAAS,CAAG,AAAC,IAC3B,EAAa,IAAI,CAAC,IAAI,aAAa,EAAM,IAAI,EACjD,EAEA,EAAW,OAAO,CAAC,GAAc,OAAO,CAAC,EAAS,WAAW,EAE7D,EAAQ,YAAY,UAChB,GAAI,AAAwB,IAAxB,EAAa,MAAM,CAAQ,OAC/B,IAAM,EAAM,AA5DpB,SAAsB,CAAO,CAAE,CAAU,EACrC,IAAM,EAAU,AAZpB,SAA2B,CAAM,EAE7B,IAAM,EAAS,IAAI,aADJ,EAAO,MAAM,CAAC,CAAC,EAAK,IAAQ,EAAM,EAAI,MAAM,CAAE,IAEzD,EAAS,EAKb,OAJA,EAAO,OAAO,CAAC,AAAC,IACZ,EAAO,GAAG,CAAC,EAAO,GAClB,GAAU,EAAM,MAAM,AAC1B,GACO,CACX,EAGsC,GAC5B,EAAa,AAAiB,EAAjB,EAAQ,MAAM,CAC3B,EAAS,IAAI,YAAY,GAAK,GAC9B,EAAO,IAAI,SAAS,GAE1B,SAAS,EAAS,CAAM,CAAE,CAAG,EACzB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAI,MAAM,CAAE,IAC5B,EAAK,QAAQ,CAAC,EAAS,EAAG,EAAI,UAAU,CAAC,GAEjD,CAEA,EAAS,EAAG,QACZ,EAAK,SAAS,CAAC,EAAG,GAAK,EAAY,CAAA,GACnC,EAAS,EAAG,QACZ,EAAS,GAAI,QACb,EAAK,SAAS,CAAC,GAAI,GAAI,CAAA,GACvB,EAAK,SAAS,CAAC,GAAI,EAAG,CAAA,GACtB,EAAK,SAAS,CAAC,GAAI,EAAG,CAAA,GACtB,EAAK,SAAS,CAAC,GAAI,EAAY,CAAA,GAC/B,EAAK,SAAS,CAAC,GAAI,AAAa,EAAb,EAAgB,CAAA,GACnC,EAAK,SAAS,CAAC,GAAI,EAAG,CAAA,GACtB,EAAK,SAAS,CAAC,GAAI,GAAI,CAAA,GACvB,EAAS,GAAI,QACb,EAAK,SAAS,CAAC,GAAI,EAAY,CAAA,GAE/B,IAAM,EAAM,AAhDhB,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,EAuCgC,GAG5B,OAFA,IAAI,WAAW,GAAQ,GAAG,CAAC,IAAI,WAAW,GAAM,IAEzC,IAAI,KAAK,CAAC,EAAK,CAAE,CAAE,KAAM,WAAY,EAChD,EA8BiC,EAAc,EAAS,UAAU,EACpD,EAAS,MAAM,EAAI,WAAW,EACpC,OAAM,EAAS,GACf,EAAe,EAAE,AACrB,EAAG,EACP,CAEA,SAAS,IACA,IACL,EAAU,CAAA,EACN,GAAO,cAAc,GACrB,GAAc,EAAa,UAAU,GACzC,EAAe,KACf,EAAe,EAAE,CACrB,CAMA,OAJA,EAAI,EAAE,CAAC,OAAQ,GACf,EAAI,EAAE,CAAC,QAAS,GAChB,EAAI,EAAE,CAAC,UAAW,GAEX,CACH,KAAM,qBACN,QAAS,CACb,CACJ,CACJ,C,E,iB,C,GAxIwB,EAAA,MAAA,CAAA,EAAA,UAAA,IAAA,GA0IpB,AAAkB,aAAlB,OAAO,QACP,CAAA,OAAO,kBAAqB,CAAG,CADnC,C,E,C,iD,O,E,C,Q,C,S,C,C,C,C,C,C,C,EC1IA,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":["<anon>","packages/artplayer-plugin-asr/src/index.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 Line truncated
@@ -0,0 +1,8 @@
/*!
* artplayer-plugin-asr.js v2.0.0
* Github: https://github.com/zhw2590582/ArtPlayer
* (c) 2017-2025 Harvey Zack
* Released under the MIT License.
*/
!function(e,t,n,r,o,i,u,l){var a="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof a[r]&&a[r],f=s.i||{},c=s.cache||{},d="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function p(t,n){if(!c[t]){if(!e[t]){if(o[t])return o[t];var i="function"==typeof a[r]&&a[r];if(!n&&i)return i(t,!0);if(s)return s(t,!0);if(d&&"string"==typeof t)return d(t);var u=Error("Cannot find module '"+t+"'");throw u.code="MODULE_NOT_FOUND",u}f.resolve=function(n){var r=e[t][1][n];return null!=r?r:n},f.cache={};var l=c[t]=new p.Module(t);e[t][0].call(l.exports,f,l,l.exports,a)}return c[t].exports;function f(e){var t=f.resolve(e);return!1===t?{}:p(t)}}p.isParcelRequire=!0,p.Module=function(e){this.id=e,this.bundle=p,this.require=d,this.exports={}},p.modules=e,p.cache=c,p.parent=s,p.distDir=void 0,p.publicUrl=void 0,p.devServer=void 0,p.i=f,p.register=function(t,n){e[t]=[function(e,t){t.exports=n},{}]},Object.defineProperty(p,"root",{get:function(){return a[r]}}),a[r]=p;for(var y=0;y<t.length;y++)p(t[y]);if(n){var w=p(n);"object"==typeof exports&&"undefined"!=typeof module?module.exports=w:"function"==typeof define&&define.amd&&define(function(){return w})}}({"1gnQM":[function(e,t,n,r){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");function i(e={}){let{interval:t=5e3,sampleRate:n=16e3,callback:r=()=>null}=e;return e=>{let o=!1,i=null,u=null,l=null,a=[],s=null,f=` 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); `,c=()=>{let e=new Blob([f],{type:"application/javascript"});return URL.createObjectURL(e)};async function d(){if(o)return;o=!0,"suspended"===(i=new(window.AudioContext||window.webkitAudioContext)({sampleRate:n})).state&&await i.resume(),u||(u=i.createMediaElementSource(e.video)).connect(i.destination);let f=c();await i.audioWorklet.addModule(f),URL.revokeObjectURL(f),(l=new AudioWorkletNode(i,"recorder-processor")).port.onmessage=e=>{a.push(new Float32Array(e.data))},u.connect(l).connect(i.destination),s=setInterval(async()=>{if(0===a.length)return;let e=function(e,t){let n=function(e){let t=new Float32Array(e.reduce((e,t)=>e+t.length,0)),n=0;return e.forEach(e=>{t.set(e,n),n+=e.length}),t}(e),r=2*n.length,o=new ArrayBuffer(44+r),i=new DataView(o);function u(e,t){for(let n=0;n<t.length;n++)i.setUint8(e+n,t.charCodeAt(n))}u(0,"RIFF"),i.setUint32(4,36+r,!0),u(8,"WAVE"),u(12,"fmt "),i.setUint32(16,16,!0),i.setUint16(20,1,!0),i.setUint16(22,1,!0),i.setUint32(24,t,!0),i.setUint32(28,2*t,!0),i.setUint16(32,2,!0),i.setUint16(34,16,!0),u(36,"data"),i.setUint32(40,r,!0);let l=function(e){let t=e.length,n=new ArrayBuffer(2*t),r=new DataView(n);for(let n=0;n<t;n++){let t=Math.max(-1,Math.min(1,e[n]));r.setInt16(2*n,t<0?32768*t:32767*t,!0)}return n}(n);return new Uint8Array(o).set(new Uint8Array(l),44),new Blob([i],{type:"audio/wav"})}(a,i.sampleRate),t=await e.arrayBuffer();await r(t),a=[]},t)}function p(){o&&(o=!1,s&&clearInterval(s),l&&l.disconnect(),l=null,a=[])}return e.on("play",d),e.on("pause",p),e.on("destroy",p),{name:"artplayerPluginAsr",destroy:p}}}o.defineInteropFlag(n),o.export(n,"default",()=>i),"undefined"!=typeof window&&(window.artplayerPluginAsr=i)},{"@parcel/transformer-js/src/esmodule-helpers.js":"6ykb1"}],"6ykb1":[function(e,t,n,r){n.interopDefault=function(e){return e&&e.__esModule?e:{default:e}},n.defineInteropFlag=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.exportAll=function(e,t){return Object.keys(e).forEach(function(n){"default"===n||"__esModule"===n||Object.prototype.hasOwnProperty.call(t,n)||Object.defineProperty(t,n,{enumerable:!0,get:function(){return e[n]}})}),t},n.export=function(e,t,n){Object.defineProperty(e,t,{enumerable:!0,get:n})}},{}]},["1gnQM"],"1gnQM","parcelRequire4dc0",{});
@@ -0,0 +1,8 @@
/*!
* artplayer-plugin-asr.js v2.0.0
* Github: https://github.com/zhw2590582/ArtPlayer
* (c) 2017-2025 Harvey Zack
* Released under the MIT License.
*/
!function(e,t,r,n,o,i,u,a){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],f=s.i||{},l=s.cache||{},p="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function d(t,r){if(!l[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 u=Error("Cannot find module '"+t+"'");throw u.code="MODULE_NOT_FOUND",u}f.resolve=function(r){var n=e[t][1][r];return null!=n?n:r},f.cache={};var a=l[t]=new d.Module(t);e[t][0].call(a.exports,f,a,a.exports,c)}return l[t].exports;function f(e){var t=f.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=l,d.parent=s,d.distDir=void 0,d.publicUrl=void 0,d.devServer=void 0,d.i=f,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;y<t.length;y++)d(t[y]);if(r){var _=d(r);"object"==typeof exports&&"undefined"!=typeof module?module.exports=_:"function"==typeof define&&define.amd&&define(function(){return _})}}({"98QZN":[function(e,t,r,n){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");o.defineInteropFlag(r),o.export(r,"default",function(){return a});var i=e("@swc/helpers/cjs/_async_to_generator.cjs"),u=e("@swc/helpers/cjs/_ts_generator.cjs");function a(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.interval,r=void 0===t?5e3:t,n=e.sampleRate,o=void 0===n?16e3:n,a=e.callback,c=void 0===a?function(){return null}:a;return function(e){var t=!1,n=null,a=null,s=null,f=[],l=null,p=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 d(){return(d=(0,i._)(function(){var d;return(0,u._)(this,function(y){switch(y.label){case 0:if(t)return[2];if(t=!0,"suspended"!==(n=new(window.AudioContext||window.webkitAudioContext)({sampleRate:o})).state)return[3,2];return[4,n.resume()];case 1:y.sent(),y.label=2;case 2:return a||(a=n.createMediaElementSource(e.video)).connect(n.destination),d=p(),[4,n.audioWorklet.addModule(d)];case 3:return y.sent(),URL.revokeObjectURL(d),(s=new AudioWorkletNode(n,"recorder-processor")).port.onmessage=function(e){f.push(new Float32Array(e.data))},a.connect(s).connect(n.destination),l=setInterval((0,i._)(function(){return(0,u._)(this,function(e){switch(e.label){case 0:if(0===f.length)return[2];return[4,(function(e,t){var r,n,o=(r=new Float32Array(e.reduce(function(e,t){return e+t.length},0)),n=0,e.forEach(function(e){r.set(e,n),n+=e.length}),r),i=2*o.length,u=new ArrayBuffer(44+i),a=new DataView(u);function c(e,t){for(var r=0;r<t.length;r++)a.setUint8(e+r,t.charCodeAt(r))}c(0,"RIFF"),a.setUint32(4,36+i,!0),c(8,"WAVE"),c(12,"fmt "),a.setUint32(16,16,!0),a.setUint16(20,1,!0),a.setUint16(22,1,!0),a.setUint32(24,t,!0),a.setUint32(28,2*t,!0),a.setUint16(32,2,!0),a.setUint16(34,16,!0),c(36,"data"),a.setUint32(40,i,!0);var s=function(e){for(var t=e.length,r=new ArrayBuffer(2*t),n=new DataView(r),o=0;o<t;o++){var i=Math.max(-1,Math.min(1,e[o]));n.setInt16(2*o,i<0?32768*i:32767*i,!0)}return r}(o);return new Uint8Array(u).set(new Uint8Array(s),44),new Blob([a],{type:"audio/wav"})})(f,n.sampleRate).arrayBuffer()];case 1:return[4,c(e.sent())];case 2:return e.sent(),f=[],[2]}})}),r),[2]}})})).apply(this,arguments)}function y(){t&&(t=!1,l&&clearInterval(l),s&&s.disconnect(),s=null,f=[])}return e.on("play",function(){return d.apply(this,arguments)}),e.on("pause",y),e.on("destroy",y),{name:"artplayerPluginAsr",destroy:y}}}"undefined"!=typeof window&&(window.artplayerPluginAsr=a)},{"@swc/helpers/cjs/_async_to_generator.cjs":"cZn0e","@swc/helpers/cjs/_ts_generator.cjs":"eltGh","@parcel/transformer-js/src/esmodule-helpers.js":"qpMMf"}],cZn0e:[function(e,t,r,n){"use strict";function o(e,t,r,n,o,i,u){try{var a=e[i](u),c=a.value}catch(e){r(e);return}a.done?t(c):Promise.resolve(c).then(n,o)}r._=function(e){return function(){var t=this,r=arguments;return new Promise(function(n,i){var u=e.apply(t,r);function a(e){o(u,n,i,a,c,"next",e)}function c(e){o(u,n,i,a,c,"throw",e)}a(void 0)})}}},{}],eltGh:[function(e,t,r,n){"use strict";r._=e("eb260df52bffddd").__generator},{eb260df52bffddd:"6yrAu"}],"6yrAu":[function(e,t,r,n){var o=e("@parcel/transformer-js/src/esmodule-helpers.js");o.defineInteropFlag(r),o.export(r,"__extends",function(){return a}),o.export(r,"__assign",function(){return c}),o.export(r,"__rest",function(){return s}),o.export(r,"__decorate",function(){return f}),o.export(r,"__param",function(){return l}),o.exLine truncated
@@ -0,0 +1,30 @@
{
"license": "MIT",
"version": "2.0.0",
"name": "artplayer-plugin-asr",
"description": "Asr plugin for ArtPlayer",
"main": "dist/artplayer-plugin-asr.js",
"legacy": "dist/artplayer-plugin-asr.legacy.js",
"module": "dist/artplayer-plugin-asr.esm.js",
"types": "types/artplayer-plugin-asr.d.ts",
"exports": {
"import": "./dist/artplayer-plugin-asr.esm.js",
"require": "./dist/artplayer-plugin-asr.js",
"default": "./dist/artplayer-plugin-asr.js"
},
"author": "Harvey Zack <laozhaochaguan@gmail.com>",
"browserslist": "last 1 Chrome version",
"homepage": "https://artplayer.org",
"repository": {
"type": "git",
"url": "git+https://github.com/zhw2590582/ArtPlayer.git"
},
"bugs": {
"url": "https://github.com/zhw2590582/ArtPlayer/issues"
},
"keywords": [
"html5",
"video",
"player"
]
}
+249
View File
@@ -0,0 +1,249 @@
import style from 'bundle-text:./style.less';
export default function artplayerPluginAsr(option = {}) {
const { hideTimeout = 10000, length = 3, interval = 100, sampleRate = 16000, onAudioChunk = () => null } = option;
return (art) => {
let started = false;
let audioCtx = null;
let sourceNode = null;
let recorderNode = null;
let gainNode = null;
let bufferChunks = [];
let timer = null;
let workletLoaded = false;
let hideTimer = null;
let mediaStream = null;
let mediaStreamSource = null;
const $asr = art.layers.add({
name: 'asr',
html: '',
});
function splitByPunctuation(text) {
return text
.split(/(?<=[、。!?!?\.])\s*/u)
.map((s) => s.trim())
.filter(Boolean)
.slice(-length);
}
function hide() {
$asr.style.display = 'none';
}
function append(subtitle) {
if (typeof subtitle !== 'string') return;
clearTimeout(hideTimer);
hideTimer = setTimeout(hide, hideTimeout);
$asr.style.display = '';
$asr.innerHTML = splitByPunctuation(subtitle)
.map((line) => `<div class="art-asr-line">${line}</div>`)
.join('');
}
const recorderProcessorCode = `
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);
`;
const createWorkletBlobUrl = () => {
const blob = new Blob([recorderProcessorCode], { type: 'application/javascript' });
return URL.createObjectURL(blob);
};
function floatTo16BitPCM(float32Array) {
const len = float32Array.length;
const buffer = new ArrayBuffer(len * 2);
const view = new DataView(buffer);
for (let i = 0; i < len; i++) {
let s = Math.max(-1, Math.min(1, float32Array[i]));
view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true);
}
return buffer;
}
async function setupAudioContext() {
if (audioCtx) return audioCtx;
audioCtx = new (window.AudioContext || window.webkitAudioContext)({ sampleRate });
if (audioCtx.state === 'suspended') await audioCtx.resume();
return audioCtx;
}
async function setupAudioSource() {
if (!sourceNode && art.video) {
try {
sourceNode = audioCtx.createMediaElementSource(art.video);
return sourceNode;
} catch (err) {
console.warn('[artplayerPluginAsr] Direct connection failed, trying fallback...', err);
}
}
try {
if (!mediaStream) {
mediaStream = await captureAudioFromVideo(art.video);
}
if (mediaStream) {
mediaStreamSource = audioCtx.createMediaStreamSource(mediaStream);
return mediaStreamSource;
}
} catch (err) {
console.warn('[artplayerPluginAsr] MediaStream fallback failed:', err);
}
return null;
}
async function captureAudioFromVideo(videoElement) {
try {
if (videoElement.captureStream) return videoElement.captureStream();
if (videoElement.mozCaptureStream) return videoElement.mozCaptureStream();
console.warn('[artplayerPluginAsr] captureStream not supported');
return null;
} catch (err) {
console.warn('[artplayerPluginAsr] Error capturing stream:', err);
return null;
}
}
async function startCapture() {
if (started) return;
try {
await setupAudioContext();
const audioSource = await setupAudioSource();
if (!audioSource) throw new Error('Could not establish audio source');
if (!workletLoaded) {
const blobUrl = createWorkletBlobUrl();
await audioCtx.audioWorklet.addModule(blobUrl);
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,避免输出干扰
const CHUNK_SAMPLES = sampleRate * (interval / 1000);
timer = setInterval(async () => {
if (bufferChunks.length === 0) return;
let accumulated = new Float32Array(0);
while (accumulated.length < CHUNK_SAMPLES && bufferChunks.length) {
const next = bufferChunks.shift();
const tmp = new Float32Array(accumulated.length + next.length);
tmp.set(accumulated, 0);
tmp.set(next, accumulated.length);
accumulated = tmp;
}
if (accumulated.length < CHUNK_SAMPLES) return;
const chunkToSend = accumulated.slice(0, CHUNK_SAMPLES);
const pcm = floatTo16BitPCM(chunkToSend);
const subtitle = await onAudioChunk(pcm);
append(subtitle);
}, interval);
started = true;
} catch (err) {
console.error('[artplayerPluginAsr] Initialization failed:', err);
await stopCapture();
}
}
async function stopCapture() {
if (!started) return;
started = false;
clearInterval(timer);
timer = null;
if (recorderNode) {
recorderNode.disconnect();
recorderNode.port.onmessage = null;
recorderNode = null;
}
if (gainNode) {
gainNode.disconnect();
gainNode = null;
}
bufferChunks = [];
}
async function destroy() {
await stopCapture();
if (mediaStreamSource) {
mediaStreamSource.disconnect();
mediaStreamSource = null;
}
if (sourceNode) {
sourceNode.disconnect();
sourceNode = null;
}
if (mediaStream) {
mediaStream.getTracks().forEach((track) => track.stop());
mediaStream = null;
}
if (audioCtx) {
await audioCtx.close();
audioCtx = null;
}
workletLoaded = false;
}
art.on('play', startCapture);
art.on('pause', stopCapture);
art.on('destroy', destroy);
return {
name: 'artplayerPluginAsr',
stop: destroy,
hide,
append,
};
};
}
if (typeof document !== 'undefined') {
if (!document.getElementById('artplayer-plugin-asr')) {
const $style = document.createElement('style');
$style.id = 'artplayer-plugin-asr';
$style.textContent = style;
document.head.appendChild($style);
}
}
if (typeof window !== 'undefined') {
window['artplayerPluginAsr'] = artplayerPluginAsr;
}
@@ -0,0 +1,31 @@
.art-video-player {
.art-layer-asr {
pointer-events: none !important;
position: absolute;
z-index: 150;
inset: 0px;
display: flex;
flex-direction: column;
justify-content: end;
padding: 0 2%;
font-size: 1rem;
gap: var(--art-subtitle-gap);
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;
}
&.art-control-show {
.art-layer-asr {
padding-bottom: calc(var(--art-control-height) + var(--art-subtitle-bottom));
}
}
}
@@ -0,0 +1,20 @@
import type Artplayer from 'artplayer';
export = artplayerPluginAsr;
export as namespace artplayerPluginAsr;
interface AsrPluginOption {
length?: number;
interval?: number;
sampleRate?: number;
hideTimeout?: number;
onAudioChunk?: (buffer: ArrayBuffer) => void | Promise<void>;
}
interface AsrPluginInstance {
name: 'artplayerPluginAsr';
hide: () => void;
append: () => void;
}
declare function artplayerPluginAsr(option?: AsrPluginOption): (art: Artplayer) => AsrPluginInstance;