@idlebox/browser 0.0.45 → 0.0.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ export declare function downloadBlob(blob: Blob, name: string): void;
2
+ //# sourceMappingURL=download-blob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"download-blob.d.ts","sourceRoot":"","sources":["../../src/binray/download-blob.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAOpD"}
@@ -0,0 +1,9 @@
1
+ export function downloadBlob(blob, name) {
2
+ const url = URL.createObjectURL(blob);
3
+ const a = document.createElement('a');
4
+ a.href = url;
5
+ a.download = name;
6
+ a.click();
7
+ URL.revokeObjectURL(url);
8
+ }
9
+ //# sourceMappingURL=download-blob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"download-blob.js","sourceRoot":"","sources":["../../src/binray/download-blob.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,IAAU,EAAE,IAAY;IACpD,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC;IACb,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC,CAAC,KAAK,EAAE,CAAC;IACV,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC"}
@@ -1,3 +1,6 @@
1
+ /**
2
+ * A class that provides a way to store data with an expiration time. (in localstorage)
3
+ */
1
4
  export declare class TimeoutStorage<T> {
2
5
  private readonly storage;
3
6
  private readonly valueKey;
@@ -9,4 +12,4 @@ export declare class TimeoutStorage<T> {
9
12
  read(defaultVal: Readonly<T>): Readonly<T>;
10
13
  read(): Readonly<T> | undefined;
11
14
  }
12
- //# sourceMappingURL=timeoutStorage.d.ts.map
15
+ //# sourceMappingURL=with-timeout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with-timeout.d.ts","sourceRoot":"","sources":["../../src/storage/with-timeout.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,cAAc,CAAC,CAAC;IAM3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IALzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAGlC,GAAG,EAAE,MAAM,EACM,OAAO,GAAE,OAAsB;IAMjD,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAU7C,MAAM;IAKN,SAAS;IAWT,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;IAC1C,IAAI,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS;CAuB/B"}
@@ -1,3 +1,6 @@
1
+ /**
2
+ * A class that provides a way to store data with an expiration time. (in localstorage)
3
+ */
1
4
  export class TimeoutStorage {
2
5
  storage;
3
6
  valueKey;
@@ -49,4 +52,4 @@ export class TimeoutStorage {
49
52
  }
50
53
  }
51
54
  }
