This commit is contained in:
zpc 2025-03-28 14:48:09 +08:00
parent b77c86974a
commit 3702252e00
9 changed files with 727 additions and 348 deletions

View File

@ -3,6 +3,7 @@ using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using ShengShengBuXi.ConsoleApp.Models;
using System.Linq;
using System.Transactions;
namespace ShengShengBuXi.ConsoleApp.Services;
@ -867,6 +868,9 @@ public class PhoneBoothService : IPhoneBoothService, IDisposable
}
}
public static DateTime _lasHasoudDateTime = DateTime.Now;
public static bool _isSpeaking = false;
/// <summary>
/// 检查是否有声音
/// </summary>
@ -894,9 +898,19 @@ public class PhoneBoothService : IPhoneBoothService, IDisposable
}
}
}
bool isSpeaking = maxVolume > _config.Recording.SilenceThreshold;
if (isSpeaking && !_isSpeaking)
{
_isSpeaking = true;
}
if (DateTime.Now.Subtract(_lasHasoudDateTime).TotalSeconds > 1)
{
Console.WriteLine($"当前音量:{maxVolume},设置的音量灵敏度:{_config.Recording.SilenceThreshold},是否已监测到在说话中:{_isSpeaking}");
_lasHasoudDateTime = DateTime.Now;
_isSpeaking = false;
}
// 如果最大音量超过阈值,则认为有声音
return maxVolume > _config.Recording.SilenceThreshold;
return isSpeaking;
}
/// <summary>

View File

@ -1,5 +1,6 @@
{
"SignalRHubUrl": "http://115.159.44.16/audiohub",
"SignalRHubUrl": "http://localhost:81/audiohub",
"ConfigBackupPath": "config.json",
"AutoConnectToServer": true
}

View File

@ -19,7 +19,7 @@
"RecordingDeviceNumber": 0,
"SampleRate": 16000,
"Channels": 1,
"BufferMilliseconds": 100,
"BufferMilliseconds": 50,
"SilenceThreshold": 0.15,
"SilenceTimeoutSeconds": 30,
"AllowUserHangup": true,

View File

@ -83,7 +83,7 @@ namespace ShengShengBuXi.Hubs
/// 预设句子列表
/// </summary>
private static List<string> _presetSentences = new List<string>();
// 配置信息
private static string _displayConfig = "{}";
private static object _displayConfigLock = new object();
@ -480,9 +480,18 @@ namespace ShengShengBuXi.Hubs
{
try
{
_logger.LogDebug($"转发音频数据到{monitoringClients.Count}个监听客户端,数据长度: {audioData.Length}");
// 尝试直接发送数据
await Clients.Clients(monitoringClients).SendAsync("ReceiveAudioData", audioData);
if (_configurationService.CurrentConfig.Network.EnableAudioNoiseReduction)
{
var jiangzao = _audioProcessingService.ApplyNoiseReduction(audioData, config.SampleRate, config.Channels);
_logger.LogDebug($"转发音频数据到{monitoringClients.Count}个监听客户端,数据长度: {audioData.Length},降噪后长度:{jiangzao.Length}");
// 尝试直接发送数据
await Clients.Clients(monitoringClients).SendAsync("ReceiveAudioData", jiangzao);
}
else
{
// 尝试直接发送数据
await Clients.Clients(monitoringClients).SendAsync("ReceiveAudioData", audioData);
}
}
catch (Exception ex)
{

View File

@ -309,6 +309,11 @@ public class NetworkConfig
/// 是否启用实时音频传输
/// </summary>
public bool EnableAudioStreaming { get; set; } = true;
/// <summary>
/// 是否开启音频降噪
/// </summary>
public bool EnableAudioNoiseReduction { get; set; } = false;
/// <summary>
/// 心跳间隔(秒)

File diff suppressed because it is too large Load Diff

View File

@ -15,18 +15,18 @@ namespace ShengShengBuXi.Services
/// 当有新的语音转文字结果时触发
/// </summary>
event EventHandler<SpeechToTextResult> SpeechToTextResultReceived;
/// <summary>
/// 当音频数据被保存为文件时触发
/// </summary>
event EventHandler<string> AudioSavedToFile;
/// <summary>
/// 初始化音频处理服务
/// </summary>
/// <returns>初始化是否成功</returns>
bool Initialize();
/// <summary>
/// 处理接收到的音频数据
/// </summary>
@ -37,7 +37,7 @@ namespace ShengShengBuXi.Services
/// <param name="token">取消令牌</param>
/// <returns>异步任务</returns>
Task ProcessAudioDataAsync(byte[] audioData, int sampleRate, int channels, string clientId, CancellationToken token = default);
/// <summary>
/// 开始新的音频流处理
/// </summary>
@ -47,7 +47,7 @@ namespace ShengShengBuXi.Services
/// <param name="token">取消令牌</param>
/// <returns>异步任务</returns>
Task StartAudioStreamAsync(string clientId, int sampleRate, int channels, CancellationToken token = default);
/// <summary>
/// 结束音频流处理
/// </summary>
@ -55,26 +55,41 @@ namespace ShengShengBuXi.Services
/// <param name="token">取消令牌</param>
/// <returns>异步任务</returns>
Task EndAudioStreamAsync(string clientId, CancellationToken token = default);
/// <summary>
/// 获取当前正在处理的音频流
/// </summary>
/// <param name="clientId">客户端ID</param>
/// <returns>音频流</returns>
Stream GetCurrentAudioStream(string clientId);
/// <summary>
/// 获取最近的录音文件
/// </summary>
/// <param name="count">文件数量</param>
/// <returns>录音文件路径列表</returns>
string[] GetRecentRecordings(int count = 10);
/// <summary>
/// 获取会话的录音文件路径
/// </summary>
/// <param name="clientId">客户端ID</param>
/// <returns>录音文件路径如果没有则返回null</returns>
string GetRecordingFilePath(string clientId);
/// <summary>
/// 应用噪声消除
/// </summary>
/// <param name="audioData">音频数据</param>
/// <param name="sampleRate">采样率</param>
/// <param name="channels">声道数</param>
/// <param name="noiseThreshold">噪声门限值</param>
/// <param name="attackSeconds">攻击时间</param>
/// <param name="releaseSeconds">释放时间</param>
/// <param name="highPassCutoff">高通滤波器截止频率(Hz)</param>
/// <param name="q">滤波器Q值</param>
/// <returns></returns>
byte[] ApplyNoiseReduction(byte[] audioData, int sampleRate = 16000, int channels = 1, float noiseThreshold = 0.02f, float attackSeconds = 0.01f, float releaseSeconds = 0.1f, int highPassCutoff = 80, float q = 1.0f);
}
}
}

View File

@ -562,7 +562,7 @@ namespace ShengShengBuXi.Services
await ProcessAudioAsync(audioData, sessionId, token);
// 等待一段时间,模拟实时处理
await Task.Delay(100, token);
await Task.Delay(20, token);
}
// 结束会话

View File

@ -39,6 +39,7 @@
"reconnectDelayMs": 2000,
"enableSpeechToText": true,
"enableAudioStreaming": true,
"EnableAudioNoiseReduction": false,
"heartbeatIntervalSeconds": 15,
"tencentCloudASR": {
"appId": "",