This commit is contained in:
zpc 2025-03-28 02:39:13 +08:00
parent b00924a691
commit 7cf247a873
7 changed files with 839 additions and 214 deletions

View File

@ -0,0 +1,24 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShengShengBuXi.ConsoleApp", "ShengShengBuXi.ConsoleApp.csproj", "{FE0A1BEA-BEF1-CDEB-D076-0AD5E44F7491}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FE0A1BEA-BEF1-CDEB-D076-0AD5E44F7491}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE0A1BEA-BEF1-CDEB-D076-0AD5E44F7491}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE0A1BEA-BEF1-CDEB-D076-0AD5E44F7491}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE0A1BEA-BEF1-CDEB-D076-0AD5E44F7491}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9BAF9C30-5594-4165-981C-6FACBF081E8D}
EndGlobalSection
EndGlobal

View File

@ -7,6 +7,7 @@ using Microsoft.Extensions.Logging;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Text.Json;
using Newtonsoft.Json;
@ -91,7 +92,99 @@ namespace ShengShengBuXi.Hubs
/// </summary>
private static readonly int _sentenceHistoryLimit = 20;
// 客户端注册信息
private static Dictionary<string, ClientInfo> _clientsDict = new Dictionary<string, ClientInfo>();
// 用于线程安全访问
private static object _clientsLock = new object();
// 文本显示队列
private static List<DisplayText> _displayTextList = new List<DisplayText>();
private static object _displayTextListLock = new object();
// 监控文本列表
private static List<MonitorText> _monitorTextList = new List<MonitorText>();
private static object _monitorTextListLock = new object();
// 配置信息
private static string _displayConfig = "{}";
private static object _displayConfigLock = new object();
// 管理员配置保存路径
private static readonly string ConfigDirectory = Path.Combine(Directory.GetCurrentDirectory(), "config");
private static readonly string DisplayConfigPath = Path.Combine(ConfigDirectory, "display.json");
// 用于初始化配置
static AudioHub()
{
// 确保配置目录存在
if (!Directory.Exists(ConfigDirectory))
{
Directory.CreateDirectory(ConfigDirectory);
}
// 加载显示配置
LoadDisplayConfig();
}
// 加载显示配置
private static void LoadDisplayConfig()
{
try
{
if (File.Exists(DisplayConfigPath))
{
string configJson = File.ReadAllText(DisplayConfigPath);
lock (_displayConfigLock)
{
_displayConfig = configJson;
}
Console.WriteLine("加载显示配置成功");
}
else
{
// 创建默认配置
string defaultConfig = @"{
""leftContainer"": {
""turnPageHeight"": 0.8,
""fontSize"": ""16px"",
""typewriterSpeed"": 50
},
""rightContainer"": {
""fontSize"": ""24px"",
""fontWeight"": ""normal"",
""fontStyle"": ""normal"",
""typewriterSpeed"": 50
},
""waterEffect"": {
""enabled"": true,
""minInterval"": 800,
""maxInterval"": 2000,
""simultaneousDrops"": 3,
""fadeOutSpeed"": 0.1,
""centerBias"": 0.5,
""largeDrop"": {
""probability"": 0.2,
""size"": 9
}
}
}";
lock (_displayConfigLock)
{
_displayConfig = defaultConfig;
}
// 保存默认配置
File.WriteAllText(DisplayConfigPath, defaultConfig);
Console.WriteLine("创建默认显示配置成功");
}
}
catch (Exception ex)
{
Console.WriteLine($"加载显示配置出错: {ex.Message}");
}
}
/// <summary>
/// 初始化音频Hub
/// </summary>
@ -1328,5 +1421,76 @@ namespace ShengShengBuXi.Hubs
_logger.LogInformation($"客户端获取当前显示模式: {Context.ConnectionId}, 类型: {clientInfo.ClientType}");
return _configurationService.CurrentConfig.DisplayType;
}
/// <summary>
/// 获取显示配置
/// </summary>
/// <returns>显示配置的JSON字符串</returns>
public string GetDisplayConfig()
{
lock (_displayConfigLock)
{
return _displayConfig;
}
}
/// <summary>
/// 保存显示配置
/// </summary>
/// <param name="configJson">配置的JSON字符串</param>
/// <returns>是否保存成功</returns>
public async Task<bool> SaveDisplayConfig(string configJson)
{
try
{
// 尝试解析JSON以验证格式
JsonDocument.Parse(configJson);
// 保存到文件
await File.WriteAllTextAsync(DisplayConfigPath, configJson);
// 更新内存中的配置
lock (_displayConfigLock)
{
_displayConfig = configJson;
}
// 通知所有显示客户端
await NotifyDisplayConfig();
return true;
}
catch (Exception ex)
{
Console.WriteLine($"保存显示配置出错: {ex.Message}");
return false;
}
}
/// <summary>
/// 通知所有显示客户端更新配置
/// </summary>
private async Task NotifyDisplayConfig()
{
string configJson;
lock (_displayConfigLock)
{
configJson = _displayConfig;
}
List<string> displayClientIds = new List<string>();
lock (_clients)
{
displayClientIds = _clients
.Where(c => c.Value.ClientType.ToString() == "Display")
.Select(c => c.Key)
.ToList();
}
foreach (var clientId in displayClientIds)
{
await Clients.Client(clientId).SendAsync("ReceiveDisplayConfig", configJson);
}
}
}
}

