wangwang/js/audioRecorder.js

149 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import BarkDetector from './barkDetector';
export default class AudioRecorder {
constructor(options = {}) {
this.recorder = wx.getRecorderManager();
this.detector = new BarkDetector(options);
this.isRecording = false;
this.sampleRate = options.sampleRate || 16000;
this.frameSize = options.frameSize || 8192;
this.onUpdate = options.onUpdate || null;
this.onError = options.onError || null;
this._bindEvents();
}
_bindEvents() {
this.recorder.onStart(() => {
this.isRecording = true;
});
this.recorder.onStop(() => {
this.isRecording = false;
});
this.recorder.onError((err) => {
this.isRecording = false;
if (this.onError) this.onError(err);
});
this.recorder.onFrameRecorded((res) => {
if (!res.frameBuffer || res.frameBuffer.byteLength === 0) return;
const pcm = new Int16Array(res.frameBuffer);
this.detector.feed(pcm, this.sampleRate);
const status = this.detector.getStatus();
if (this.onUpdate) {
this.onUpdate(status);
}
});
}
start() {
if (this.isRecording) return;
// 先检查并请求麦克风权限
this._checkAndRequestPermission()
.then(() => this._doStart())
.catch((err) => {
console.error('mic permission error', err);
if (this.onError) this.onError(err);
});
}
_checkAndRequestPermission() {
return new Promise((resolve, reject) => {
wx.getSetting({
success: (res) => {
const auth = res.authSetting['scope.record'];
if (auth === true) {
// 已授权
resolve();
return;
}
if (auth === false) {
// 之前拒绝过,需要引导去设置页
this._showOpenSettings(reject);
return;
}
// 未请求过权限,发起授权请求
wx.authorize({
scope: 'scope.record',
success: () => resolve(),
fail: (err) => {
// 用户点击拒绝
if (err.errCode === 12001 || (err.errMsg && err.errMsg.includes('auth deny'))) {
this._showOpenSettings(reject);
} else {
reject(err);
}
}
});
},
fail: reject
});
});
}
_showOpenSettings(reject) {
wx.showModal({
title: '需要麦克风权限',
content: '汪汪大作战需要麦克风来检测你的狗叫声,请在设置中打开麦克风权限。',
confirmText: '去设置',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
wx.openSetting({
success: (settingRes) => {
if (settingRes.authSetting['scope.record']) {
this._doStart();
} else {
reject(new Error('用户未在设置中开启麦克风权限'));
}
},
fail: reject
});
} else {
reject(new Error('用户取消授权'));
}
},
fail: reject
});
}
_doStart() {
try {
// 微信小游戏 onFrameRecorded 在部分环境(尤其是开发者工具模拟器)下不会实时触发,
// 在真机上通常正常。这里用 1KB 帧大小(约 64ms尝试获得较频繁的回调。
this.recorder.start({
duration: 600000,
sampleRate: 16000,
numberOfChannels: 1,
format: 'PCM',
frameSize: 1
});
// recorder started
} catch (err) {
console.error('[AudioRecorder] recorder.start() error', err);
if (this.onError) this.onError(err);
}
}
stop() {
if (!this.isRecording) return;
this.recorder.stop();
}
reset() {
this.detector.reset();
}
getStatus() {
return this.detector.getStatus();
}
}