audio youhua
This commit is contained in:
parent
0a7b2124a8
commit
fe2876f09c
@ -8,12 +8,20 @@ class AudioProcessor {
|
|||||||
|
|
||||||
// VAD相关属性
|
// VAD相关属性
|
||||||
this.isSpeaking = false;
|
this.isSpeaking = false;
|
||||||
this.silenceThreshold = options.silenceThreshold || 0.01;
|
this.silenceThreshold = options.silenceThreshold || 0.03;
|
||||||
this.silenceTimeout = options.silenceTimeout || 1000;
|
this.silenceTimeout = options.silenceTimeout || 1000;
|
||||||
this.minSpeechDuration = options.minSpeechDuration || 300;
|
this.minSpeechDuration = options.minSpeechDuration || 300;
|
||||||
this.silenceTimer = null;
|
this.silenceTimer = null;
|
||||||
this.speechStartTime = null;
|
this.speechStartTime = null;
|
||||||
this.audioBuffer = [];
|
this.audioBuffer = [];
|
||||||
|
this.backgroundNoiseLevel = 0;
|
||||||
|
// 添加连续性检测参数
|
||||||
|
this.consecutiveFramesRequired = 3;
|
||||||
|
this.consecutiveFramesCount = 0; // 当前连续帧计数
|
||||||
|
this.frameBuffer = []; // 帧缓冲区
|
||||||
|
this.adaptiveThreshold = options.adaptiveThreshold !== false;
|
||||||
|
this.noiseCalibrationSamples = [];
|
||||||
|
this.isCalibrated = false; // 添加校准状态标志
|
||||||
|
|
||||||
// API配置
|
// API配置
|
||||||
this.apiConfig = {
|
this.apiConfig = {
|
||||||
@ -36,6 +44,49 @@ class AudioProcessor {
|
|||||||
this.onStatusUpdate = options.onStatusUpdate || (() => {});
|
this.onStatusUpdate = options.onStatusUpdate || (() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加背景噪音校准方法
|
||||||
|
// 改进背景噪音校准方法,添加更多日志
|
||||||
|
calibrateBackgroundNoise(audioData) {
|
||||||
|
const audioLevel = this.calculateAudioLevel(audioData);
|
||||||
|
this.noiseCalibrationSamples.push(audioLevel);
|
||||||
|
|
||||||
|
if (this.noiseCalibrationSamples.length >= 100) {
|
||||||
|
this.backgroundNoiseLevel = this.noiseCalibrationSamples.reduce((a, b) => a + b) / this.noiseCalibrationSamples.length;
|
||||||
|
const oldThreshold = this.silenceThreshold;
|
||||||
|
this.silenceThreshold = Math.max(this.backgroundNoiseLevel * 2.5, 0.005); // 设置最小阈值
|
||||||
|
|
||||||
|
console.log(`背景噪音校准完成:`);
|
||||||
|
console.log(`- 平均背景噪音: ${this.backgroundNoiseLevel.toFixed(4)}`);
|
||||||
|
console.log(`- 旧阈值: ${oldThreshold.toFixed(4)}`);
|
||||||
|
console.log(`- 新阈值: ${this.silenceThreshold.toFixed(4)}`);
|
||||||
|
|
||||||
|
this.noiseCalibrationSamples = [];
|
||||||
|
this.onStatusUpdate('背景噪音校准完成,等待语音输入...', 'ready');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 改进音频能量计算
|
||||||
|
calculateAudioLevel(audioData) {
|
||||||
|
let sum = 0;
|
||||||
|
let peak = 0;
|
||||||
|
for (let i = 0; i < audioData.length; i++) {
|
||||||
|
const sample = Math.abs(audioData[i]);
|
||||||
|
sum += sample * sample;
|
||||||
|
peak = Math.max(peak, sample);
|
||||||
|
}
|
||||||
|
const rms = Math.sqrt(sum / audioData.length);
|
||||||
|
// 结合RMS和峰值进行更准确的检测
|
||||||
|
return rms * 0.7 + peak * 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新校准背景噪音
|
||||||
|
recalibrateBackground() {
|
||||||
|
this.noiseCalibrationSamples = [];
|
||||||
|
this.isCalibrated = false;
|
||||||
|
this.onStatusUpdate('开始重新校准背景噪音...', 'calibrating');
|
||||||
|
console.log('开始重新校准背景噪音');
|
||||||
|
}
|
||||||
|
|
||||||
// 生成UUID
|
// 生成UUID
|
||||||
generateUUID() {
|
generateUUID() {
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||||
@ -46,27 +97,33 @@ class AudioProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 计算音频能量(音量)
|
// 计算音频能量(音量)
|
||||||
calculateAudioLevel(audioData) {
|
// calculateAudioLevel(audioData) {
|
||||||
let sum = 0;
|
// let sum = 0;
|
||||||
for (let i = 0; i < audioData.length; i++) {
|
// for (let i = 0; i < audioData.length; i++) {
|
||||||
sum += audioData[i] * audioData[i];
|
// sum += audioData[i] * audioData[i];
|
||||||
}
|
// }
|
||||||
return Math.sqrt(sum / audioData.length);
|
// return Math.sqrt(sum / audioData.length);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 语音活动检测
|
// 修改语音活动检测方法
|
||||||
|
// 改进语音活动检测
|
||||||
detectVoiceActivity(audioData) {
|
detectVoiceActivity(audioData) {
|
||||||
const audioLevel = this.calculateAudioLevel(audioData);
|
const audioLevel = this.calculateAudioLevel(audioData);
|
||||||
const currentTime = Date.now();
|
const currentTime = Date.now();
|
||||||
|
|
||||||
|
// 连续性检测
|
||||||
if (audioLevel > this.silenceThreshold) {
|
if (audioLevel > this.silenceThreshold) {
|
||||||
|
this.consecutiveFramesCount++;
|
||||||
|
|
||||||
|
// 需要连续几帧都超过阈值才开始录音
|
||||||
|
if (this.consecutiveFramesCount >= this.consecutiveFramesRequired) {
|
||||||
if (!this.isSpeaking) {
|
if (!this.isSpeaking) {
|
||||||
this.isSpeaking = true;
|
this.isSpeaking = true;
|
||||||
this.speechStartTime = currentTime;
|
this.speechStartTime = currentTime;
|
||||||
this.audioBuffer = [];
|
this.audioBuffer = [...this.frameBuffer]; // 包含之前的帧
|
||||||
this.onSpeechStart();
|
this.onSpeechStart();
|
||||||
this.onStatusUpdate('检测到语音,开始录音...', 'speaking');
|
this.onStatusUpdate('检测到语音,开始录音...', 'speaking');
|
||||||
console.log('开始说话');
|
console.log(`开始说话 - 音量: ${audioLevel.toFixed(4)}, 连续帧: ${this.consecutiveFramesCount}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.silenceTimer) {
|
if (this.silenceTimer) {
|
||||||
@ -76,6 +133,18 @@ class AudioProcessor {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
// 还未达到连续帧要求,缓存音频数据
|
||||||
|
this.frameBuffer.push(new Float32Array(audioData));
|
||||||
|
if (this.frameBuffer.length > this.consecutiveFramesRequired) {
|
||||||
|
this.frameBuffer.shift(); // 保持缓冲区大小
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 重置连续帧计数
|
||||||
|
this.consecutiveFramesCount = 0;
|
||||||
|
this.frameBuffer = [];
|
||||||
|
|
||||||
if (this.isSpeaking && !this.silenceTimer) {
|
if (this.isSpeaking && !this.silenceTimer) {
|
||||||
this.silenceTimer = setTimeout(() => {
|
this.silenceTimer = setTimeout(() => {
|
||||||
this.handleSpeechEnd();
|
this.handleSpeechEnd();
|
||||||
@ -277,6 +346,11 @@ class AudioProcessor {
|
|||||||
this.isRecording = true;
|
this.isRecording = true;
|
||||||
this.onStatusUpdate('等待语音输入...', 'ready');
|
this.onStatusUpdate('等待语音输入...', 'ready');
|
||||||
|
|
||||||
|
// 在startRecording方法的最后添加
|
||||||
|
if (this.adaptiveThreshold && this.noiseCalibrationSamples.length === 0) {
|
||||||
|
this.onStatusUpdate('正在校准背景噪音,请保持安静...', 'calibrating');
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user