52
- //# sourceMappingURL=timeoutStorage.js.map
55
+ //# sourceMappingURL=with-timeout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with-timeout.js","sourceRoot":"","sources":["../../src/storage/with-timeout.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,cAAc;IAMR;IALD,QAAQ,CAAS;IACjB,SAAS,CAAS;IAEnC,YACC,GAAW,EACM,UAAmB,YAAY;QAA/B,YAAO,GAAP,OAAO,CAAwB;QAEhD,IAAI,CAAC,QAAQ,GAAG,GAAG,GAAG,SAAS,CAAC;QAChC,IAAI,CAAC,SAAS,GAAG,GAAG,GAAG,UAAU,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,IAAiB,EAAE,MAAqB;QAC5C,IAAI,MAAM,YAAY,IAAI,EAAE,CAAC;YAC5B,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QAC/B,CAAC;QAED,2DAA2D;QAC3D,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM;QACL,yCAAyC;QACzC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED,SAAS;QACR,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/C,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;YACpC,0CAA0C;YAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACb,CAAC;QAED,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAKD,IAAI,CAAC,UAAwB;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,CAAC,IAAI,EAAE,CAAC;YACX,OAAO,UAAU,CAAC;QACnB,CAAC;QAED,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/C,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;YACpC,0CAA0C;YAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,OAAO,UAAU,CAAC;QACnB,CAAC;QAED,IAAI,CAAC;YACJ,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,EAAE,EAAE,CAAC;YACb,qDAAqD;YACrD,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,OAAO,UAAU,CAAC;QACnB,CAAC;IACF,CAAC;CACD"}
@@ -0,0 +1,44 @@
1
+ import { type IDisposable } from '@idlebox/common';
2
+ export declare class StreamAppender {
3
+ private readonly stream;
4
+ private readonly dfd;
5
+ private readonly queue;
6
+ private _finished;
7
+ constructor(stream: SourceBuffer);
8
+ private _pump;
9
+ private _error;
10
+ append(buffer: ArrayBuffer): void;
11
+ finish(): void;
12
+ terminate(): void;
13
+ wait(): Promise<void>;
14
+ }
15
+ export declare class MediaForPlayback {
16
+ private readonly mediaSource;
17
+ readonly ready: Promise<void>;
18
+ private readonly endDfd;
19
+ readonly id: number;
20
+ private static guid;
21
+ constructor();
22
+ private opened;
23
+ open(mime: string): Promise<StreamAppender>;
24
+ playToNewAudioElement(): HtmlAudioPlayer;
25
+ finish(): Promise<void>;
26
+ private disList;
27
+ _register(d: IDisposable): void;
28
+ dispose(): void;
29
+ }
30
+ export declare class HtmlAudioPlayer {
31
+ readonly element: HTMLAudioElement;
32
+ private readonly _humanSpeaking;
33
+ readonly onHumanSpeaking: import("@idlebox/common").EventRegister<boolean>;
34
+ constructor();
35
+ private tmr?;
36
+ private aboutToSetSpeaking;
37
+ private speaking;
38
+ private _moveSpeakState;
39
+ private disposed;
40
+ dispose(): void;
41
+ onEnd(fn: () => void): void;
42
+ }
43
+ export declare function disposeAudioElement(audio: HTMLAudioElement): void;
44
+ //# sourceMappingURL=audio-player.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-player.d.ts","sourceRoot":"","sources":["../../src/web-audio/audio-player.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI7E,qBAAa,cAAc;IAKd,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA+B;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,OAAO,CAAC,SAAS,CAAS;gBAEG,MAAM,EAAE,YAAY;IAOjD,OAAO,CAAC,KAAK;IAgBb,OAAO,CAAC,MAAM;IAYd,MAAM,CAAC,MAAM,EAAE,WAAW;IAc1B,MAAM;IAMN,SAAS;IAOT,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAGrB;AAED,qBAAa,gBAAgB;IAC5B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,SAAgB,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IAEtD,SAAgB,EAAE,EAAE,MAAM,CAAC;IAG3B,OAAO,CAAC,MAAM,CAAC,IAAI,CAAK;;IAkBxB,OAAO,CAAC,MAAM,CAAS;IACjB,IAAI,CAAC,IAAI,EAAE,MAAM;IAoBvB,qBAAqB;IAWd,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B,OAAO,CAAC,OAAO,CAAqB;IACpC,SAAS,CAAC,CAAC,EAAE,WAAW;IAIxB,OAAO;CAMP;AAED,qBAAa,eAAe;IAC3B,SAAgB,OAAO,EAAE,gBAAgB,CAAC;IAE1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0B;IACzD,SAAgB,eAAe,mDAA6B;;IA4B5D,OAAO,CAAC,GAAG,CAAC,CAAS;IACrB,OAAO,CAAC,kBAAkB;IAiB1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO;IAaP,KAAK,CAAC,EAAE,EAAE,MAAM,IAAI;CAWpB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,QAO1D"}
@@ -0,0 +1,242 @@
1
+ import { DeferredPromise, Emitter } from '@idlebox/common';
2
+ const DELAY_CLOSE_MOUTH = 700;
3
+ export class StreamAppender {
4
+ stream;
5
+ dfd = new DeferredPromise();
6
+ queue = [];
7
+ _finished = false;
8
+ constructor(stream) {
9
+ this.stream = stream;
10
+ stream.mode = 'sequence';
11
+ stream.addEventListener('updateend', this._pump.bind(this));
12
+ stream.addEventListener('error', this._error.bind(this));
13
+ }
14
+ _pump() {
15
+ // console.log('[stream] pump %s', this.queue.length);
16
+ if (this.stream.updating) {
17
+ // console.error(' - busy');
18
+ return;
19
+ }
20
+ const next = this.queue.shift();
21
+ if (next) {
22
+ // console.log('playing %s bytes', next.byteLength);
23
+ this.stream.appendBuffer(next);
24
+ }
25
+ else if (this._finished) {
26
+ // console.log('StreamAppender: dispose');
27
+ this.dfd.complete();
28
+ }
29
+ }
30
+ _error(e) {
31
+ // console.log('[stream] pump fail', e);
32
+ this.queue.length = 0;
33
+ this.finish();
34
+ const err = e.error;
35
+ if (!(err instanceof Error)) {
36
+ console.error('e似乎不是ErrorEvent', e);
37
+ }
38
+ this.dfd.error(err);
39
+ }
40
+ append(buffer) {
41
+ if (this._finished) {
42
+ throw new Error('不能在finish之后append');
43
+ }
44
+ this.queue.push(buffer);
45
+ if (!this.stream.updating) {
46
+ // console.log('[stream] pump start');
47
+ this._pump();
48
+ }
49
+ else {
50
+ // console.log('[stream] queue data');
51
+ }
52
+ }
53
+ finish() {
54
+ // console.log('[stream] done.');
55
+ this._finished = true;
56
+ this._pump();
57
+ }
58
+ terminate() {
59
+ // console.log('[stream] done. (terminate)');
60
+ this._finished = true;
61
+ this.queue.length = 0;
62
+ this._pump();
63
+ }
64
+ wait() {
65
+ return this.dfd.p;
66
+ }
67
+ }
68
+ export class MediaForPlayback {
69
+ mediaSource;
70
+ ready;
71
+ endDfd = new DeferredPromise();
72
+ id;
73
+ // biome-ignore lint/correctness/noUnusedPrivateClassMembers: bug
74
+ static guid = 0;
75
+ constructor() {
76
+ this.id = ++MediaForPlayback.guid;
77
+ // console.log('[media source %d] create', this.id);
78
+ const source = new window.MediaSource();
79
+ this.ready = new Promise((resolve) => {
80
+ const wrap = () => {
81
+ source.removeEventListener('sourceopen', wrap);
82
+ // console.log('[media source %d] sourceopen', this.id);
83
+ resolve();
84
+ };
85
+ source.addEventListener('sourceopen', wrap);
86
+ });
87
+ this.mediaSource = source;
88
+ }
89
+ opened = false;
90
+ async open(mime) {
91
+ if (this.opened)
92
+ throw new Error('duplicate call to MediaForPlayback.open()');
93
+ this.opened = true;
94
+ // console.log('[media source %d] open', this.id, mime);
95
+ await this.ready;
96
+ const buffer = this.mediaSource.addSourceBuffer(mime);
97
+ const appender = new StreamAppender(buffer);
98
+ appender.wait().finally(() => {
99
+ // console.log('[media source %d] appender finished', this.id);
100
+ this.mediaSource.endOfStream();
101
+ this.endDfd.complete();
102
+ this.dispose();
103
+ });
104
+ return appender;
105
+ }
106
+ playToNewAudioElement() {
107
+ const audio = new HtmlAudioPlayer();
108
+ audio.onEnd(() => {
109
+ this.dispose();
110
+ });
111
+ audio.element.src = URL.createObjectURL(this.mediaSource);
112
+ return audio;
113
+ }
114
+ finish() {
115
+ return this.endDfd.p;
116
+ }
117
+ disList = [];
118
+ _register(d) {
119
+ this.disList.push(d);
120
+ }
121
+ dispose() {
122
+ // console.log('[media source %d] dispose()', this.id);
123
+ for (const obj of this.disList) {
124
+ obj.dispose();
125
+ }
126
+ }
127
+ }
128
+ export class HtmlAudioPlayer {
129
+ element;
130
+ _humanSpeaking = new Emitter();
131
+ onHumanSpeaking = this._humanSpeaking.event;
132
+ constructor() {
133
+ const audio = new Audio();
134
+ this.element = audio;
135
+ // for (const n of mdevents) {
136
+ // audio.addEventListener(n, () => {
137
+ // console.log('[audio] event: %s', n);
138
+ // });
139
+ // }
140
+ audio.addEventListener('ended', () => {
141
+ this.dispose();
142
+ });
143
+ audio.addEventListener('canplay', () => {
144
+ this.aboutToSetSpeaking(true);
145
+ });
146
+ audio.addEventListener('pause', () => {
147
+ this.aboutToSetSpeaking(false);
148
+ });
149
+ audio.addEventListener('waiting', () => {
150
+ this.aboutToSetSpeaking(false, DELAY_CLOSE_MOUTH / 2);
151
+ });
152
+ audio.autoplay = true;
153
+ }
154
+ tmr;
155
+ aboutToSetSpeaking(target, timeout = DELAY_CLOSE_MOUTH) {
156
+ if (this.tmr) {
157
+ clearTimeout(this.tmr);
158
+ this.tmr = 0;
159
+ }
160
+ if (target) {
161
+ this._moveSpeakState(true);
162
+ }
163
+ else {
164
+ this.tmr = setTimeout(() => {
165
+ this.tmr = 0;
166
+ this._moveSpeakState(false);
167
+ }, timeout);
168
+ }
169
+ }
170
+ speaking = false;
171
+ _moveSpeakState(target) {
172
+ if (this.speaking === target)
173
+ return;
174
+ this.speaking = target;
175
+ // console.log('human-speaking:', target);
176
+ this._humanSpeaking.fireNoError(this.speaking);
177
+ if (this.disposed) {
178
+ this._humanSpeaking.dispose();
179
+ }
180
+ }
181
+ disposed = false;
182
+ dispose() {
183
+ // console.log('HtmlAudioPlayer: dispose');
184
+ this.disposed = true;
185
+ disposeAudioElement(this.element);
186
+ if (this.speaking) {
187
+ this.aboutToSetSpeaking(false);
188
+ }
189
+ else {
190
+ this._humanSpeaking.dispose();
191
+ }
192
+ }
193
+ onEnd(fn) {
194
+ if (this.element.ended) {
195
+ fn();
196
+ }
197
+ else {
198
+ const once = () => {
199
+ fn();
200
+ this.element.removeEventListener('ended', once);
201
+ };
202
+ this.element.addEventListener('ended', once);
203
+ }
204
+ }
205
+ }
206
+ export function disposeAudioElement(audio) {
207
+ if (!audio.ended && !('__my_end' in audio)) {
208
+ Object.assign(audio, { __my_end: true });
209
+ const ee = new Event('ended');
210
+ Object.assign(ee, { error: new Error('canceled') });
211
+ audio.dispatchEvent(ee);
212
+ }
213
+ }
214
+ // @ts-ignore
215
+ // biome-ignore lint/correctness/noUnusedVariables: debug
216
+ const mdevents = [
217
+ 'abort',
218
+ 'canplay',
219
+ 'canplaythrough',
220
+ 'durationchange',
221
+ 'emptied',
222
+ 'encrypted',
223
+ 'ended',
224
+ 'error',
225
+ 'loadeddata',
226
+ 'loadedmetadata',
227
+ 'loadstart',
228
+ 'pause',
229
+ 'play',
230
+ 'playing',
231
+ 'progress',
232
+ 'ratechange',
233
+ 'seeked',
234
+ 'seeking',
235
+ 'stalled',
236
+ 'suspend',
237
+ 'timeupdate',
238
+ 'volumechange',
239
+ 'waiting',
240
+ 'waitingforkey',
241
+ ];
242
+ //# sourceMappingURL=audio-player.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-player.js","sourceRoot":"","sources":["../../src/web-audio/audio-player.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import { DuplicateDisposeAction, EnhancedDisposable, type EventRegister } from '@idlebox/common';
2
+ interface IRecorder {
3
+ onDataAvailable: EventRegister<Uint8Array<ArrayBuffer>>;
4
+ onFinished: EventRegister<void>;
5
+ dispose(): void;
6
+ }
7
+ /**
8
+ * TODO: 新api要求使用webworker 这里模拟worker
9
+ */
10
+ export declare class RawPcmStreamNode extends EnhancedDisposable implements IRecorder {
11
+ private readonly audioContext;
12
+ private readonly bitDepth;
13
+ private readonly latency;
14
+ protected duplicateDispose: DuplicateDisposeAction;
15
+ private readonly _onDataAvailable;
16
+ readonly onDataAvailable: EventRegister<Uint8Array<ArrayBuffer>>;
17
+ /**
18
+ * 由于AudioNode没有类似end的事件,只能用延迟模拟一个
19
+ */
20
+ private readonly _onFinished;
21
+ readonly onFinished: EventRegister<void>;
22
+ /**
23
+ * 被要求结束后,只有连续没有收到音频,才真正触发 onFinished
24
+ * 这和决定录音何时结束无关
25
+ */
26
+ private readonly willFinish;
27
+ private _node?;
28
+ constructor(audioContext: AudioContext, bitDepth?: number, latency?: number);
29
+ get bufferSize(): number;
30
+ private _getNode;
31
+ connectFrom(source: AudioNode): void;
32
+ /**
33
+ * 外部不要调用
34
+ *
35
+ * 优雅结束
36
+ * @private
37
+ */
38
+ shutdown(): void;
39
+ }
40
+ export declare class RawPcmStreamRecorder extends EnhancedDisposable {
41
+ readonly bitDepth: number;
42
+ readonly sampleRate: number;
43
+ protected duplicateDispose: DuplicateDisposeAction;
44
+ private readonly channels;
45
+ private readonly dfd;
46
+ constructor(bitDepth?: number, sampleRate?: number);
47
+ get context(): AudioContext;
48
+ private started?;
49
+ /**
50
+ * 开始录音(可以重复调用,返回相同)
51
+ * stop之后不能重新start
52
+ */
53
+ startRecording(latency?: number): Promise<IRecorder>;
54
+ private _microphone?;
55
+ private _analyze?;
56
+ private _recorder?;
57
+ _startRecording(latency: number): Promise<RawPcmStreamNode>;
58
+ private caclculateVolume;
59
+ getPromise(): Promise<void> & import("@idlebox/common").IProgressHolder<void, any>;
60
+ private hasClosed;
61
+ private close_microphone;
62
+ stopRecording(): Promise<void>;
63
+ }
64
+ export {};
65
+ //# sourceMappingURL=pcm-recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pcm-recorder.d.ts","sourceRoot":"","sources":["../../src/web-audio/pcm-recorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,sBAAsB,EAEtB,kBAAkB,EAGlB,KAAK,aAAa,EAClB,MAAM,iBAAiB,CAAC;AAOzB,UAAU,SAAS;IAClB,eAAe,EAAE,aAAa,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IACxD,UAAU,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,OAAO,IAAI,IAAI,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,kBAAmB,YAAW,SAAS;IAqB3E,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAtBzB,UAAmB,gBAAgB,yBAAgC;IAEnE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0C;IAC3E,SAAgB,eAAe,yCAA+B;IAE9D;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,SAAgB,UAAU,sBAA0B;IAEpD;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkB;IAE7C,OAAO,CAAC,KAAK,CAAC,CAAsB;gBAGlB,YAAY,EAAE,YAAY,EAC1B,QAAQ,SAAK,EACb,OAAO,SAAM;IAqB/B,IAAI,UAAU,WAEb;IAED,OAAO,CAAC,QAAQ;IAoBhB,WAAW,CAAC,MAAM,EAAE,SAAS;IAI7B;;;;;OAKG;IACH,QAAQ;CAIR;AAED,qBAAa,oBAAqB,SAAQ,kBAAkB;aAO1C,QAAQ;aACR,UAAU;IAP3B,UAAmB,gBAAgB,yBAAgC;IAEnE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAK;IAC9B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA+B;gBAGlC,QAAQ,SAAK,EACb,UAAU,SAAQ;IAKnC,IAAI,OAAO,IAAI,YAAY,CAoB1B;IAED,OAAO,CAAC,OAAO,CAAC,CAA4B;IAE5C;;;OAGG;IACH,cAAc,CAAC,OAAO,GAAE,MAAY,GAAG,OAAO,CAAC,SAAS,CAAC;IAWzD,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,CAAe;IAChC,OAAO,CAAC,SAAS,CAAC,CAAmB;IAC/B,eAAe,CAAC,OAAO,EAAE,MAAM;IA4CrC,OAAO,CAAC,gBAAgB;IAexB,UAAU;IAIV,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,gBAAgB;IAkBlB,aAAa;CAenB"}
@@ -0,0 +1,226 @@
1
+ import { closableToDisposable, DeferredPromise, definePublicConstant, DuplicateDisposeAction, Emitter, EnhancedDisposable, ExtendableTimer, sleep, } from '@idlebox/common';
2
+ /**
3
+ * TODO: need a logger
4
+ */
5
+ const logger = console;
6
+ /**
7
+ * TODO: 新api要求使用webworker 这里模拟worker
8
+ */
9
+ export class RawPcmStreamNode extends EnhancedDisposable {
10
+ audioContext;
11
+ bitDepth;
12
+ latency;
13
+ duplicateDispose = DuplicateDisposeAction.Allow;
14
+ _onDataAvailable = new Emitter();
15
+ onDataAvailable = this._onDataAvailable.event;
16
+ /**
17
+ * 由于AudioNode没有类似end的事件,只能用延迟模拟一个
18
+ */
19
+ _onFinished = new Emitter();
20
+ onFinished = this._onFinished.event;
21
+ /**
22
+ * 被要求结束后,只有连续没有收到音频,才真正触发 onFinished
23
+ * 这和决定录音何时结束无关
24
+ */
25
+ willFinish;
26
+ _node;
27
+ constructor(audioContext, bitDepth = 16, latency = 150) {
28
+ super();
29
+ this.audioContext = audioContext;
30
+ this.bitDepth = bitDepth;
31
+ this.latency = latency;
32
+ this.willFinish = new ExtendableTimer(latency * 2);
33
+ this.willFinish.onSchedule(() => {
34
+ logger.debug('连续没有收到音频,录制正确结束');
35
+ this._onFinished.fireNoError();
36
+ this.dispose();
37
+ });
38
+ this.onPostDispose(() => {
39
+ this._onFinished.dispose();
40
+ if (this._node) {
41
+ this._node.disconnect();
42
+ this._node = undefined;
43
+ }
44
+ this.willFinish.cancel();
45
+ this._onDataAvailable.dispose();
46
+ });
47
+ }
48
+ get bufferSize() {
49
+ return calculateBufferSize(this.latency, this.audioContext.sampleRate, 1, this.bitDepth);
50
+ }
51
+ _getNode() {
52
+ if (!this._node) {
53
+ this._node = this.audioContext.createScriptProcessor(this.bufferSize, 1, 1);
54
+ logger.debug(`创建新的stream-node: buffer size = %s`, this.bufferSize);
55
+ }
56
+ this._node.onaudioprocess = (event) => {
57
+ this.willFinish.renew();
58
+ const rawPcmData = event.inputBuffer.getChannelData(0);
59
+ logger.debug('~ script process data %s frames', event.inputBuffer.length);
60
+ const buff = float32_sint16(rawPcmData);
61
+ this._onDataAvailable.fireNoError(new Uint8Array(buff.buffer));
62
+ };
63
+ // 实际无用,但没有目标就不产生事件
64
+ this._node.connect(this.audioContext.destination);
65
+ return this._node;
66
+ }
67
+ connectFrom(source) {
68
+ source.connect(this._getNode());
69
+ }
70
+ /**
71
+ * 外部不要调用
72
+ *
73
+ * 优雅结束
74
+ * @private
75
+ */
76
+ shutdown() {
77
+ logger.debug('即将结束录制过程');
78
+ this.willFinish.start();
79
+ }
80
+ }
81
+ export class RawPcmStreamRecorder extends EnhancedDisposable {
82
+ bitDepth;
83
+ sampleRate;
84
+ duplicateDispose = DuplicateDisposeAction.Allow;
85
+ channels = 1;
86
+ dfd = new DeferredPromise();
87
+ constructor(bitDepth = 16, sampleRate = 16000) {
88
+ super();
89
+ this.bitDepth = bitDepth;
90
+ this.sampleRate = sampleRate;
91
+ }
92
+ get context() {
93
+ logger.debug('creating new audio context');
94
+ const context = new AudioContext({ sampleRate: this.sampleRate });
95
+ context.addEventListener('statechange', () => {
96
+ if (context.state === 'closed' && !this.hasDisposed) {
97
+ this.dispose();
98
+ }
99
+ });
100
+ definePublicConstant(this, 'context', context);
101
+ this._register(closableToDisposable(context));
102
+ this.onBeforeDispose(() => {
103
+ if (!this.dfd.settled)
104
+ this.dfd.error(new Error('录制操作中断'));
105
+ this.started = undefined;
106
+ this.close_microphone(0);
107
+ });
108
+ return context;
109
+ }
110
+ started;
111
+ /**
112
+ * 开始录音(可以重复调用,返回相同)
113
+ * stop之后不能重新start
114
+ */
115
+ startRecording(latency = 150) {
116
+ if (this.disposed || this.hasClosed) {
117
+ throw new Error('recorder is already finished');
118
+ }
119
+ if (!this.started) {
120
+ this.started = this._startRecording(latency);
121
+ }
122
+ return this.started;
123
+ }
124
+ _microphone;
125
+ _analyze;
126
+ _recorder;
127
+ async _startRecording(latency) {
128
+ logger.debug('启动录音,缓冲 %sms', latency);
129
+ const microphone = await navigator.mediaDevices
130
+ .getUserMedia({
131
+ video: false,
132
+ audio: {
133
+ sampleRate: this.sampleRate,
134
+ channelCount: this.channels,
135
+ sampleSize: this.bitDepth,
136
+ echoCancellation: true,
137
+ noiseSuppression: true,
138
+ autoGainControl: true,
139
+ },
140
+ })
141
+ .catch((e) => {
142
+ this.dfd.error(e);
143
+ throw e;
144
+ });
145
+ const streamNode = this.context.createMediaStreamSource(microphone);
146
+ for (const item of microphone.getAudioTracks()) {
147
+ item.addEventListener('ended', () => {
148
+ logger.warn('麦克风由于外部原因停止');
149
+ this.close_microphone(0);
150
+ });
151
+ }
152
+ this._microphone = microphone;
153
+ const recorder = new RawPcmStreamNode(this.context, this.bitDepth, latency);
154
+ this._recorder = recorder;
155
+ recorder.connectFrom(streamNode);
156
+ recorder.onFinished(() => {
157
+ this.dfd.complete();
158
+ });
159
+ const analyze = this.context.createAnalyser();
160
+ this._analyze = analyze;
161
+ streamNode.connect(analyze);
162
+ return recorder;
163
+ }
164
+ caclculateVolume() {
165
+ if (!this._analyze)
166
+ return 0;
167
+ const bufferLength = this._analyze.frequencyBinCount;
168
+ const dataArray = new Uint8Array(bufferLength);
169
+ this._analyze.getByteFrequencyData(dataArray);
170
+ let sum = 0;
171
+ for (const amplitude of dataArray) {
172
+ sum += amplitude * amplitude;
173
+ }
174
+ return Math.sqrt(sum / dataArray.length);
175
+ }
176
+ getPromise() {
177
+ return this.dfd.p;
178
+ }
179
+ hasClosed = false;
180
+ close_microphone(delay) {
181
+ if (this.hasClosed)
182
+ return;
183
+ this.hasClosed = true;
184
+ logger.debug('程序主动关闭麦克风 | 延迟 %sms', delay);
185
+ sleep(delay).then(() => {
186
+ if (this._microphone) {
187
+ // 其实只有一个
188
+ for (const item of this._microphone.getAudioTracks()) {
189
+ item.stop();
190
+ this._microphone.removeTrack(item);
191
+ }
192
+ }
193
+ if (this._recorder)
194
+ this._recorder.shutdown();
195
+ });
196
+ }
197
+ async stopRecording() {
198
+ const volume = this.caclculateVolume();
199
+ // 不知道是否合适
200
+ const delay = (1000 * volume) / 60;
201
+ this.close_microphone(delay);
202
+ return new Promise((resolve, reject) => {
203
+ if (!this._recorder)
204
+ return resolve();
205
+ this._recorder.onBeforeDispose(resolve);
206
+ this._recorder.onBeforeDispose(() => reject(new Error('录制操作非正常中断')));
207
+ });
208
+ }
209
+ }
210
+ function calculateBufferSize(milliseconds, sampleRate, channels, bits) {
211
+ const rawSize = Math.floor((milliseconds / 1000) * sampleRate * channels * (bits / 8));
212
+ // 返回大于rawSize的最接近的2的幂
213
+ const near = 2 ** Math.ceil(Math.log2(rawSize));
214
+ return Math.max(256, Math.min(16384, near));
215
+ }
216
+ function float32_sint16(input) {
217
+ // 将Float32Array转换为Int16Array
218
+ const output = new Int16Array(input.length);
219
+ for (let i = 0; i < input.length; i++) {
220
+ let s = input[i];
221
+ s = Math.max(-1, Math.min(1, s));
222
+ output[i] = s < 0 ? s * 0x8000 : s * 0x7fff;
223
+ }
224
+ return output;
225
+ }
226
+ //# sourceMappingURL=pcm-recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pcm-recorder.js","sourceRoot":"","sources":["../../src/web-audio/pcm-recorder.ts"],"names":[],"mappings":"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"}