优化 数据存储同步到数据库

This commit is contained in:
小肥羊 2025-02-27 18:28:12 +08:00
parent c12c8ebfcd
commit 1b239201a2
11 changed files with 184 additions and 26 deletions

View File

@ -19,14 +19,16 @@ namespace Learn.VideoAnalysis.Controllers
private readonly ILogger<ApiController> _logger;
private readonly IMapper mp;
private readonly Repository<VideoTask> videoTaskDB;
private readonly Repository<VideoKonwPoint> videoKonwDB;
private readonly IBserGPT chatGPT;
public ApiController(ILogger<ApiController> logger, Repository<VideoTask> videoTaskDB,
IMapper mp, IBserGPT chatGPT)
IMapper mp, IBserGPT chatGPT, Repository<VideoKonwPoint> videoKonwDB)
{
_logger = logger;
this.videoTaskDB = videoTaskDB;
this.mp = mp;
this.chatGPT = chatGPT;
this.videoKonwDB = videoKonwDB;
}
private string GetClientIpAddress()
@ -151,6 +153,53 @@ namespace Learn.VideoAnalysis.Controllers
, task.Id);
return Ok();
}
/// <summary>
/// 获取视频知识点片段<para>taskId/tagId二选一</para>
/// </summary>
/// <param name="taskId"></param>
/// <param name="tagId">自定义id</param>
/// <returns></returns>
[HttpGet(Name = "TaskKnowInfo")]
public async Task<IActionResult> TaskKnowInfo(long taskId, string? tagId)
{
if (taskId == 0 && string.IsNullOrEmpty(tagId))
return BadRequest();
var task = await videoTaskDB.AsQueryable()
.WhereIF(taskId != 0, s => s.Id == taskId)
.WhereIF(!string.IsNullOrEmpty(tagId), s => s.TagId == tagId)
.FirstAsync();
if(task is null)
return BadRequest("无效任务");
var konwArr = await videoKonwDB.AsQueryable()
.Where(s=>s.VideoTaskId == task.Id)
.ToArrayAsync();
if (konwArr is null || konwArr.Length ==0)
return BadRequest("无效任务");
return Ok(new TaskKnowRes()
{
TagId = task.TagId,
Status = task.LastEnum,
VideoTaskId = task.Id,
KnowBlockArr = konwArr
.GroupBy(s=>s.StartTime)
.Select(s=>new TaskKnowBlock()
{
Id = s.First().Id,
Content = s.First().Content,
StartTime = s.First().StartTime,
EndTime = s.First().EndTime,
Theme =s.First().Theme,
Know=s.Select(x=>new TaskKnowInfo()
{
Id=x.Id,
KnowPoint=x.KnowPoint,
KnowPointId = x.KnowPointId
}).ToArray()
}).ToArray()
});
}
/// <summary>
/// »ñÈ¡ÊÓÆµÐÅÏ¢<para>taskId/tagId¶þѡһ</para>
/// </summary>

View File

@ -1,4 +1,5 @@
using AntDesign;
using SqlSugar;
using System.ComponentModel.DataAnnotations;
using UserCenter.Model.Enum;
using VideoAnalysisCore.AICore.GPT.Dto;
@ -71,6 +72,76 @@ namespace Learn.VideoAnalysis.Controllers.Dto
public string Text { get; set; }
public object Value { get; set; }
}
public class TaskKnowInfo
{
/// <summary>
///视频片段知识点 id
/// </summary>
public long Id { get; set; }
/// <summary>
/// 知识点
/// </summary>
public string KnowPoint { get; set; }
/// <summary>
/// 知识点ID
/// </summary>
public string KnowPointId { get; set; }
}
public class TaskKnowBlock
{
public long Id { get; set; }
/// <summary>
/// 开始时间
/// </summary>
public float? StartTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
public float? EndTime { get; set; }
/// <summary>
/// 持续时间
/// </summary>
[SugarColumn(IsIgnore = true)]
public float? KeepTime => (EndTime ?? 0) - StartTime ?? 0;
/// <summary>
/// 主题
/// </summary>
public string? Theme { get; set; }
/// <summary>
/// 内容总结
/// </summary>
public string? Content { get; set; }
/// <summary>
/// 知识点列表
/// </summary>
public TaskKnowInfo[] Know { get; set; }
}
/// <summary>
/// 视频片段知识点结果
/// </summary>
public class TaskKnowRes
{
/// <summary>
/// 自定义Id [任务视频自定义id]
/// <see cref="VideoTask.TagId"/>
/// </summary>
public string? TagId { get; set; }
/// <summary>
/// 任务当前执行状态
/// </summary>
public RedisChannelEnum Status { get; set; }
/// <summary>
/// 视频任务id
/// </summary>
public long VideoTaskId { get; set; }
/// <summary>
/// 视频知识快
/// </summary>
public TaskKnowBlock[] KnowBlockArr { get; set; }
}
public class TaskInfoRes: TaskRes
{
public TaskInfoRes()
@ -81,19 +152,19 @@ namespace Learn.VideoAnalysis.Controllers.Dto
/// 任务当前执行状态
/// </summary>
public RedisChannelEnum Status { get; set; }
/// <summary>
/// 时间轴状态枚举
/// </summary>
public Dictionary<int, string> TimeTypeEnum =>
Enum.GetValues(typeof(TimeBaseTypeEnum))
.Cast<TimeBaseTypeEnum>()
.ToDictionary(x => (int)x, x => x.ToString());
///// <summary>
///// 时间轴状态枚举
///// </summary>
//public Dictionary<int, string> TimeTypeEnum =>
// Enum.GetValues(typeof(TimeBaseTypeEnum))
// .Cast<TimeBaseTypeEnum>()
// .ToDictionary(x => (int)x, x => x.ToString());
/// <summary>
/// 时间轴合计
/// </summary>
public Dictionary<TimeBaseTypeEnum, TextValue>? TimeBaseTotal =>
TimeBase?.GroupBy(s => s.TimeBaseType??TimeBaseTypeEnum.)?
.ToDictionary(s => s.Key, s => new TextValue(s.Sum(x => x.End - x.Start)));
///// <summary>
///// 时间轴合计
///// </summary>
//public Dictionary<TimeBaseTypeEnum, TextValue>? TimeBaseTotal =>
// TimeBase?.GroupBy(s => s.TimeBaseType??TimeBaseTypeEnum.教师讲授)?
// .ToDictionary(s => s.Key, s => new TextValue(s.Sum(x => x.End - x.Start)));
}
}