View File

@ -0,0 +1,60 @@
using System;
namespace ShengShengBuXi.Models
{
/// <summary>
/// 监控文本模型
/// </summary>
public class MonitorText
{
/// <summary>
/// 唯一标识符
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// 显示文本内容
/// </summary>
public string Text { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime Timestamp { get; set; }
/// <summary>
/// 是否来自真实用户(否则为系统预设文本)
/// </summary>
public bool IsRealUser { get; set; }
/// <summary>
/// 原始语音识别结果ID如果有
/// </summary>
public string RecognitionId { get; set; }
/// <summary>
/// 文本优先级(真实用户优先显示)
/// </summary>
public int Priority => IsRealUser ? 10 : 1;
/// <summary>
/// 是否处理过
/// </summary>
public bool IsProcessed { get; set; } = false;
/// <summary>
/// 处理后的文字
/// </summary>
public string CompletedText { get; set; }
/// <summary>
/// 录音文件路径
/// </summary>
public string RecordingPath { get; set; }
/// <summary>
/// 识别文字的文件的路径
/// </summary>
public string TextFilePath { get; set; }
}
}

File diff suppressed because it is too large Load Diff

View File

@ -155,10 +155,7 @@
size: 80 // 大涟漪的大小
}
},
// 预设的中文句子数组
sentences: [
]
};
let currentSentenceIndex = 0; // 当前句子索引
@ -354,6 +351,19 @@
displayText(text);
});
// 接收显示配置的处理函数
hubConnection.on("ReceiveDisplayConfig", function (configJson) {
console.log("收到显示配置");
try {
const newConfig = JSON.parse(configJson);
// 更新全局配置
updateConfig(newConfig);
console.log("已更新显示配置");
} catch (error) {
console.error("解析显示配置失败:", error);
}
});
// 启动连接
hubConnection.start()
.then(function () {
@ -362,6 +372,19 @@
hubConnection.invoke("RegisterClient", 3, "Display")
.then(function() {
console.log("注册为显示客户端成功");
// 获取显示配置
return hubConnection.invoke("GetDisplayConfig");
})
.then(function(configJson) {
if(configJson) {
console.log("已获取显示配置");
try {
const config = JSON.parse(configJson);
updateConfig(config);
} catch (error) {
console.error("解析显示配置失败:", error);
}
}
// 开始接收显示文本
return hubConnection.invoke("StartReceivingDisplayText");
})
@ -369,7 +392,7 @@
console.log("开始接收显示文本");
})
.catch(function(err) {
console.error("注册客户端失败:", err);
console.error("客户端操作失败:", err);
});
})
.catch(function (err) {
@ -385,6 +408,67 @@
});
}
// 更新配置
function updateConfig(newConfig) {
// 更新左侧容器配置
if (newConfig.leftContainer) {
CONFIG.leftContainer.turnPageHeight = newConfig.leftContainer.turnPageHeight || CONFIG.leftContainer.turnPageHeight;
CONFIG.leftContainer.fontSize = newConfig.leftContainer.fontSize || CONFIG.leftContainer.fontSize;
CONFIG.leftContainer.typewriterSpeed = newConfig.leftContainer.typewriterSpeed || CONFIG.leftContainer.typewriterSpeed;
// 应用字体大小到CSS
document.documentElement.style.setProperty('--left-font-size', CONFIG.leftContainer.fontSize);
}
// 更新右侧容器配置
if (newConfig.rightContainer) {
CONFIG.rightContainer.fontSize = newConfig.rightContainer.fontSize || CONFIG.rightContainer.fontSize;
CONFIG.rightContainer.fontWeight = newConfig.rightContainer.fontWeight || CONFIG.rightContainer.fontWeight;
CONFIG.rightContainer.fontStyle = newConfig.rightContainer.fontStyle || CONFIG.rightContainer.fontStyle;
CONFIG.rightContainer.typewriterSpeed = newConfig.rightContainer.typewriterSpeed || CONFIG.rightContainer.typewriterSpeed;
// 应用到CSS
document.documentElement.style.setProperty('--right-font-size', CONFIG.rightContainer.fontSize);
document.documentElement.style.setProperty('--right-font-weight', CONFIG.rightContainer.fontWeight);
document.documentElement.style.setProperty('--right-font-style', CONFIG.rightContainer.fontStyle);
}
// 更新水波纹效果配置
if (newConfig.waterEffect) {
CONFIG.waterEffect.enabled = newConfig.waterEffect.enabled !== undefined ? newConfig.waterEffect.enabled : CONFIG.waterEffect.enabled;
CONFIG.waterEffect.minInterval = newConfig.waterEffect.minInterval || CONFIG.waterEffect.minInterval;
CONFIG.waterEffect.maxInterval = newConfig.waterEffect.maxInterval || CONFIG.waterEffect.maxInterval;
CONFIG.waterEffect.simultaneousDrops = newConfig.waterEffect.simultaneousDrops || CONFIG.waterEffect.simultaneousDrops;
CONFIG.waterEffect.fadeOutSpeed = newConfig.waterEffect.fadeOutSpeed || CONFIG.waterEffect.fadeOutSpeed;
CONFIG.waterEffect.centerBias = newConfig.waterEffect.centerBias !== undefined ? newConfig.waterEffect.centerBias : CONFIG.waterEffect.centerBias;
if (newConfig.waterEffect.largeDrop) {
CONFIG.waterEffect.largeDrop.probability = newConfig.waterEffect.largeDrop.probability !== undefined ?
newConfig.waterEffect.largeDrop.probability : CONFIG.waterEffect.largeDrop.probability;
CONFIG.waterEffect.largeDrop.size = newConfig.waterEffect.largeDrop.size || CONFIG.waterEffect.largeDrop.size;
}
// 应用水波纹效果配置
if ($('.water-effect').data('ripples')) {
// 如果ripples已初始化先销毁
$('.water-effect').ripples('destroy');
}
if (CONFIG.waterEffect.enabled) {
$('.water-effect').show();
$('.water-effect').ripples({
resolution: 1024,
dropRadius: 1.5,
perturbance: 0
});
} else {
$('.water-effect').hide();
}
}
console.log("配置已更新:", CONFIG);
}
// 页面加载完成后初始化
$(window).ready(function () {
$('#magazine').turn({

View File

@ -10,6 +10,9 @@
</PropertyGroup>
<ItemGroup>
<Content Update="config.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\js\jquery.ripples.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

View File

@ -0,0 +1,25 @@
{
"leftContainer": {
"turnPageHeight": 0.55,
"fontSize": "16px",
"typewriterSpeed": 50
},
"rightContainer": {
"fontSize": "40px",
"fontWeight": "700",
"fontStyle": "italic",
"typewriterSpeed": 330
},
"waterEffect": {
"enabled": true,
"minInterval": 1600,
"maxInterval": 8000,
"simultaneousDrops": 2,
"fadeOutSpeed": 2000,
"centerBias": 0.6,
"largeDrop": {
"probability": 0.2,
"size": 80
}
}
}