From a39c5af74c19df7eb29eaaba4190d8404ffe1324 Mon Sep 17 00:00:00 2001 From: zpc Date: Sat, 29 Mar 2025 11:15:22 +0800 Subject: [PATCH] 23 --- ShengShengBuXi/Hubs/AudioHub.cs | 122 ++++-- ShengShengBuXi/Pages/Monitor.cshtml | 623 ++++++++++++++++------------ 2 files changed, 443 insertions(+), 302 deletions(-) diff --git a/ShengShengBuXi/Hubs/AudioHub.cs b/ShengShengBuXi/Hubs/AudioHub.cs index acbec4a..4eb21d5 100644 --- a/ShengShengBuXi/Hubs/AudioHub.cs +++ b/ShengShengBuXi/Hubs/AudioHub.cs @@ -43,6 +43,9 @@ namespace ShengShengBuXi.Hubs /// private static Timer _cleanupTimer; + + private static bool isInitialized = false; + /// /// 显示文本队列 /// @@ -123,7 +126,7 @@ namespace ShengShengBuXi.Hubs // 加载显示配置 LoadDisplayConfig(); - + // 加载控屏设置 LoadScreenControlSetting(); } @@ -203,7 +206,7 @@ namespace ShengShengBuXi.Hubs { // 默认设置为自动 _manualScreenControlEnabled = false; - + // 保存默认设置 SaveScreenControlSetting(); Console.WriteLine("创建默认控屏设置成功"); @@ -215,7 +218,7 @@ namespace ShengShengBuXi.Hubs _manualScreenControlEnabled = false; } } - + // 保存控屏设置 private static bool SaveScreenControlSetting() { @@ -265,18 +268,22 @@ namespace ShengShengBuXi.Hubs _cleanupTimer = new Timer(CleanupOldProcessedPaths, null, TimeSpan.FromMinutes(30), TimeSpan.FromMinutes(30)); } - // 从文件加载预设句子 - LoadPresetSentencesFromFile(); + if (!isInitialized) + { + isInitialized = true; + // 从文件加载预设句子 + LoadPresetSentencesFromFile(); - // 从文件加载监控文本队列 - LoadMonitorTextQueueFromFile(); + // 从文件加载监控文本队列 + LoadMonitorTextQueueFromFile(); - // 初始化显示文本定时器 - InitializeDisplayTextTimer(); + // 初始化显示文本定时器 + InitializeDisplayTextTimer(); - // 注册应用程序域卸载事件,以便在应用关闭时保存数据 - AppDomain.CurrentDomain.ProcessExit += (sender, e) => SaveMonitorTextQueueToFile(); - AppDomain.CurrentDomain.DomainUnload += (sender, e) => SaveMonitorTextQueueToFile(); + // 注册应用程序域卸载事件,以便在应用关闭时保存数据 + AppDomain.CurrentDomain.ProcessExit += (sender, e) => SaveMonitorTextQueueToFile(); + AppDomain.CurrentDomain.DomainUnload += (sender, e) => SaveMonitorTextQueueToFile(); + } } /// @@ -513,8 +520,8 @@ namespace ShengShengBuXi.Hubs if (_clients.TryAdd(Context.ConnectionId, clientInfo)) { + _logger.LogInformation($"已自动注册音频源客户端: {Context.ConnectionId}"); } - //return; } if (clientInfo.ClientType != ClientType.Controller) @@ -523,53 +530,90 @@ namespace ShengShengBuXi.Hubs return; } - // 处理音频数据 - var config = _configurationService.CurrentConfig.Recording; - await _audioProcessingService.ProcessAudioDataAsync(audioData, config.SampleRate, config.Channels, Context.ConnectionId); - - // 处理语音识别 - if (_configurationService.CurrentConfig.Network.EnableSpeechToText) + // 音频数据基本验证 + if (audioData == null || audioData.Length < 2) { - await _speechToTextService.ProcessAudioAsync(audioData, Context.ConnectionId); + return; // 忽略无效数据 } - // 转发音频数据到管理端 - if (_configurationService.CurrentConfig.Network.EnableAudioStreaming) - { - // await Clients.Group("webadmin").SendAsync("ReceiveAudioData", Context.ConnectionId, audioData); + // 获取配置,避免多次读取 + var config = _configurationService.CurrentConfig.Recording; + bool enableSpeechToText = _configurationService.CurrentConfig.Network.EnableSpeechToText; + bool enableAudioStreaming = _configurationService.CurrentConfig.Network.EnableAudioStreaming; + bool enableNoiseReduction = _configurationService.CurrentConfig.Network.EnableAudioNoiseReduction; - // 转发音频到正在监听的显示端 + // 并行处理不同的任务 + var tasks = new List(); + + // 处理音频数据(总是执行) + tasks.Add(_audioProcessingService.ProcessAudioDataAsync(audioData, config.SampleRate, config.Channels, Context.ConnectionId)); + + // 处理语音识别(如果启用) + if (enableSpeechToText) + { + tasks.Add(_speechToTextService.ProcessAudioAsync(audioData, Context.ConnectionId)); + } + + // 音频流转发(如果启用) + if (enableAudioStreaming) + { var monitoringClients = _clients.Values - .Where(c => (c.ClientType == ClientType.Monitor || c.ClientType == ClientType.WebAdmin)) + .Where(c => c.ClientType == ClientType.Monitor) .Select(c => c.ClientId) .ToList(); - if (monitoringClients.Any()) + if (monitoringClients.Count > 0) { + // 音频数据处理和发送速率控制 try { - byte[] dataToSend; + // 基于当前时间创建节流标识 + var now = DateTime.Now; + var throttleKey = now.ToString("yyyyMMddHHmmss") + (now.Millisecond / 100).ToString(); - if (_configurationService.CurrentConfig.Network.EnableAudioNoiseReduction) + // 使用当前客户端连接ID和时间标识作为处理标记 + var processingKey = $"{Context.ConnectionId}:{throttleKey}"; + + // 获取降噪或原始数据 + byte[] dataToSend; + if (enableNoiseReduction) { dataToSend = _audioProcessingService.ApplyNoiseReduction(audioData, config.SampleRate, config.Channels); - _logger.LogDebug($"转发音频数据到{monitoringClients.Count}个监听客户端,数据长度: {audioData.Length},降噪后长度:{dataToSend.Length}"); } else { dataToSend = audioData; - _logger.LogDebug($"转发音频数据到{monitoringClients.Count}个监听客户端,数据长度: {audioData.Length}"); } - // 始终使用二进制格式发送数据,避免字符串转换 - await Clients.Clients(monitoringClients).SendAsync("ReceiveAudioData", dataToSend); + // 为每个监控客户端创建单独的发送任务,确保数据流的独立性 + foreach (var clientId in monitoringClients) + { + // 添加音频数据发送任务,使用单独的客户端连接 + tasks.Add(Clients.Client(clientId).SendAsync("ReceiveAudioData", dataToSend)); + } + + // 只在日志级别为Debug时输出详细信息 + if (_logger.IsEnabled(LogLevel.Debug) && monitoringClients.Count > 0) + { + _logger.LogDebug($"分发音频数据到{monitoringClients.Count}个监听客户端,数据长度: {dataToSend.Length}字节,标识: {throttleKey}"); + } } catch (Exception ex) { - _logger.LogError($"转发音频数据到监听端失败: {ex.Message}"); + _logger.LogError($"准备音频数据分发时出错: {ex.Message}"); } } } + + // 等待所有任务完成 + try + { + await Task.WhenAll(tasks); + } + catch (Exception ex) + { + _logger.LogError($"处理音频数据时发生错误: {ex.Message}"); + } } /// @@ -1062,7 +1106,9 @@ namespace ShengShengBuXi.Hubs // 如果是真实用户的发言,持久化保存到文件 if (textToDisplay.IsRealUser) { + SaveRealUserDisplayToFile(textToDisplay); + _presetSentences.Add(textToDisplay.Text); } } else @@ -1710,18 +1756,18 @@ namespace ShengShengBuXi.Hubs // 设置模式 _manualScreenControlEnabled = isManual; - + // 保存设置 bool success = SaveScreenControlSetting(); - + if (success) { // 通知所有监控客户端更新设置 await Clients.Group("monitor").SendAsync("ScreenControlSettingChanged", isManual); - + _logger.LogInformation($"控屏设置已更新为: {(isManual ? "手动" : "自动")}"); } - + return success; } diff --git a/ShengShengBuXi/Pages/Monitor.cshtml b/ShengShengBuXi/Pages/Monitor.cshtml index d11f401..b5d5bb7 100644 --- a/ShengShengBuXi/Pages/Monitor.cshtml +++ b/ShengShengBuXi/Pages/Monitor.cshtml @@ -4,6 +4,9 @@ ViewData["Title"] = "清竹园-中控页面"; } + + +
@@ -18,14 +21,14 @@
+ style="width: 24px; height: 24px; background-color: red;">
未检测到通话
+ style="max-height: 75vh; overflow-y: auto;">
加载中...
@@ -108,12 +111,13 @@
-
文本编辑 (最多输入30个文字)
+
+ 文本编辑 (最多输入30个文字) +
+ maxlength="30">
@@ -124,12 +128,12 @@
@@ -153,7 +157,7 @@
+ style="max-height: 75vh; overflow-y: auto;">
加载中...
@@ -186,7 +190,7 @@