View File

@ -6,6 +6,8 @@ using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
using System.Xml.Linq;
using System.Runtime.InteropServices;
using SqlSugar.IOC;
using VideoAnalysisCore.Model;
namespace VideoAnalysisCore.AICore.FFMPGE
{
@ -30,7 +32,10 @@ namespace VideoAnalysisCore.AICore.FFMPGE
public static async Task Audio2WAV16KAsync(string task)
{
Task = task;
var filePath = RedisExpand.Redis.HGet(RedisExpandKey.Task(task), "LocalMediaPath");
var filePath = await DbScoped.SugarScope
.Queryable<VideoTask>()
.Where(s => s.Id == long.Parse(task))
.Select(s=>s.LocalMediaPath).FirstAsync();
if (string.IsNullOrEmpty(filePath))
throw new Exception($"任务id[{task}] 无效");

View File

@ -9,6 +9,7 @@ using VideoAnalysisCore.Model.Dto;
using VideoAnalysisCore.AICore.GPT.Dto;
using VideoAnalysisCore.AICore.GPT;
using System.Threading.Tasks;
using VideoAnalysisCore.AICore.SherpaOnnx;
namespace VideoAnalysisCore.AICore.GPT.ChatGPT
{
@ -89,7 +90,10 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
$"输出格式 json字符串 对象格式{fileNameResFormat}";
var fileNameInfoRes = await ChatAsync<FileNameInfo>(task, fileNamePostMessages, null, fileNameResFormat);
var captions = ExpandFunction.GetSpeakerCaptions(task);
var speakerArr = JsonSerializer.Deserialize<OfflineSpeakerRes[]>(taskInfo.Speaker);
var captionsArr = JsonSerializer.Deserialize<SenseVoiceRes[]>(taskInfo.Captions);
var captions = ExpandFunction.GetSpeakerCaptions(captionsArr, speakerArr);
var maxVideoTime = captions?.TimeBase?.LastOrDefault()?.End ?? 0;
var criteriaBuilder = new StringBuilder();
@ -245,7 +249,10 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
var taskInfo = await videoTaskDB.AsQueryable()
.Where(s => s.Id == taskId)
.FirstAsync();
var captions = ExpandFunction.GetSpeakerCaptions(task);
var speakerArr = JsonSerializer.Deserialize<OfflineSpeakerRes[]>(taskInfo.Speaker);
var captionsArr = JsonSerializer.Deserialize<SenseVoiceRes[]>(taskInfo.Captions);
var captions = ExpandFunction.GetSpeakerCaptions(captionsArr, speakerArr);
var criteriaArr = await criteriaDB.GetListAsync(s => s.Subject == taskInfo.Subject);
var criteriaBuilder = new StringBuilder();
foreach (var item in criteriaArr)

View File

@ -9,6 +9,7 @@ using VideoAnalysisCore.Model.Dto;
using VideoAnalysisCore.AICore.GPT.Dto;
using System.Threading.Tasks;
using VideoAnalysisCore.AICore.GPT.ChatGPT;
using VideoAnalysisCore.AICore.SherpaOnnx;
namespace VideoAnalysisCore.AICore.GPT.DeepSeek
{
@ -62,7 +63,9 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
$"输出格式 json字符串 对象格式{fileNameResFormat}";
var fileNameInfoRes = await ChatAsync<FileNameInfo>(task, fileNamePostMessages, null);//, "deepseek-chat");
var captions = ExpandFunction.GetSpeakerCaptions(task);
var speakerArr = JsonSerializer.Deserialize<OfflineSpeakerRes[]>(taskInfo.Speaker);
var captionsArr = JsonSerializer.Deserialize<SenseVoiceRes[]>(taskInfo.Captions);
var captions = ExpandFunction.GetSpeakerCaptions(captionsArr, speakerArr);
var maxVideoTime = captions?.TimeBase?.LastOrDefault()?.End ?? 0;
var criteriaBuilder = new StringBuilder();

View File

@ -53,7 +53,9 @@ namespace VideoAnalysisCore.AICore.GPT.KIMI
var taskInfo = await videoTaskDB.AsQueryable()
.Where(s => s.Id == taskId)
.FirstAsync();
var captions = ExpandFunction.GetSpeakerCaptions(task);
var speakerArr = JsonSerializer.Deserialize<OfflineSpeakerRes[]>(taskInfo.Speaker);
var captionsArr = JsonSerializer.Deserialize<SenseVoiceRes[]>(taskInfo.Captions);
var captions = ExpandFunction.GetSpeakerCaptions(captionsArr, speakerArr);
var criteriaArr = await criteriaDB.GetListAsync(s => s.Subject == taskInfo.Subject);
var criteriaBuilder = new StringBuilder();
foreach (var item in criteriaArr)

View File

@ -1,14 +1,17 @@
using Microsoft.Extensions.Options;
using SherpaOnnx;
using SqlSugar.IOC;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using VideoAnalysisCore.Common;
using VideoAnalysisCore.Model;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace VideoAnalysisCore.AICore.SherpaOnnx
@ -256,6 +259,12 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
}
Console.WriteLine(DateTime.Now + "=> SenseVoice 字幕数量"+ res.Count);
var captionsStr = JsonSerializer.Serialize(res);
DbScoped.SugarScope
.Updateable<VideoTask>()
.SetColumns(it => it.Captions == captionsStr)
.Where(it => it.Id == long.Parse(task));
await RedisExpand.Redis.HMSetAsync(RedisExpandKey.Task(task), "Captions", res);
//RedisExpand.InsertChannel(Enum.RedisChannelEnum.ParsingSpeaker, task);
RedisExpand.InsertChannel(Enum.RedisChannelEnum.ChatModelAnalysis, task);

View File

@ -4,6 +4,9 @@ using System.Linq;
using System.Text.Json.Serialization;
using VideoAnalysisCore.Common;
using SherpaOnnx;
using SqlSugar.IOC;
using VideoAnalysisCore.Model;
using System.Text.Json;
namespace VideoAnalysisCore.AICore.SherpaOnnx
{
@ -72,6 +75,11 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
}, nint.Zero);
var res = segments.Select(s => new OfflineSpeakerRes(s));
await RedisExpand.Redis.HSetAsync(RedisExpandKey.Task(task), "Speaker", res);
var speakerStr = JsonSerializer.Serialize(res);
DbScoped.SugarScope
.Updateable<VideoTask>()
.SetColumns(it => it.Speaker == speakerStr)
.Where(it => it.Id == long.Parse(task));
//加入下一队列
RedisExpand.InsertChannel(Enum.RedisChannelEnum.ChatModelAnalysis, task);

View File

@ -178,10 +178,8 @@ namespace VideoAnalysisCore.Common
/// <summary>
/// 获取Task处理后的 说话人字幕
/// </summary>
public static TotalCaptionsDto GetSpeakerCaptions(string task)
public static TotalCaptionsDto GetSpeakerCaptions(SenseVoiceRes[] captionsArr, OfflineSpeakerRes[] speakerArr)
{
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("音频解析数据异常");
@ -193,9 +191,9 @@ namespace VideoAnalysisCore.Common
var teacherSpeaking = 0f;
var studentSpeaking = 0f;
var results = new Dictionary<SenseVoiceRes, List<int>>();
var ss = new List<int> { 1 };
if (speakerArr is null || speakerArr.Count() == 0)
{
var ss = new List<int> { 1 };
results = captionsArr.ToDictionary(s => s, s=> ss);
}
else

View File

@ -1,11 +1,13 @@
using AntDesign;
using Downloader;
using SqlSugar.IOC;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using VideoAnalysisCore.Model;
namespace VideoAnalysisCore.Common
{
@ -122,7 +124,11 @@ namespace VideoAnalysisCore.Common
var outputPath = Path.Combine(localPath, task + fileExtension);
if (!Directory.Exists(localPath)) Directory.CreateDirectory(localPath);
RedisExpand.Redis.HSet(RedisExpandKey.Task(task), "LocalMediaPath", outputPath);
DbScoped.SugarScope
.Updateable<VideoTask>()
.SetColumns(it => it.LocalMediaPath == outputPath)
.Where(it => it.Id == long.Parse(task));
IDownload download = DownloadBuilder.New()
.WithUrl(fileUrl)
.WithDirectory(localPath)

View File

@ -12,7 +12,7 @@ using Whisper.net;
namespace VideoAnalysisCore.Model
{
/// <summary>
/// 视频任务知识片段
/// 视频片段知识点
/// </summary>
[SugarTable("videokonwpoint")]
public class VideoKonwPoint : IDB