416 lines
15 KiB
C#
416 lines
15 KiB
C#
using AntDesign;
|
||
using AntDesign.TableModels;
|
||
using FreeRedis;
|
||
using Microsoft.Extensions.DependencyModel;
|
||
using SqlSugar;
|
||
using SqlSugar.IOC;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using System.Runtime.Loader;
|
||
using System.Text;
|
||
using System.Text.RegularExpressions;
|
||
using System.Threading.Tasks;
|
||
using UserCenter.Model.Interface;
|
||
using VideoAnalysisCore.AICore.SherpaOnnx;
|
||
using VideoAnalysisCore.Enum;
|
||
using VideoAnalysisCore.Interface;
|
||
using VideoAnalysisCore.Model.Dto;
|
||
using Whisper.net;
|
||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||
|
||
namespace VideoAnalysisCore.Common
|
||
{
|
||
|
||
/// <summary>
|
||
/// 程序 公共变量
|
||
/// </summary>
|
||
public static class AppCommon
|
||
{
|
||
/// <summary>
|
||
/// 应用有效程序集
|
||
/// </summary>
|
||
public static readonly IEnumerable<Assembly> Assemblies;
|
||
/// <summary>
|
||
/// 主库数据库表类型
|
||
/// </summary>
|
||
public static readonly IEnumerable<Type> DbMatserType;
|
||
public static readonly IEnumerable<Type> KnowsType;
|
||
static AppCommon()
|
||
{
|
||
try
|
||
{
|
||
Assemblies = ExpandFunction.GetAssemblies();
|
||
var assembliesType = Assemblies.Where(s => s.FullName.Contains("VideoAnalysis")).SelectMany(s => s.ExportedTypes
|
||
.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false)));
|
||
DbMatserType = assembliesType
|
||
.Where(u => u.GetInterfaces().Contains(typeof(IDB)));
|
||
KnowsType = assembliesType
|
||
.Where(u =>u.GetInterfaces().Contains(typeof(IKnowsDB)));
|
||
}
|
||
catch
|
||
{
|
||
throw;
|
||
}
|
||
//.Where(u => !u.IsDefined(typeof(SplitTableAttribute), false))
|
||
//.Where(u => !typeof(Model.DataCenterYH.IDataCenterYHModel).IsAssignableFrom(u))
|
||
//.Where(u => !u.IsSubclassOf(typeof(YQ_BaseEntity)));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 程序配置
|
||
/// </summary>
|
||
public static AppConfig Config = new AppConfig();
|
||
/// <summary>
|
||
/// ServiceProvider
|
||
/// </summary>
|
||
public static IServiceProvider? Services;
|
||
/// <summary>
|
||
/// 文件下载路径
|
||
/// </summary>
|
||
public static string TaskCachedFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TaskCachedFile");
|
||
|
||
/// <summary>
|
||
/// 模型地址
|
||
/// </summary>
|
||
public static string AIModelFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AICore", "_Static");
|
||
|
||
|
||
/// <summary>
|
||
/// 获取视频路径
|
||
/// </summary>
|
||
/// <param name="tid"></param>
|
||
/// <returns></returns>
|
||
public static string GetVideoPath(string tid) => $"./video/{tid}/{tid}.mp4";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 拓展函数
|
||
/// </summary>
|
||
public static class ExpandFunction
|
||
{
|
||
static Dictionary<string, string> FormulaData = new Dictionary<string, string>()
|
||
{
|
||
{ "阿尔法","α"},
|
||
{ "贝塔","β"},
|
||
{ "伽马","γ"},
|
||
{ "德尔塔","Δ"},
|
||
{ "派","π"},
|
||
{ "西格马","∑"},
|
||
{ "欧米伽","Ω"},
|
||
{ "普西","Ψ"},
|
||
};
|
||
static string FormulaDataKey = string.Join("|", FormulaData.Keys);
|
||
/// <summary>
|
||
/// 处理数学公式
|
||
/// </summary>
|
||
/// <param name="f"></param>
|
||
/// <returns></returns>
|
||
public static string HandleFormula(string f)
|
||
{
|
||
if (string.IsNullOrEmpty(f))
|
||
return f;
|
||
return Regex.Replace(f, FormulaDataKey,
|
||
match =>
|
||
FormulaData[match.Value]
|
||
);
|
||
}
|
||
/// <summary>
|
||
/// 转换 ant 查询枚举 到 sqlsuger枚举
|
||
/// </summary>
|
||
/// <param name="filterOperator">ant 查询枚举</param>
|
||
/// <returns></returns>
|
||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||
public static ConditionalType ConvertToConditionalType(TableFilterCompareOperator filterOperator)
|
||
{
|
||
return filterOperator switch
|
||
{
|
||
TableFilterCompareOperator.Equals => ConditionalType.Equal,
|
||
TableFilterCompareOperator.Contains => ConditionalType.Like,
|
||
TableFilterCompareOperator.StartsWith => ConditionalType.LikeLeft,
|
||
TableFilterCompareOperator.EndsWith => ConditionalType.LikeRight,
|
||
TableFilterCompareOperator.GreaterThan => ConditionalType.GreaterThan,
|
||
TableFilterCompareOperator.LessThan => ConditionalType.LessThan,
|
||
TableFilterCompareOperator.GreaterThanOrEquals => ConditionalType.GreaterThanOrEqual,
|
||
TableFilterCompareOperator.LessThanOrEquals => ConditionalType.LessThanOrEqual,
|
||
TableFilterCompareOperator.Condition => ConditionalType.In,
|
||
TableFilterCompareOperator.NotEquals => ConditionalType.NoEqual,
|
||
TableFilterCompareOperator.IsNull => ConditionalType.IsNullOrEmpty,
|
||
TableFilterCompareOperator.IsNotNull => ConditionalType.IsNot,
|
||
TableFilterCompareOperator.NotContains => ConditionalType.NoLike,
|
||
TableFilterCompareOperator.TheSameDateWith => ConditionalType.EqualNull,
|
||
TableFilterCompareOperator.Between => ConditionalType.Range,
|
||
_ => throw new ArgumentOutOfRangeException(nameof(filterOperator), filterOperator, "未知的枚举类型!")
|
||
};
|
||
}
|
||
public static List<IConditionalModel> ToSqlSugerWhere(this QueryModel qm )
|
||
{
|
||
return qm.FilterModel.SelectMany(s => s.Filters.Select(x => new ConditionalModel()
|
||
{
|
||
FieldName = s.FieldName,
|
||
ConditionalType = ConvertToConditionalType( x.FilterCompareOperator),
|
||
FieldValue = x.Value.GetType().IsEnum?((int)x.Value).ToString() : x.Value.ToString(),
|
||
} as IConditionalModel)).ToList();
|
||
}
|
||
/// <summary>
|
||
/// 获取应用有效程序集
|
||
/// </summary>
|
||
/// <returns>IEnumerable</returns>
|
||
public static List<Assembly> GetAssemblies()
|
||
{
|
||
// 获取当前解决方案的所有程序集
|
||
var assembliesStr = DependencyContext.Default.RuntimeLibraries
|
||
.Where(u => !u.Name.StartsWith(nameof(Microsoft))
|
||
&& !u.Name.StartsWith(nameof(System))
|
||
&& !u.Name.StartsWith("netstandard")
|
||
&& (u.Type == "project"));
|
||
|
||
var assemblies = assembliesStr.Select(a => AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(a.Name))).ToList();
|
||
var assemblies1 = Assembly.GetEntryAssembly().GetReferencedAssemblies().Where(x => x.Name.StartsWith("App.") || x.Name.StartsWith("UserCenter."))
|
||
.Select(a => AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(a.Name))).ToList();
|
||
foreach (var item in assemblies1)
|
||
{
|
||
if (!assemblies.Contains(item))
|
||
assemblies.Add(item);
|
||
}
|
||
return assemblies;
|
||
}
|
||
/// <summary>
|
||
/// 获取Task处理后的 说话人字幕
|
||
/// </summary>
|
||
public static TotalCaptionsDto GetSpeakerCaptions(string task)
|
||
{
|
||
var captionsArr = RedisExpand.Redis.HMGet<SenseVoiceRes[]>(RedisExpandKey.Task(task), "Captions").FirstOrDefault();
|
||
var speakerArr = RedisExpand.Redis.HMGet<OfflineSpeakerRes[]>(RedisExpandKey.Task(task), "Speaker").FirstOrDefault();
|
||
if (captionsArr is null || captionsArr.Length == 0)
|
||
//|| speakerArr is null || speakerArr.Length == 0)
|
||
throw new Exception("音频解析数据异常");
|
||
// 教师说话人Id
|
||
var techerId = speakerArr is null || !speakerArr.Any()
|
||
? 0
|
||
:speakerArr.GroupBy(s=>s.SpeakerIndex).Select(s => (s.Key,s.Sum(x=>x.Total)))
|
||
.OrderByDescending(s=>s.Item2).First().Key;
|
||
var teacherSpeaking = 0f;
|
||
var studentSpeaking = 0f;
|
||
var results = new Dictionary<SenseVoiceRes, List<int>>();
|
||
if (speakerArr is null || speakerArr.Count() == 0)
|
||
{
|
||
var ss = new List<int> { 1 };
|
||
results = captionsArr.ToDictionary(s => s, s=> ss);
|
||
}
|
||
else
|
||
{
|
||
foreach (var segment in captionsArr)
|
||
{
|
||
var spList = new List<int>();
|
||
foreach (var speakerRes in speakerArr)
|
||
{
|
||
if (speakerRes.Start > segment.End)
|
||
break;
|
||
if (segment.Start <= speakerRes.End
|
||
&& segment.End >= speakerRes.Start)
|
||
{
|
||
if (speakerRes.SpeakerIndex == techerId)
|
||
teacherSpeaking += speakerRes.Total;
|
||
else
|
||
studentSpeaking += speakerRes.Total;
|
||
spList.Add(speakerRes.SpeakerIndex);
|
||
}
|
||
}
|
||
var sp = spList.Distinct().ToList();
|
||
if (sp.Count > 0)
|
||
results.Add(segment, sp);
|
||
}
|
||
|
||
}
|
||
//拼接 提示词字幕源
|
||
var stringBuilder = new StringBuilder();
|
||
foreach (var item in results)
|
||
{
|
||
stringBuilder.Append(item.Value.First());
|
||
stringBuilder.Append(":");
|
||
stringBuilder.Append(item.Key.Start);
|
||
stringBuilder.Append(":");
|
||
stringBuilder.Append(item.Key.End);
|
||
stringBuilder.Append(":");
|
||
stringBuilder.Append(item.Key.Text);
|
||
stringBuilder.Append("|");
|
||
}
|
||
return new TotalCaptionsDto
|
||
{
|
||
StudentSpeaking = (decimal)studentSpeaking,
|
||
TeacherSpeaking = (decimal)teacherSpeaking,
|
||
Captions = stringBuilder.ToString(),
|
||
TimeBase = results.Select(s=>new TimeBase()
|
||
{
|
||
Start = s.Key.Start,
|
||
End = s.Key.End,
|
||
Content = s.Key.Text,
|
||
TimeBaseType = s.Value.Count == 1 && s.Value.First() == techerId
|
||
? TimeBaseTypeEnum.教师讲授
|
||
: TimeBaseTypeEnum.互动交流
|
||
})
|
||
};
|
||
}
|
||
/// <summary>
|
||
/// 转化枚举
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
/// <returns></returns>
|
||
public static T? ToEnum<T>(this object data) where T : struct, System.Enum
|
||
{
|
||
try
|
||
{
|
||
if (data is null || string.IsNullOrEmpty(data?.ToString()))
|
||
return null;
|
||
return System.Enum.Parse<T>(data.ToString());
|
||
}
|
||
catch (Exception)
|
||
{
|
||
return null;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 转化本地缓存目录
|
||
/// </summary>
|
||
/// <param name="taskId">任务id</param>
|
||
/// <returns></returns>
|
||
public static string LocalPath(this string taskId)
|
||
{
|
||
return Path.Combine(AppCommon.TaskCachedFile, taskId);
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// ffmpeg配置
|
||
/// </summary>
|
||
public class GptConfig
|
||
{
|
||
/// <summary>
|
||
/// 请求 公开的服务地址
|
||
/// </summary>
|
||
public string Host { get; set; } = string.Empty;
|
||
/// <summary>
|
||
/// api的密钥
|
||
/// </summary>
|
||
public string ApiKey { get; set; } = string.Empty;
|
||
}
|
||
/// <summary>
|
||
/// 文本模型 配置
|
||
/// </summary>
|
||
public class ChatGptConfig
|
||
{
|
||
/// <summary>
|
||
/// KIMI
|
||
/// <para></para>
|
||
/// </summary>
|
||
public GptConfig ChatGpt { get; set; } = new GptConfig();
|
||
public GptConfig KIMI { get; set; } = new GptConfig();
|
||
}
|
||
|
||
/// <summary>
|
||
/// ffmpeg配置
|
||
/// </summary>
|
||
public class FFmpegConfig
|
||
{
|
||
/// <summary>
|
||
/// 音频切片时间段
|
||
/// <para>0不切片</para>
|
||
/// </summary>
|
||
public int TimeSlice { get; set; } = 0;
|
||
}
|
||
/// <summary>
|
||
/// Whisper配置
|
||
/// </summary>
|
||
public class WhisperConfig
|
||
{
|
||
/// <summary>
|
||
/// 模型名称
|
||
/// </summary>
|
||
public string ModelName { get; set; } = string.Empty;
|
||
|
||
}
|
||
/// <summary>
|
||
/// 管理界面Admin账号
|
||
/// </summary>
|
||
public class AdminConfig
|
||
{
|
||
/// <summary>
|
||
/// 账号
|
||
/// </summary>
|
||
public string Account { get; set; } = string.Empty;
|
||
/// <summary>
|
||
/// 密码
|
||
/// </summary>
|
||
public string Password { get; set; } = string.Empty;
|
||
}
|
||
/// <summary>
|
||
/// redis配置
|
||
/// </summary>
|
||
public class RedisConfig
|
||
{
|
||
/// <summary>
|
||
/// redis连接字符串
|
||
/// </summary>
|
||
public string ConnectionString { get; set; } = string.Empty;
|
||
}
|
||
|
||
public class DBConfig
|
||
{
|
||
/// <summary>
|
||
/// 主库链接
|
||
/// </summary>
|
||
public string ConnectionString { get; set; }=string.Empty;
|
||
/// <summary>
|
||
/// 数据库类型
|
||
/// </summary>
|
||
public IocDbType SqlType { get; set; }
|
||
/// <summary>
|
||
/// 启动时更新表结构
|
||
/// </summary>
|
||
public bool UpdateTable { get; set; }
|
||
|
||
}
|
||
/// <summary>
|
||
/// 应用程序配置
|
||
/// </summary>
|
||
public class AppConfig
|
||
{
|
||
/// <summary>
|
||
/// 程序ID
|
||
/// </summary>
|
||
public string ID { get; set; } = string.Empty;
|
||
/// <summary>
|
||
/// Admin
|
||
/// </summary>
|
||
public AdminConfig Admin { get; set; } = new AdminConfig();
|
||
/// <summary>
|
||
/// redis
|
||
/// </summary>
|
||
public RedisConfig Redis { get; set; } = new RedisConfig();
|
||
/// <summary>
|
||
/// Whisper AI
|
||
/// </summary>
|
||
public WhisperConfig Whisper { get; set; } = new WhisperConfig();
|
||
/// <summary>
|
||
/// FFmpeg
|
||
/// </summary>
|
||
public FFmpegConfig FFmpeg { get; set; } = new FFmpegConfig();
|
||
/// <summary>
|
||
/// ChatGpt
|
||
/// </summary>
|
||
public ChatGptConfig ChatGpt { get; set; } = new ChatGptConfig();
|
||
/// <summary>
|
||
/// 数据库配置
|
||
/// </summary>
|
||
public DBConfig DB { get; set; } = new DBConfig();
|
||
/// <summary>
|
||
/// 知识点数据库
|
||
/// </summary>
|
||
public DBConfig KnowsDB { get; set; } = new DBConfig();
|
||
|
||
}
|
||
}
|