videomail-client 16.2.0 → 16.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -5
- package/dist/cjs/index.cjs +278 -108
- package/dist/esm/index.js +221 -71
- package/dist/esm/util/html/media/AudioRecorder.d.ts +19 -9
- package/dist/esm/util/html/media/AudioRecorderWorklet.d.ts +17 -0
- package/dist/umd/index.js +268 -96
- package/package.json +9 -9
package/dist/esm/index.js
CHANGED
|
@@ -3620,7 +3620,7 @@ const constants = {
|
|
|
3620
3620
|
}
|
|
3621
3621
|
};
|
|
3622
3622
|
var package_namespaceObject = {
|
|
3623
|
-
rE: "16.
|
|
3623
|
+
rE: "16.4.0"
|
|
3624
3624
|
};
|
|
3625
3625
|
function isAudioEnabled(options) {
|
|
3626
3626
|
return Boolean(options.audio.enabled);
|
|
@@ -7740,6 +7740,49 @@ const MEDIA_EVENTS = [
|
|
|
7740
7740
|
"volumechange"
|
|
7741
7741
|
];
|
|
7742
7742
|
const mediaEvents = MEDIA_EVENTS;
|
|
7743
|
+
const AUDIO_RECORDER_PROCESSOR_NAME = "videomail-pcm-recorder";
|
|
7744
|
+
function registerAudioRecorderProcessor(name, Processor, register) {
|
|
7745
|
+
class PcmRecorderProcessor extends Processor {
|
|
7746
|
+
process(inputs) {
|
|
7747
|
+
if (this.recordingId < 0) return false;
|
|
7748
|
+
const channel = inputs[0]?.[0];
|
|
7749
|
+
if (!channel || 0 === this.recordingId) return true;
|
|
7750
|
+
let inputOffset = 0;
|
|
7751
|
+
while(inputOffset < channel.length){
|
|
7752
|
+
const count = Math.min(this.samples.length - this.offset, channel.length - inputOffset);
|
|
7753
|
+
this.samples.set(channel.subarray(inputOffset, inputOffset + count), this.offset);
|
|
7754
|
+
this.offset += count;
|
|
7755
|
+
inputOffset += count;
|
|
7756
|
+
if (this.offset === this.samples.length) {
|
|
7757
|
+
const samples = this.samples;
|
|
7758
|
+
this.port.postMessage({
|
|
7759
|
+
recordingId: this.recordingId,
|
|
7760
|
+
samples
|
|
7761
|
+
}, [
|
|
7762
|
+
samples.buffer
|
|
7763
|
+
]);
|
|
7764
|
+
this.samples = new Float32Array(this.offset);
|
|
7765
|
+
this.offset = 0;
|
|
7766
|
+
}
|
|
7767
|
+
}
|
|
7768
|
+
return true;
|
|
7769
|
+
}
|
|
7770
|
+
constructor(options){
|
|
7771
|
+
super();
|
|
7772
|
+
this.samples = new Float32Array(options.processorOptions.bufferSize);
|
|
7773
|
+
this.offset = 0;
|
|
7774
|
+
this.recordingId = 0;
|
|
7775
|
+
this.port.onmessage = (event)=>{
|
|
7776
|
+
const recordingId = event.data;
|
|
7777
|
+
if ("number" != typeof recordingId) return;
|
|
7778
|
+
if (!Number.isSafeInteger(recordingId) || recordingId < -1) return;
|
|
7779
|
+
this.recordingId = recordingId;
|
|
7780
|
+
this.offset = 0;
|
|
7781
|
+
};
|
|
7782
|
+
}
|
|
7783
|
+
}
|
|
7784
|
+
register(name, PcmRecorderProcessor);
|
|
7785
|
+
}
|
|
7743
7786
|
function AudioRecorder_define_property(obj, key, value) {
|
|
7744
7787
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
7745
7788
|
value: value,
|
|
@@ -7751,40 +7794,113 @@ function AudioRecorder_define_property(obj, key, value) {
|
|
|
7751
7794
|
return obj;
|
|
7752
7795
|
}
|
|
7753
7796
|
const CHANNELS = 1;
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
class AudioRecorder {
|
|
7758
|
-
hasAudioContext() {
|
|
7759
|
-
return Boolean(getAudioContextClass()) && Boolean(this.getAudioContext());
|
|
7760
|
-
}
|
|
7797
|
+
const DEFAULT_BUFFER_SIZE = 2048;
|
|
7798
|
+
const MIN_BUFFER_SIZE = 256;
|
|
7799
|
+
const MAX_BUFFER_SIZE = 16384;
|
|
7800
|
+
class AudioRecorder extends util_Despot {
|
|
7761
7801
|
getAudioContext() {
|
|
7762
|
-
if (!this.vcAudioContext)
|
|
7763
|
-
const AudioContext = getAudioContextClass();
|
|
7764
|
-
this.vcAudioContext = new AudioContext();
|
|
7765
|
-
}
|
|
7802
|
+
if (!this.vcAudioContext) this.vcAudioContext = new window.AudioContext();
|
|
7766
7803
|
return this.vcAudioContext;
|
|
7767
7804
|
}
|
|
7768
|
-
|
|
7805
|
+
getBufferSize() {
|
|
7806
|
+
const configuredSize = this.options.audio.bufferSize;
|
|
7807
|
+
const bufferSize = "auto" === configuredSize ? DEFAULT_BUFFER_SIZE : configuredSize;
|
|
7808
|
+
if (void 0 === bufferSize) throw error_createError({
|
|
7809
|
+
message: "Audio buffer size is required.",
|
|
7810
|
+
options: this.options
|
|
7811
|
+
});
|
|
7812
|
+
const validBufferSize = Number.isInteger(bufferSize) && bufferSize >= MIN_BUFFER_SIZE && bufferSize <= MAX_BUFFER_SIZE && is_power_of_two(bufferSize);
|
|
7813
|
+
if (!validBufferSize) throw error_createError({
|
|
7814
|
+
message: `Audio buffer size must be a power of two between ${MIN_BUFFER_SIZE} and ${MAX_BUFFER_SIZE}. The current buffer size is ${bufferSize}.`,
|
|
7815
|
+
options: this.options
|
|
7816
|
+
});
|
|
7817
|
+
return bufferSize;
|
|
7818
|
+
}
|
|
7819
|
+
validateVolume() {
|
|
7820
|
+
const { volume } = this.options.audio;
|
|
7821
|
+
const validVolume = Number.isFinite(volume) && volume >= 0 && volume <= 1;
|
|
7822
|
+
if (!validVolume) throw error_createError({
|
|
7823
|
+
message: `Audio volume must be between zero and one. The current volume is ${volume}.`,
|
|
7824
|
+
options: this.options
|
|
7825
|
+
});
|
|
7826
|
+
}
|
|
7827
|
+
revokeModuleUrl() {
|
|
7828
|
+
if (this.moduleUrl) {
|
|
7829
|
+
URL.revokeObjectURL(this.moduleUrl);
|
|
7830
|
+
this.moduleUrl = void 0;
|
|
7831
|
+
}
|
|
7832
|
+
}
|
|
7833
|
+
async loadWorklet(context) {
|
|
7834
|
+
const source = `(${registerAudioRecorderProcessor.toString()})(${JSON.stringify(AUDIO_RECORDER_PROCESSOR_NAME)}, AudioWorkletProcessor, registerProcessor);`;
|
|
7835
|
+
const moduleUrl = URL.createObjectURL(new Blob([
|
|
7836
|
+
source
|
|
7837
|
+
], {
|
|
7838
|
+
type: "text/javascript"
|
|
7839
|
+
}));
|
|
7840
|
+
this.moduleUrl = moduleUrl;
|
|
7841
|
+
try {
|
|
7842
|
+
await context.audioWorklet.addModule(moduleUrl);
|
|
7843
|
+
} finally{
|
|
7844
|
+
if (this.moduleUrl === moduleUrl) this.revokeModuleUrl();
|
|
7845
|
+
}
|
|
7846
|
+
}
|
|
7847
|
+
onAudioProcess(event) {
|
|
7848
|
+
const callback = this.audioCallback;
|
|
7849
|
+
if (!callback) return;
|
|
7769
7850
|
if (!this.userMedia.isRecording() || this.userMedia.isPaused()) return;
|
|
7770
|
-
const
|
|
7771
|
-
|
|
7851
|
+
const message = event.data;
|
|
7852
|
+
if ("object" != typeof message || null === message) return;
|
|
7853
|
+
if (!("recordingId" in message) || message.recordingId !== this.recordingId) return;
|
|
7854
|
+
if (!("samples" in message) || !(message.samples instanceof Float32Array)) return;
|
|
7855
|
+
if (0 === message.samples.length) return;
|
|
7856
|
+
callback(new audio_sample(message.samples));
|
|
7772
7857
|
}
|
|
7773
7858
|
disconnect() {
|
|
7774
|
-
if (this.
|
|
7775
|
-
this.
|
|
7776
|
-
this.
|
|
7859
|
+
if (this.worklet) {
|
|
7860
|
+
this.worklet.port.onmessage = null;
|
|
7861
|
+
this.worklet.onprocessorerror = null;
|
|
7862
|
+
this.worklet.port.postMessage(-1);
|
|
7863
|
+
this.worklet.port.close();
|
|
7864
|
+
this.worklet.disconnect();
|
|
7865
|
+
this.worklet = void 0;
|
|
7777
7866
|
}
|
|
7778
7867
|
this.audioInput?.disconnect();
|
|
7779
7868
|
this.volume?.disconnect();
|
|
7869
|
+
this.audioInput = void 0;
|
|
7870
|
+
this.volume = void 0;
|
|
7871
|
+
this.audioCallback = void 0;
|
|
7872
|
+
this.recordingId = 0;
|
|
7780
7873
|
}
|
|
7781
|
-
init(localMediaStream) {
|
|
7874
|
+
async init(localMediaStream) {
|
|
7782
7875
|
this.options.logger.debug("AudioRecorder: init()");
|
|
7876
|
+
const initializationId = ++this.initializationId;
|
|
7783
7877
|
this.disconnect();
|
|
7784
|
-
const
|
|
7785
|
-
this.
|
|
7878
|
+
const bufferSize = this.getBufferSize();
|
|
7879
|
+
this.validateVolume();
|
|
7880
|
+
if ("function" != typeof window.AudioContext) throw error_createError({
|
|
7881
|
+
message: "Audio recording requires Web Audio support.",
|
|
7882
|
+
options: this.options
|
|
7883
|
+
});
|
|
7884
|
+
const context = this.getAudioContext();
|
|
7885
|
+
if (void 0 === context.audioWorklet || "function" != typeof window.AudioWorkletNode) throw error_createError({
|
|
7886
|
+
message: "Audio recording requires AudioWorklet support in a secure context.",
|
|
7887
|
+
options: this.options
|
|
7888
|
+
});
|
|
7889
|
+
const workletReady = this.workletReady ??= this.loadWorklet(context);
|
|
7890
|
+
try {
|
|
7891
|
+
await workletReady;
|
|
7892
|
+
} catch (exc) {
|
|
7893
|
+
if (this.workletReady === workletReady) this.workletReady = void 0;
|
|
7894
|
+
if (initializationId !== this.initializationId) return;
|
|
7895
|
+
throw error_createError({
|
|
7896
|
+
message: "Unable to load the audio recorder worklet. Check AudioWorklet and Content Security Policy support for blob: scripts.",
|
|
7897
|
+
cause: exc,
|
|
7898
|
+
options: this.options
|
|
7899
|
+
});
|
|
7900
|
+
}
|
|
7901
|
+
if (initializationId !== this.initializationId) return;
|
|
7786
7902
|
try {
|
|
7787
|
-
this.audioInput =
|
|
7903
|
+
this.audioInput = context.createMediaStreamSource(localMediaStream);
|
|
7788
7904
|
} catch (exc) {
|
|
7789
7905
|
throw error_createError({
|
|
7790
7906
|
message: "Webcam has no audio",
|
|
@@ -7792,38 +7908,69 @@ class AudioRecorder {
|
|
|
7792
7908
|
options: this.options
|
|
7793
7909
|
});
|
|
7794
7910
|
}
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
|
|
7799
|
-
|
|
7800
|
-
|
|
7801
|
-
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
7805
|
-
|
|
7806
|
-
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
|
|
7911
|
+
try {
|
|
7912
|
+
this.volume = context.createGain();
|
|
7913
|
+
this.volume.gain.value = this.options.audio.volume;
|
|
7914
|
+
this.worklet = new window.AudioWorkletNode(context, AUDIO_RECORDER_PROCESSOR_NAME, {
|
|
7915
|
+
channelCount: CHANNELS,
|
|
7916
|
+
channelCountMode: "explicit",
|
|
7917
|
+
outputChannelCount: [
|
|
7918
|
+
CHANNELS
|
|
7919
|
+
],
|
|
7920
|
+
processorOptions: {
|
|
7921
|
+
bufferSize
|
|
7922
|
+
}
|
|
7923
|
+
});
|
|
7924
|
+
this.worklet.port.onmessage = (event)=>{
|
|
7925
|
+
this.onAudioProcess(event);
|
|
7926
|
+
};
|
|
7927
|
+
this.worklet.onprocessorerror = ()=>{
|
|
7928
|
+
this.stop();
|
|
7929
|
+
this.emit("ERROR", {
|
|
7930
|
+
err: error_createError({
|
|
7931
|
+
message: "Audio recording processor failed.",
|
|
7932
|
+
options: this.options
|
|
7933
|
+
})
|
|
7934
|
+
});
|
|
7935
|
+
};
|
|
7936
|
+
this.audioInput.connect(this.volume);
|
|
7937
|
+
this.volume.connect(this.worklet);
|
|
7938
|
+
this.worklet.connect(context.destination);
|
|
7939
|
+
} catch (exc) {
|
|
7940
|
+
this.disconnect();
|
|
7941
|
+
throw error_createError({
|
|
7942
|
+
message: "Failed to connect the audio recorder.",
|
|
7943
|
+
exc,
|
|
7944
|
+
options: this.options
|
|
7945
|
+
});
|
|
7946
|
+
}
|
|
7810
7947
|
}
|
|
7811
7948
|
record(cb) {
|
|
7812
7949
|
this.options.logger.debug("AudioRecorder: record()");
|
|
7813
|
-
|
|
7814
|
-
|
|
7815
|
-
|
|
7950
|
+
this.audioCallback = cb;
|
|
7951
|
+
this.updateRecordingState();
|
|
7952
|
+
}
|
|
7953
|
+
updateRecordingState() {
|
|
7954
|
+
if (!this.worklet) return;
|
|
7955
|
+
const shouldRecord = Boolean(this.audioCallback) && this.userMedia.isRecording() && !this.userMedia.isPaused();
|
|
7956
|
+
this.recordingId = shouldRecord ? ++this.recordingSequence : 0;
|
|
7957
|
+
this.worklet.port.postMessage(this.recordingId);
|
|
7816
7958
|
}
|
|
7817
7959
|
async resume() {
|
|
7818
|
-
const context = this.
|
|
7960
|
+
const context = this.vcAudioContext;
|
|
7961
|
+
if (!context) return;
|
|
7819
7962
|
if ("running" !== context.state) await context.resume();
|
|
7820
7963
|
}
|
|
7821
7964
|
stop() {
|
|
7822
7965
|
this.options.logger.debug("AudioRecorder: stop()");
|
|
7966
|
+
this.initializationId++;
|
|
7823
7967
|
this.disconnect();
|
|
7824
|
-
|
|
7968
|
+
this.revokeModuleUrl();
|
|
7969
|
+
const context = this.vcAudioContext;
|
|
7970
|
+
this.vcAudioContext = void 0;
|
|
7971
|
+
this.workletReady = void 0;
|
|
7972
|
+
if (context && "closed" !== context.state) context.close().then(()=>{
|
|
7825
7973
|
this.options.logger.debug("AudioRecorder: audio context is closed");
|
|
7826
|
-
this.vcAudioContext = void 0;
|
|
7827
7974
|
}).catch((err)=>{
|
|
7828
7975
|
if (err instanceof Error) return void this.options.logger.error(error_createError({
|
|
7829
7976
|
err,
|
|
@@ -7833,17 +7980,11 @@ class AudioRecorder {
|
|
|
7833
7980
|
});
|
|
7834
7981
|
}
|
|
7835
7982
|
getSampleRate() {
|
|
7836
|
-
if (
|
|
7983
|
+
if ("function" == typeof window.AudioContext) return this.getAudioContext().sampleRate;
|
|
7837
7984
|
return -1;
|
|
7838
7985
|
}
|
|
7839
7986
|
constructor(userMedia, options){
|
|
7840
|
-
AudioRecorder_define_property(this, "
|
|
7841
|
-
AudioRecorder_define_property(this, "audioInput", void 0);
|
|
7842
|
-
AudioRecorder_define_property(this, "volume", void 0);
|
|
7843
|
-
AudioRecorder_define_property(this, "vcAudioContext", void 0);
|
|
7844
|
-
AudioRecorder_define_property(this, "userMedia", void 0);
|
|
7845
|
-
AudioRecorder_define_property(this, "options", void 0);
|
|
7846
|
-
this.options = options;
|
|
7987
|
+
super("AudioRecorder", options), AudioRecorder_define_property(this, "userMedia", void 0), AudioRecorder_define_property(this, "worklet", void 0), AudioRecorder_define_property(this, "audioInput", void 0), AudioRecorder_define_property(this, "volume", void 0), AudioRecorder_define_property(this, "vcAudioContext", void 0), AudioRecorder_define_property(this, "workletReady", void 0), AudioRecorder_define_property(this, "moduleUrl", void 0), AudioRecorder_define_property(this, "audioCallback", void 0), AudioRecorder_define_property(this, "initializationId", 0), AudioRecorder_define_property(this, "recordingSequence", 0), AudioRecorder_define_property(this, "recordingId", 0);
|
|
7847
7988
|
this.userMedia = userMedia;
|
|
7848
7989
|
}
|
|
7849
7990
|
}
|
|
@@ -7989,27 +8130,33 @@ class UserMedia extends util_Despot {
|
|
|
7989
8130
|
const fireCallbacks = ()=>{
|
|
7990
8131
|
const readyState = this.rawVisualUserMedia?.readyState;
|
|
7991
8132
|
this.options.logger.debug(`UserMedia: fireCallbacks(readyState=${readyState}, onPlayReached=${this.onPlayReached}, onLoadedMetaDataReached=${this.onLoadedMetaDataReached})`);
|
|
7992
|
-
if (this.onPlayReached && this.onLoadedMetaDataReached) if (this.audioRecorder)
|
|
7993
|
-
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
|
|
8000
|
-
|
|
8001
|
-
|
|
8133
|
+
if (this.onPlayReached && this.onLoadedMetaDataReached) if (this.audioRecorder) {
|
|
8134
|
+
const initializeAudio = async (audioRecorder)=>{
|
|
8135
|
+
try {
|
|
8136
|
+
await audioRecorder.init(localMediaStream);
|
|
8137
|
+
if (initializationId !== this.initializationId || this.currentVisualStream !== localMediaStream) return;
|
|
8138
|
+
const onAudioReady = ()=>{
|
|
8139
|
+
if (initializationId !== this.initializationId || this.currentVisualStream !== localMediaStream) return;
|
|
8140
|
+
if (this.recording) this.audioRecord(audioCallback);
|
|
8141
|
+
else this.on("SENDING_FIRST_FRAME", ()=>{
|
|
8142
|
+
this.audioRecord(audioCallback);
|
|
8143
|
+
});
|
|
8144
|
+
this.clearInitializationListeners?.();
|
|
8145
|
+
videoCallback();
|
|
8146
|
+
};
|
|
8147
|
+
if (params?.recovering) await audioRecorder.resume();
|
|
8148
|
+
onAudioReady();
|
|
8149
|
+
} catch (exc) {
|
|
8150
|
+
if (initializationId !== this.initializationId) return;
|
|
8151
|
+
unloadAllEventListeners();
|
|
8152
|
+
this.stop(void 0, {
|
|
8153
|
+
preserveRecordingState: Boolean(params?.recovering)
|
|
8154
|
+
});
|
|
8155
|
+
endedEarlyCallback(exc);
|
|
8156
|
+
}
|
|
8002
8157
|
};
|
|
8003
|
-
|
|
8004
|
-
|
|
8005
|
-
} catch (exc) {
|
|
8006
|
-
unloadAllEventListeners();
|
|
8007
|
-
this.stop(void 0, {
|
|
8008
|
-
preserveRecordingState: Boolean(params?.recovering)
|
|
8009
|
-
});
|
|
8010
|
-
endedEarlyCallback(exc);
|
|
8011
|
-
}
|
|
8012
|
-
else {
|
|
8158
|
+
initializeAudio(this.audioRecorder);
|
|
8159
|
+
} else {
|
|
8013
8160
|
this.clearInitializationListeners?.();
|
|
8014
8161
|
videoCallback();
|
|
8015
8162
|
}
|
|
@@ -8166,15 +8313,18 @@ class UserMedia extends util_Despot {
|
|
|
8166
8313
|
}
|
|
8167
8314
|
pause() {
|
|
8168
8315
|
this.paused = true;
|
|
8316
|
+
this.audioRecorder?.updateRecordingState();
|
|
8169
8317
|
}
|
|
8170
8318
|
isPaused() {
|
|
8171
8319
|
return this.paused;
|
|
8172
8320
|
}
|
|
8173
8321
|
resume() {
|
|
8174
8322
|
this.paused = false;
|
|
8323
|
+
this.audioRecorder?.updateRecordingState();
|
|
8175
8324
|
}
|
|
8176
8325
|
record() {
|
|
8177
8326
|
this.recording = true;
|
|
8327
|
+
this.audioRecorder?.updateRecordingState();
|
|
8178
8328
|
}
|
|
8179
8329
|
isRecording() {
|
|
8180
8330
|
return this.recording;
|
|
@@ -1,21 +1,31 @@
|
|
|
1
1
|
import AudioSample from "audio-sample";
|
|
2
|
-
import { VideomailClientOptions } from "../../../types/options.js";
|
|
3
|
-
import UserMedia from "../../../wrappers/visuals/userMedia.js";
|
|
2
|
+
import type { VideomailClientOptions } from "../../../types/options.js";
|
|
3
|
+
import type UserMedia from "../../../wrappers/visuals/userMedia.js";
|
|
4
|
+
import Despot from "../../Despot.js";
|
|
4
5
|
export type AudioProcessCB = (audioSample: AudioSample) => void;
|
|
5
|
-
declare class AudioRecorder {
|
|
6
|
-
private
|
|
6
|
+
declare class AudioRecorder extends Despot {
|
|
7
|
+
private readonly userMedia;
|
|
8
|
+
private worklet?;
|
|
7
9
|
private audioInput?;
|
|
8
10
|
private volume?;
|
|
9
11
|
private vcAudioContext?;
|
|
10
|
-
private
|
|
11
|
-
private
|
|
12
|
-
|
|
13
|
-
private
|
|
12
|
+
private workletReady?;
|
|
13
|
+
private moduleUrl?;
|
|
14
|
+
private audioCallback?;
|
|
15
|
+
private initializationId;
|
|
16
|
+
private recordingSequence;
|
|
17
|
+
private recordingId;
|
|
18
|
+
constructor(userMedia: Pick<UserMedia, "isRecording" | "isPaused">, options: VideomailClientOptions);
|
|
14
19
|
private getAudioContext;
|
|
20
|
+
private getBufferSize;
|
|
21
|
+
private validateVolume;
|
|
22
|
+
private revokeModuleUrl;
|
|
23
|
+
private loadWorklet;
|
|
15
24
|
private onAudioProcess;
|
|
16
25
|
private disconnect;
|
|
17
|
-
init(localMediaStream: MediaStream): void
|
|
26
|
+
init(localMediaStream: MediaStream): Promise<void>;
|
|
18
27
|
record(cb: AudioProcessCB): void;
|
|
28
|
+
updateRecordingState(): void;
|
|
19
29
|
resume(): Promise<void>;
|
|
20
30
|
stop(): void;
|
|
21
31
|
getSampleRate(): number;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const AUDIO_RECORDER_PROCESSOR_NAME = "videomail-pcm-recorder";
|
|
2
|
+
export interface AudioRecorderProcessorOptions {
|
|
3
|
+
processorOptions: {
|
|
4
|
+
bufferSize: number;
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
export interface AudioRecorderProcessor {
|
|
8
|
+
process(inputs: readonly (readonly Float32Array[])[], outputs: readonly (readonly Float32Array[])[]): boolean;
|
|
9
|
+
}
|
|
10
|
+
interface AudioRecorderProcessorBase {
|
|
11
|
+
readonly port: {
|
|
12
|
+
onmessage: ((event: MessageEvent<unknown>) => void) | null;
|
|
13
|
+
postMessage: (message: unknown, transfer: Transferable[]) => void;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export default function registerAudioRecorderProcessor(name: string, Processor: new () => AudioRecorderProcessorBase, register: (processorName: string, processor: new (options: AudioRecorderProcessorOptions) => AudioRecorderProcessor) => void): void;
|
|
17
|
+
export {};
|