Compare commits

..

No commits in common. "0edf143f8a552983f975628e383dbc303866c83f" and "6015245d78f2b53f087a8c0f570582023a750f74" have entirely different histories.

17 changed files with 241 additions and 358 deletions

View File

@ -2,9 +2,7 @@
using Learn.VideoAnalysis.API.Expand; using Learn.VideoAnalysis.API.Expand;
using Mapster; using Mapster;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using VideoAnalysisCore.AICore.FFMPGE;
using VideoAnalysisCore.AICore.GPT.DeepSeek; using VideoAnalysisCore.AICore.GPT.DeepSeek;
using VideoAnalysisCore.AICore.SherpaOnnx;
using VideoAnalysisCore.Common; using VideoAnalysisCore.Common;
using VideoAnalysisCore.Common.Expand; using VideoAnalysisCore.Common.Expand;
@ -39,12 +37,8 @@ namespace Learn.VideoAnalysis.API
builder.Services.AddHttpClient(); builder.Services.AddHttpClient();
builder.Services.AddSqlSugarExpand(); builder.Services.AddSqlSugarExpand();
builder.Services.AddRedisExpand(); builder.Services.AddRedisExpand();
builder.Services.AddCoravel(); builder.Services.AddCoravel();
builder.Services.AddCorsExpand(); builder.Services.AddCorsExpand();
builder.Services.AddDownloadFileExpand();
builder.Services.AddFFMPGEExpand();
builder.Services.AddSenseVoiceExpand();
builder.Services.AddHttpContextAccessor(); builder.Services.AddHttpContextAccessor();
builder.Services.AddControllersWithViews(options => builder.Services.AddControllersWithViews(options =>
{ {

View File

@ -120,7 +120,7 @@
"LastEnvName": "10楼刀片机", "LastEnvName": "10楼刀片机",
"RemoveDaysFromPublished": "10", "RemoveDaysFromPublished": "10",
"WorkDir": "/home/heyang/", "WorkDir": "/home/heyang/",
"Volume": "/home/hy/VideoAnalysis/AICore:/app/AICore/_Static;/mnt/2tb/VideoAnalysis/TaskCachedFile:/app/TaskCachedFile", "Volume": "/home/hy/VideoAnalysis/AICore:/app/AICore/_Static;/home/hy/VideoAnalysis/TaskCachedFile:/app/TaskCachedFile",
"Other": "-e va_args=\"\"", "Other": "-e va_args=\"\"",
"EnvPairList": [ "EnvPairList": [
{ {
@ -129,7 +129,7 @@
"LinuxEnvParam": null, "LinuxEnvParam": null,
"DockerPort": "9040", "DockerPort": "9040",
"DockerEnvName": "", "DockerEnvName": "",
"DockerVolume": "/home/hy/VideoAnalysis/AICore:/app/AICore/_Static;/mnt/2tb/VideoAnalysis/TaskCachedFile:/app/TaskCachedFile", "DockerVolume": "/home/hy/VideoAnalysis/AICore:/app/AICore/_Static;/home/hy/VideoAnalysis/TaskCachedFile:/app/TaskCachedFile",
"DockerOther": "-e va_args=\"\"" "DockerOther": "-e va_args=\"\""
}, },
{ {

View File

@ -23,8 +23,6 @@ namespace Learn.VideoAnalysis.Components.Pages
[Inject] private ConfirmService ComfirmService { get; set; } = default!; [Inject] private ConfirmService ComfirmService { get; set; } = default!;
[Inject] private Repository<VideoTask> taskDB { get; set; } = default!; [Inject] private Repository<VideoTask> taskDB { get; set; } = default!;
[Inject] private NavigationManager NavigationManager { get; set; } = default!; [Inject] private NavigationManager NavigationManager { get; set; } = default!;
[Inject] private RedisManager redisManager { get; set; } = default!;
[Inject] private INotificationService _notice { get; set; } = default!; [Inject] private INotificationService _notice { get; set; } = default!;
@ -56,7 +54,7 @@ namespace Learn.VideoAnalysis.Components.Pages
async void ReStartClick(VideoTaskDto query) async void ReStartClick(VideoTaskDto query)
{ {
selectDefaultValue = selectDefaultValue =
(await redisManager.Redis.HMGetAsync<int>(RedisExpandKey.Task(query.Id), "LastEnum")).FirstOrDefault(); (await RedisExpand.Redis.HMGetAsync<int>(RedisExpandKey.Task(query.Id), "LastEnum")).FirstOrDefault();
selectEnum = selectDefaultValue; selectEnum = selectDefaultValue;
reStartTask = query; reStartTask = query;
modalShow = true; modalShow = true;
@ -71,9 +69,9 @@ namespace Learn.VideoAnalysis.Components.Pages
/// <param name="query"></param> /// <param name="query"></param>
async void ReStart() async void ReStart()
{ {
await redisManager.ClearTaskError(reStartTask.Id); await RedisExpand.ClearTaskError(reStartTask.Id);
_=Task.Run(() => _=Task.Run(() =>
redisManager.InsertChannel((RedisChannelEnum)selectEnum, reStartTask.Id) RedisExpand.InsertChannel((RedisChannelEnum)selectEnum, reStartTask.Id)
); );
modalShow = false; modalShow = false;
} }
@ -127,7 +125,7 @@ namespace Learn.VideoAnalysis.Components.Pages
var item = rowData.Data; var item = rowData.Data;
if (item is null) if (item is null)
return; return;
var data = redisManager.Redis.HMGet<string>(RedisExpandKey.Task(item.Id), var data = RedisExpand.Redis.HMGet<string>(RedisExpandKey.Task(item.Id),
"Progress", "LastEnum", "StartTime", "ErrorMessage"); "Progress", "LastEnum", "StartTime", "ErrorMessage");
item.Progress = data[0]; item.Progress = data[0];
item.LastEnum = data[1] == null ?default:data[1].ToEnum<RedisChannelEnum>() ?? default; item.LastEnum = data[1] == null ?default:data[1].ToEnum<RedisChannelEnum>() ?? default;

View File

@ -32,7 +32,6 @@ namespace Learn.VideoAnalysis.Components.Pages
[Inject] private Repository<VideoQuestion> videoQuestionDB { get; set; } = default!; [Inject] private Repository<VideoQuestion> videoQuestionDB { get; set; } = default!;
[Inject] private Repository<VideoQuestionKonw> videoQuestionKonwDB { get; set; } = default!; [Inject] private Repository<VideoQuestionKonw> videoQuestionKonwDB { get; set; } = default!;
[Inject] private Repository<VideoKonwPoint> videoKonwPointDB { get; set; } = default!; [Inject] private Repository<VideoKonwPoint> videoKonwPointDB { get; set; } = default!;
[Inject] private RedisManager redisManager { get; set; } = default!;
[Inject] private IJSRuntime JSRuntime { get; set; } = default!; [Inject] private IJSRuntime JSRuntime { get; set; } = default!;
private VideoTask nowTask { get; set; } = default!; private VideoTask nowTask { get; set; } = default!;
@ -77,7 +76,7 @@ namespace Learn.VideoAnalysis.Components.Pages
return; return;
var captionsArr = JsonSerializer.Deserialize<SenseVoiceRes[]>(nowTask.Captions); var captionsArr = JsonSerializer.Deserialize<SenseVoiceRes[]>(nowTask.Captions);
var captionsArr1 = JsonSerializer.Deserialize<SenseVoiceRes[]>(nowTask.CaptionsAI??"[]") ; var captionsArr1 = JsonSerializer.Deserialize<SenseVoiceRes[]>(nowTask.CaptionsAI??"[]") ;
redisManager.Redis.HMGet<SenseVoiceRes[]>(RedisExpandKey.Task(taskId), "Captions").FirstOrDefault(); RedisExpand.Redis.HMGet<SenseVoiceRes[]>(RedisExpandKey.Task(taskId), "Captions").FirstOrDefault();
var konwArr = await videoKonwPointDB.AsQueryable() var konwArr = await videoKonwPointDB.AsQueryable()
.Where(s => s.VideoTaskId == nowTask.Id) .Where(s => s.VideoTaskId == nowTask.Id)

View File

@ -68,17 +68,13 @@ namespace Learn.VideoAnalysis
builder.Configuration.AddAppConfig(args); builder.Configuration.AddAppConfig(args);
builder.Services.AddSqlSugarExpand(); builder.Services.AddSqlSugarExpand();
builder.Services.AddRedisExpand();
builder.Services.AddSimpleTexOcrClient(); builder.Services.AddSimpleTexOcrClient();
builder.Services.AddDownloadFileExpand(); builder.Services.AddDownloadFileExpand();
builder.Services.AddFFMPGEExpand();
builder.Services.AddAlibabaCloudVod(); builder.Services.AddAlibabaCloudVod();
builder.Services.AddAliyunOSS(); builder.Services.AddAliyunOSS();
builder.Services.AddSenseVoiceExpand(); builder.Services.AddRedisExpand();
//builder.Services.AddSpeakerAI(); builder.Services.AddSpeakerAI();
builder.Services.AddCoravel(); builder.Services.AddCoravel();
//SenseVoice.Init(); //SenseVoice.Init();
//Òì³£¹ýÂËÆ÷ //Òì³£¹ýÂËÆ÷
builder.Services.AddControllersWithViews(options => builder.Services.AddControllersWithViews(options =>
@ -114,7 +110,6 @@ namespace Learn.VideoAnalysis
//builder.Services.AddSingleton<IBserGPT, Chat_GPT>(); //builder.Services.AddSingleton<IBserGPT, Chat_GPT>();
builder.Services.AddSingleton<IBserGPT, DeepSeek_GPT>(); builder.Services.AddSingleton<IBserGPT, DeepSeek_GPT>();
builder.Services.AddTaskSubscribe();
var app = builder.Build(); var app = builder.Build();
@ -124,7 +119,6 @@ namespace Learn.VideoAnalysis
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
_ = app.Services.GetRequiredService<RedisInit>();
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI(); app.UseSwaggerUI();
app.UseExceptionHandler("/Error"); app.UseExceptionHandler("/Error");

View File

@ -14,22 +14,9 @@ using SixLabors.ImageSharp.Processing;
using System.Text.Json; using System.Text.Json;
using System; using System;
using Microsoft.VisualBasic.FileIO; using Microsoft.VisualBasic.FileIO;
using Microsoft.Extensions.DependencyInjection;
namespace VideoAnalysisCore.AICore.FFMPGE namespace VideoAnalysisCore.AICore.FFMPGE
{ {
public static class FFMPGEExpand
{
/// <summary>
/// 添加跨域拓展
/// </summary>
/// <param name="services"></param>
public static void AddFFMPGEExpand(this IServiceCollection services)
{
services.AddSingleton<FFMPGEHandle>();
}
}
/// <summary> /// <summary>
/// Ffmpeg处理程序 /// Ffmpeg处理程序
/// </summary> /// </summary>
@ -41,27 +28,21 @@ namespace VideoAnalysisCore.AICore.FFMPGE
public static string FFmpegPath = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) public static string FFmpegPath = RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
? $"/usr/bin/ffmpeg" ? $"/usr/bin/ffmpeg"
: Path.Combine(AppCommon.AIModelFile, "ffmpeg.exe"); : Path.Combine(AppCommon.AIModelFile, "ffmpeg.exe");
private Repository<VideoTask> videoTaskDB { get; set; }
private RedisManager redisManager { get; set; }
public FFMPGEHandle(RedisManager redisManager, Repository<VideoTask> videoTaskDB)
{
this.redisManager = redisManager;
this.videoTaskDB = videoTaskDB;
}
/// <summary> /// <summary>
/// 识别视频关键帧 /// 识别视频关键帧
/// </summary> /// </summary>
/// <param name="task">任务id</param> /// <param name="task">任务id</param>
/// <returns></returns> /// <returns></returns>
public async Task VideoKeyFrames(string task) public static async Task VideoKeyFrames(string task)
{ {
var taskID = long.Parse(task); var taskID = long.Parse(task);
//间隔秒 //间隔秒
var intervalSec = 5; var intervalSec = 5;
var threshold = 8.15; var threshold = 8.15;
var ssimThreshold = 0.9; var ssimThreshold = 0.9;
var taskInfo = await videoTaskDB.AsQueryable() var taskInfo = await DbScoped.Sugar
.Queryable<VideoTask>()
.Where(s => s.Id == long.Parse(task)).FirstAsync(); .Where(s => s.Id == long.Parse(task)).FirstAsync();
if (string.IsNullOrEmpty(taskInfo.PPTVideoCode) || string.IsNullOrEmpty(taskInfo.PPTVideoUrl)) return; if (string.IsNullOrEmpty(taskInfo.PPTVideoCode) || string.IsNullOrEmpty(taskInfo.PPTVideoUrl)) return;
//视频切帧 //视频切帧
@ -74,11 +55,11 @@ namespace VideoAnalysisCore.AICore.FFMPGE
} }
var ffmpeg = new Engine(FFmpegPath); var ffmpeg = new Engine(FFmpegPath);
var cToken = new CancellationToken(); var cToken = new CancellationToken();
redisManager.SetTaskProgress(task, "Frame=>10%"); RedisExpand.SetTaskProgress(task, "Frame=>10%");
foreach (string jpgFile in Directory.GetFiles(localPath, "*.jpg")) foreach (string jpgFile in Directory.GetFiles(localPath, "*.jpg"))
FileSystem.DeleteFile(jpgFile, UIOption.OnlyErrorDialogs, RecycleOption.DeletePermanently); FileSystem.DeleteFile(jpgFile, UIOption.OnlyErrorDialogs, RecycleOption.DeletePermanently);
redisManager.SetTaskProgress(task, "Frame=>20%"); RedisExpand.SetTaskProgress(task, "Frame=>20%");
await ffmpeg.ExecuteAsync($"-i {filePath} -vf \"fps=1/{intervalSec},scale=960:540\" {localPath}/{ExpandFunction.FrameName}%03d.jpg", cToken); await ffmpeg.ExecuteAsync($"-i {filePath} -vf \"fps=1/{intervalSec},scale=960:540\" {localPath}/{ExpandFunction.FrameName}%03d.jpg", cToken);
@ -86,7 +67,7 @@ namespace VideoAnalysisCore.AICore.FFMPGE
var frameFiles = Directory.GetFiles(localPath, "*.jpg") var frameFiles = Directory.GetFiles(localPath, "*.jpg")
.OrderBy(f => f) .OrderBy(f => f)
.ToList(); .ToList();
redisManager.SetTaskProgress(task, "Frame=>80%"); RedisExpand.SetTaskProgress(task, "Frame=>80%");
Image<Rgb24> prevFrame = null; Image<Rgb24> prevFrame = null;
var keyFrames = new List<int>(10) { 5}; var keyFrames = new List<int>(10) { 5};
foreach (var frameFile in frameFiles) foreach (var frameFile in frameFiles)
@ -122,7 +103,8 @@ namespace VideoAnalysisCore.AICore.FFMPGE
} }
//写入数据库 //写入数据库
var keyFramStr = keyFrames.Where(s => s != -1).ToJson(); var keyFramStr = keyFrames.Where(s => s != -1).ToJson();
await videoTaskDB.AsUpdateable() await DbScoped.Sugar
.Updateable<VideoTask>()
.SetColumns(it => it.PPTKeyFrame == keyFramStr) .SetColumns(it => it.PPTKeyFrame == keyFramStr)
.Where(it => it.Id == taskID) .Where(it => it.Id == taskID)
.ExecuteCommandAsync(); .ExecuteCommandAsync();
@ -135,7 +117,7 @@ namespace VideoAnalysisCore.AICore.FFMPGE
/// <param name="img1"></param> /// <param name="img1"></param>
/// <param name="img2"></param> /// <param name="img2"></param>
/// <returns></returns> /// <returns></returns>
double CalculateFrameDifference(Image<Rgb24> img1, Image<Rgb24> img2) static double CalculateFrameDifference(Image<Rgb24> img1, Image<Rgb24> img2)
{ {
// 统一调整为64x64 // 统一调整为64x64
var resized1 = img1.Clone(x => x.Grayscale()); var resized1 = img1.Clone(x => x.Grayscale());
@ -154,7 +136,7 @@ namespace VideoAnalysisCore.AICore.FFMPGE
return diff / (double)(resized1.Width * resized1.Height); return diff / (double)(resized1.Width * resized1.Height);
} }
double GetTimestampFromFileName(string filePath) static double GetTimestampFromFileName(string filePath)
{ {
string fileName = Path.GetFileNameWithoutExtension(filePath); string fileName = Path.GetFileNameWithoutExtension(filePath);
return double.Parse(fileName.Split('_')[1]); return double.Parse(fileName.Split('_')[1]);
@ -164,7 +146,7 @@ namespace VideoAnalysisCore.AICore.FFMPGE
/// </summary> /// </summary>
/// <param name="task"></param> /// <param name="task"></param>
/// <returns></returns> /// <returns></returns>
public async Task RunAsync(string task) public static async Task RunAsync(string task)
{ {
await VideoKeyFrames(task); await VideoKeyFrames(task);
await Audio2WAV16KAsync(task); await Audio2WAV16KAsync(task);
@ -174,9 +156,10 @@ namespace VideoAnalysisCore.AICore.FFMPGE
/// </summary> /// </summary>
/// <param name="task">任务id</param> /// <param name="task">任务id</param>
/// <returns></returns> /// <returns></returns>
public async Task Audio2WAV16KAsync(string task) public static async Task Audio2WAV16KAsync(string task)
{ {
var filePath = await videoTaskDB.AsQueryable() var filePath = await DbScoped.Sugar
.Queryable<VideoTask>()
.Where(s => s.Id == long.Parse(task)) .Where(s => s.Id == long.Parse(task))
.Select(s=>s.LocalMediaPath).FirstAsync(); .Select(s=>s.LocalMediaPath).FirstAsync();
if (string.IsNullOrEmpty(filePath)) if (string.IsNullOrEmpty(filePath))

View File

@ -23,19 +23,17 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
private readonly Repository<CourseGradingCriteria> criteriaDB; private readonly Repository<CourseGradingCriteria> criteriaDB;
private readonly Repository<VideoTask> videoTaskDB; private readonly Repository<VideoTask> videoTaskDB;
private readonly Repository<KnowledgeInfo> knowledgeInfoDB; private readonly Repository<KnowledgeInfo> knowledgeInfoDB;
private readonly RedisManager redisManager;
/// <summary> /// <summary>
/// 初始化 /// 初始化
/// </summary> /// </summary>
/// <param name="moonshotClient"></param> /// <param name="moonshotClient"></param>
/// <param name="logger"></param> /// <param name="logger"></param>
public Chat_GPT(ChatGPTClient moonshotClient, Repository<CourseGradingCriteria> criteria, Repository<VideoTask> videoTaskDB, Repository<KnowledgeInfo> knowledgeInfoDB, RedisManager redisManager) public Chat_GPT(ChatGPTClient moonshotClient, Repository<CourseGradingCriteria> criteria, Repository<VideoTask> videoTaskDB, Repository<KnowledgeInfo> knowledgeInfoDB)
{ {
this.chatClient = moonshotClient; this.chatClient = moonshotClient;
criteriaDB = criteria; criteriaDB = criteria;
this.videoTaskDB = videoTaskDB; this.videoTaskDB = videoTaskDB;
this.knowledgeInfoDB = knowledgeInfoDB; this.knowledgeInfoDB = knowledgeInfoDB;
this.redisManager = redisManager;
} }
private static List<VideoKnowRes> MergeRes(VideoKnowRes[] timeBases) private static List<VideoKnowRes> MergeRes(VideoKnowRes[] timeBases)
@ -164,7 +162,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
item.EndTime = (int)(questionRes[i + 1]?.StartTime ?? 0) - 1; item.EndTime = (int)(questionRes[i + 1]?.StartTime ?? 0) - 1;
} }
await redisManager.Redis await RedisExpand.Redis
.HMSetAsync(RedisExpandKey.Task(task), "VideoKnows", questionRes); .HMSetAsync(RedisExpandKey.Task(task), "VideoKnows", questionRes);
//var postMessages1 = //var postMessages1 =
@ -183,7 +181,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
////questionRes1 = MergeRes(questionRes1).ToArray(); ////questionRes1 = MergeRes(questionRes1).ToArray();
var gptRes = new TaskRes(captions); var gptRes = new TaskRes(captions);
await redisManager.Redis await RedisExpand.Redis
.HMSetAsync(RedisExpandKey.Task(task), "ChatAnalysis", gptRes); .HMSetAsync(RedisExpandKey.Task(task), "ChatAnalysis", gptRes);
return gptRes; return gptRes;
} }
@ -205,13 +203,13 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
}; };
var time = DateTime.Now.ToString("MMddHHmmss"); var time = DateTime.Now.ToString("MMddHHmmss");
redisManager.SetTaskGPTCached(task, time,chatRep); RedisExpand.SetTaskGPTCached(task, time,chatRep);
var chatResp = await chatClient.Chat(chatRep); var chatResp = await chatClient.Chat(chatRep);
var chatResContent = chatResp?.res; var chatResContent = chatResp?.res;
if (string.IsNullOrEmpty(chatResContent)) if (string.IsNullOrEmpty(chatResContent))
throw new Exception("GPT返回message无效结果"); throw new Exception("GPT返回message无效结果");
if (chatResp != null) if (chatResp != null)
redisManager.SetTaskGPTCached(task, time, new object[] { chatResp.Value.res, chatResp.Value.u }); RedisExpand.SetTaskGPTCached(task, time, new object[] { chatResp.Value.res, chatResp.Value.u });
chatResContent = chatResContent?.Replace("字幕内容", "课堂情况"); chatResContent = chatResContent?.Replace("字幕内容", "课堂情况");
chatResContent = chatResContent?.Replace("\n", ""); chatResContent = chatResContent?.Replace("\n", "");
@ -309,13 +307,13 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
}; };
var time = DateTime.Now.ToString("MMddHHmmss"); var time = DateTime.Now.ToString("MMddHHmmss");
redisManager.SetTaskGPTCached(task, time, chatRep); RedisExpand.SetTaskGPTCached(task, time, chatRep);
var chatResp = await chatClient.Chat(chatRep); var chatResp = await chatClient.Chat(chatRep);
var chatResContent = chatResp?.res; var chatResContent = chatResp?.res;
if (string.IsNullOrEmpty(chatResContent)) if (string.IsNullOrEmpty(chatResContent))
throw new Exception("GPT返回message无效结果"); throw new Exception("GPT返回message无效结果");
if (chatResp != null) if (chatResp != null)
redisManager.SetTaskGPTCached(task, time, new object[] { chatResp.Value.res, chatResp.Value.u }); RedisExpand.SetTaskGPTCached(task, time, new object[] { chatResp.Value.res, chatResp.Value.u });
chatResContent = chatResContent?.Replace("字幕内容", "课堂情况"); chatResContent = chatResContent?.Replace("字幕内容", "课堂情况");
chatResContent = chatResContent?.Replace("\n", ""); chatResContent = chatResContent?.Replace("\n", "");
@ -415,7 +413,7 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
.ExecuteCommandAsync(); .ExecuteCommandAsync();
} }
await redisManager.Redis await RedisExpand.Redis
.HMSetAsync(RedisExpandKey.Task(task), "ChatAnalysis", gptRes); .HMSetAsync(RedisExpandKey.Task(task), "ChatAnalysis", gptRes);
return gptRes; return gptRes;

View File

@ -33,13 +33,10 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
//private readonly string Path = "v1/chat/completions"; //private readonly string Path = "v1/chat/completions";
private readonly IHttpClientFactory _httpClientFactory; private readonly IHttpClientFactory _httpClientFactory;
private readonly RedisManager redisManager;
public DeepSeekGPTClient(IHttpClientFactory httpClientFactory)
public DeepSeekGPTClient(IHttpClientFactory httpClientFactory, RedisManager redisManager)
{ {
_httpClientFactory = httpClientFactory; _httpClientFactory = httpClientFactory;
this.redisManager = redisManager;
} }
@ -195,7 +192,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
messageBuilder1.Append(strReasoning); messageBuilder1.Append(strReasoning);
var steamCount = messageBuilder.Length + messageBuilder1.Length; var steamCount = messageBuilder.Length + messageBuilder1.Length;
if (++threshold%30==0) if (++threshold%30==0)
redisManager.SetTaskProgress(chatReq.taskId, "steam=>"+ steamCount); RedisExpand.SetTaskProgress(chatReq.taskId, "steam=>"+ steamCount);
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -14,6 +14,7 @@ using VideoAnalysisCore.Model.Enum;
using Mapster; using Mapster;
using System.Linq; using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using static System.Collections.Specialized.BitVector32;
using FFmpeg.NET.Services; using FFmpeg.NET.Services;
using Aliyun.OSS; using Aliyun.OSS;
using Yitter.IdGenerator; using Yitter.IdGenerator;
@ -30,7 +31,6 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
{ {
private readonly DeepSeekGPTClient chatClient; private readonly DeepSeekGPTClient chatClient;
private readonly Repository<CourseGradingCriteria> criteriaDB; private readonly Repository<CourseGradingCriteria> criteriaDB;
private readonly RedisManager redisManager;
private readonly Repository<VideoTask> videoTaskDB; private readonly Repository<VideoTask> videoTaskDB;
private readonly Repository<VideoKonwPoint> videoKonwPointDB; private readonly Repository<VideoKonwPoint> videoKonwPointDB;
private readonly Repository<VideoQuestion> videoQuestionDB; private readonly Repository<VideoQuestion> videoQuestionDB;
@ -43,9 +43,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
/// </summary> /// </summary>
/// <param name="moonshotClient"></param> /// <param name="moonshotClient"></param>
/// <param name="logger"></param> /// <param name="logger"></param>
public DeepSeek_GPT(DeepSeekGPTClient moonshotClient, Repository<CourseGradingCriteria> criteria, Repository<VideoTask> videoTaskDB, public DeepSeek_GPT(DeepSeekGPTClient moonshotClient, Repository<CourseGradingCriteria> criteria, Repository<VideoTask> videoTaskDB, Repository<KnowledgeInfo> knowledgeInfoDB, Repository<VideoKonwPoint> videoKonwPointDB, SimpLetexClient simpLetexClient, Repository<VideoQuestion> videoQuestionDB, OssClient ossClient, Repository<VideoQuestionKonw> videoQuestionKonwDB)
Repository<KnowledgeInfo> knowledgeInfoDB, Repository<VideoKonwPoint> videoKonwPointDB, SimpLetexClient simpLetexClient,
Repository<VideoQuestion> videoQuestionDB, OssClient ossClient, Repository<VideoQuestionKonw> videoQuestionKonwDB, RedisManager redisManager)
{ {
chatClient = moonshotClient; chatClient = moonshotClient;
criteriaDB = criteria; criteriaDB = criteria;
@ -56,7 +54,6 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
this.videoQuestionDB = videoQuestionDB; this.videoQuestionDB = videoQuestionDB;
this.ossClient = ossClient; this.ossClient = ossClient;
this.videoQuestionKonwDB = videoQuestionKonwDB; this.videoQuestionKonwDB = videoQuestionKonwDB;
this.redisManager = redisManager;
} }
/// <summary> /// <summary>
/// 获取内容对应的章节 /// 获取内容对应的章节
@ -154,7 +151,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
.SetColumns(it => it.Sections == fileNameInfoRes.) .SetColumns(it => it.Sections == fileNameInfoRes.)
.Where(it => it.Id == taskInfo.Id) .Where(it => it.Id == taskInfo.Id)
.ExecuteCommandAsync(); .ExecuteCommandAsync();
await redisManager.Redis await RedisExpand.Redis
.HMSetAsync(RedisExpandKey.Task(task), "学科章节", fileNameInfoRes.); .HMSetAsync(RedisExpandKey.Task(task), "学科章节", fileNameInfoRes.);
return fileNameInfoRes?.; return fileNameInfoRes?.;
@ -357,7 +354,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
{ {
var time = title + DateTime.Now.ToString("MMddHHmmss"); var time = title + DateTime.Now.ToString("MMddHHmmss");
var redisCached = new object[2] { chatRep, null }; var redisCached = new object[2] { chatRep, null };
redisManager.SetTaskGPTCached(task, time, chatRep); RedisExpand.SetTaskGPTCached(task, time, chatRep);
var chatResp = await chatClient.Chat(chatRep); var chatResp = await chatClient.Chat(chatRep);
var chatResContent = chatResp?.res; var chatResContent = chatResp?.res;
if (string.IsNullOrEmpty(chatResContent)) if (string.IsNullOrEmpty(chatResContent))
@ -365,7 +362,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
if (chatResp != null) if (chatResp != null)
{ {
redisCached[1] = new object[] { chatResp.Value.res, chatResp.Value.u, chatResp.Value.reasoning }; redisCached[1] = new object[] { chatResp.Value.res, chatResp.Value.u, chatResp.Value.reasoning };
redisManager.SetTaskGPTCached(task, time, redisCached); RedisExpand.SetTaskGPTCached(task, time, redisCached);
} }
chatResContent = chatResContent?.ExtractJsonStrings()?.FirstOrDefault(); chatResContent = chatResContent?.ExtractJsonStrings()?.FirstOrDefault();
chatResContent = chatResContent?.Replace("\n", ""); chatResContent = chatResContent?.Replace("\n", "");
@ -607,7 +604,7 @@ namespace VideoAnalysisCore.AICore.GPT.DeepSeek
{ {
throw new Exception("重试次数过多!"); throw new Exception("重试次数过多!");
} }
await redisManager.Redis await RedisExpand.Redis
.HMSetAsync(RedisExpandKey.Task(task), "VideoKnows", questionRes); .HMSetAsync(RedisExpandKey.Task(task), "VideoKnows", questionRes);
return null; return null;

View File

@ -1,5 +1,4 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options;
using Microsoft.Extensions.Options;
using SherpaOnnx; using SherpaOnnx;
using SqlSugar.IOC; using SqlSugar.IOC;
using System; using System;
@ -18,40 +17,18 @@ using static System.Runtime.InteropServices.JavaScript.JSType;
namespace VideoAnalysisCore.AICore.SherpaOnnx namespace VideoAnalysisCore.AICore.SherpaOnnx
{ {
public static class SenseVoiceExpand public static class SenseVoice
{
/// <summary>
/// 添加 SenseVoice 语音转文字
/// </summary>
/// <param name="services"></param>
public static void AddSenseVoiceExpand(this IServiceCollection services)
{
services.AddSingleton<SenseVoice>();
}
}
public class SenseVoice
{ {
const string TransducerStr = "sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20"; const string TransducerStr = "sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20";
static OfflineRecognizer OR = default!; static OfflineRecognizer OR = default!;
//static VoiceActivityDetector VAD = default!; //static VoiceActivityDetector VAD = default!;
static VadModelConfig VADModelConfig = default!; static VadModelConfig VADModelConfig = default!;
public Repository<VideoTask> videoTaskDB { get; set; }
private readonly RedisManager redisManager;
public SenseVoice(Repository<VideoTask> videoTaskDB, RedisManager redisManager)
{
this.videoTaskDB = videoTaskDB;
this.redisManager = redisManager;
}
/// <summary> /// <summary>
/// 初始化 SenseVoice /// 初始化 SenseVoice
/// </summary> /// </summary>
/// <param name="numThreads">默认6线程</param> /// <param name="numThreads">默认6线程</param>
/// <param name="useGPU">是否使用gpu 报错请看安装CUDA环境<see cref="https://k2-fsa.github.io/sherpa/onnx/pretrained_models/whisper/large-v3.html#run-with-gpu-float32"/></param> /// <param name="useGPU">是否使用gpu 报错请看安装CUDA环境<see cref="https://k2-fsa.github.io/sherpa/onnx/pretrained_models/whisper/large-v3.html#run-with-gpu-float32"/></param>
public void Init(int numThreads = 6, bool useGPU = false, bool useHotwords = false) public static void Init(int numThreads = 6, bool useGPU = false, bool useHotwords = false)
{ {
Console.WriteLine("初始化 SenseVoice"); Console.WriteLine("初始化 SenseVoice");
OfflineRecognizerConfig config = new OfflineRecognizerConfig(); OfflineRecognizerConfig config = new OfflineRecognizerConfig();
@ -125,19 +102,24 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
/// </summary> /// </summary>
/// <param name="s"></param> /// <param name="s"></param>
/// <returns></returns> /// <returns></returns>
public async Task<List<SenseVoiceRes>> RunTask(Stream s) public static async Task<List<SenseVoiceRes>> RunTask(Stream s)
{ {
if (s is null) if (s is null)
throw new Exception("音频路径 is null"); throw new Exception("音频路径 is null");
return await TaskHandle(new WaveReader(s), null); return await TaskHandle(new WaveReader(s));
} }
/// <summary> /// <summary>
/// 获取语音字幕 /// 获取语音字幕
/// </summary> /// </summary>
/// <param name="task"></param> /// <param name="task"></param>
/// <returns></returns> /// <returns></returns>
public async Task RunTask(string task) public static async Task RunTask(string task)
{ {
var filePath = Path.Combine(task.LocalPath(), "task.wav"); var filePath = Path.Combine(task.LocalPath(), "task.wav");
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
@ -152,7 +134,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
/// <param name="task">任务id [默认Null]</param> /// <param name="task">任务id [默认Null]</param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="Exception"></exception> /// <exception cref="Exception"></exception>
public async Task<List<SenseVoiceRes>> TaskHandle(WaveReader reader, string? task ) public static async Task<List<SenseVoiceRes>> TaskHandle(WaveReader reader, string? task = null)
{ {
if (OR is null) if (OR is null)
Init(); Init();
@ -180,30 +162,25 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
{ {
//获取最新的发言片段 //获取最新的发言片段
while (!VAD.IsEmpty()) while (!VAD.IsEmpty())
{ await VAD.ReadNext(res, totalSecond, task);
var p = await ReadNext(VAD,res, totalSecond);
if (p != null) redisManager.SetTaskProgress(task, p + "%");
}
} }
} }
VAD.Flush(); VAD.Flush();
while (!VAD.IsEmpty()) while (!VAD.IsEmpty())
{ await VAD.ReadNext(res, totalSecond, task);
var p = await ReadNext(VAD, res, totalSecond);
if(p!= null) redisManager.SetTaskProgress(task, p + "%");
}
//如果携带任务ID //如果携带任务ID
if (!string.IsNullOrEmpty(task)) if (!string.IsNullOrEmpty(task))
{ {
Console.WriteLine(DateTime.Now + "=> SenseVoice 字幕数量" + res.Count); Console.WriteLine(DateTime.Now + "=> SenseVoice 字幕数量" + res.Count);
var captionsStr = res.ToJson(); var captionsStr = res.ToJson();
await videoTaskDB.AsUpdateable() await DbScoped.Sugar
.Updateable<VideoTask>()
.SetColumns(it => it.Captions == captionsStr) .SetColumns(it => it.Captions == captionsStr)
.Where(it => it.Id == long.Parse(task)) .Where(it => it.Id == long.Parse(task))
.ExecuteCommandAsync(); .ExecuteCommandAsync();
await redisManager.Redis.HMSetAsync(RedisExpandKey.Task(task), "Captions", res); await RedisExpand.Redis.HMSetAsync(RedisExpandKey.Task(task), "Captions", res);
//分析完成视频字幕后继续接收任务 //分析完成视频字幕后继续接收任务
redisManager.NewTask(); RedisExpand.NewTaskAsync();
} }
return res; return res;
} }
@ -213,9 +190,9 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
/// <param name="VAD"></param> /// <param name="VAD"></param>
/// <param name="res">字幕处理后写入数组</param> /// <param name="res">字幕处理后写入数组</param>
/// <param name="totalSecond">总时长</param> /// <param name="totalSecond">总时长</param>
/// <param name="progressCallback">任务回调</param> /// <param name="task">所属任务id</param>
/// <returns></returns> /// <returns></returns>
public async Task<double?> ReadNext(VoiceActivityDetector VAD, List<SenseVoiceRes> res, float totalSecond) public static async Task ReadNext(this VoiceActivityDetector VAD, List<SenseVoiceRes> res, float totalSecond, string? task = null)
{ {
var segment = VAD.Front(); var segment = VAD.Front();
var sampleRate = VADModelConfig.SampleRate; var sampleRate = VADModelConfig.SampleRate;
@ -225,14 +202,13 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
using var stream = OR.CreateStream(); using var stream = OR.CreateStream();
stream.AcceptWaveform(sampleRate, segment.Samples); stream.AcceptWaveform(sampleRate, segment.Samples);
OR.Decode(stream); OR.Decode(stream);
double? resP =null;
if (!string.IsNullOrEmpty(stream.Result.Text)) if (!string.IsNullOrEmpty(stream.Result.Text))
{ {
var text = stream.Result.Text.Trim(); var text = stream.Result.Text.Trim();
if (text.Length == 1 && text == "。")// 检查字符是否只有一个句号 if (text.Length == 1 && text == "。")// 检查字符是否只有一个句号
{ {
VAD.Pop(); VAD.Pop();
return resP; return;
} }
res.Add(new() res.Add(new()
{ {
@ -240,10 +216,10 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
Start = (float)Math.Round(startTime, 2, MidpointRounding.AwayFromZero), Start = (float)Math.Round(startTime, 2, MidpointRounding.AwayFromZero),
End = (float)Math.Round(startTime + duration, 2, MidpointRounding.AwayFromZero), End = (float)Math.Round(startTime + duration, 2, MidpointRounding.AwayFromZero),
}); });
resP = Math.Round((double)(startTime + duration) / (totalSecond) * 100, 2); if (!string.IsNullOrEmpty(task))
RedisExpand.SetTaskProgress(task, Math.Round((double)(startTime + duration) / (totalSecond) * 100,2)+"%");
} }
VAD.Pop(); VAD.Pop();
return resP;
} }
} }
} }

View File

@ -10,7 +10,6 @@ using System.Text.Json;
using VideoAnalysisCore.Model.Enum; using VideoAnalysisCore.Model.Enum;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using UserCenter.Model.Enum; using UserCenter.Model.Enum;
using VideoAnalysisCore.Model.Dto;
namespace VideoAnalysisCore.AICore.SherpaOnnx namespace VideoAnalysisCore.AICore.SherpaOnnx
{ {
@ -74,16 +73,17 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
if(i%20 !=0) if(i%20 !=0)
return 1; return 1;
var progress = (float)numProcessedChunks / numTotalChunks * 100; var progress = (float)numProcessedChunks / numTotalChunks * 100;
//RedisExpand.SetTaskProgress(task, progress); RedisExpand.SetTaskProgress(task, progress);
return 1; return 1;
}, nint.Zero); }, nint.Zero);
var res = segments.Select(s => new OfflineSpeakerRes(s)); var res = segments.Select(s => new OfflineSpeakerRes(s));
//await RedisExpand.Redis.HSetAsync(RedisExpandKey.Task(task), "Speaker", res); await RedisExpand.Redis.HSetAsync(RedisExpandKey.Task(task), "Speaker", res);
var speakerStr = res.ToJson(); var speakerStr = res.ToJson();
//await videoTaskDB.Updateable() await DbScoped.Sugar
// .SetColumns(it => it.Speaker == speakerStr) .Updateable<VideoTask>()
// .Where(it => it.Id == long.Parse(task)) .SetColumns(it => it.Speaker == speakerStr)
// .ExecuteCommandAsync(); .Where(it => it.Id == long.Parse(task))
.ExecuteCommandAsync();
} }
} }

View File

@ -45,7 +45,7 @@ namespace VideoAnalysisCore.AICore.Whisper
{ {
res.Add(new WhisperResDto(segment)); res.Add(new WhisperResDto(segment));
} }
//RedisExpand.Redis.HMSet(RedisExpandKey.Task(task), "Captions", res); RedisExpand.Redis.HMSet(RedisExpandKey.Task(task), "Captions", res);
} }
/// <summary> /// <summary>
/// 检测语言的方法 /// 检测语言的方法

View File

@ -93,16 +93,14 @@ namespace VideoAnalysisCore.Common
private readonly Repository<VideoTask> videoTaskDB; private readonly Repository<VideoTask> videoTaskDB;
private readonly Repository<NodePackageInfo> packageInfoTaskDB; private readonly Repository<NodePackageInfo> packageInfoTaskDB;
private readonly Client vodClient; private readonly Client vodClient;
private readonly RedisManager redisManager;
readonly string taskVideoName = "task.mp4"; readonly string taskVideoName = "task.mp4";
readonly string taskPPTVideoName = "ppt.mp4"; readonly string taskPPTVideoName = "ppt.mp4";
public DownloadFile(Repository<VideoTask> videoTaskDB, Client vodClient, Repository<NodePackageInfo> nackageInfoTaskDB, RedisManager redisManager) public DownloadFile(Repository<VideoTask> videoTaskDB, Client vodClient, Repository<NodePackageInfo> nackageInfoTaskDB)
{ {
this.videoTaskDB = videoTaskDB; this.videoTaskDB = videoTaskDB;
this.vodClient = vodClient; this.vodClient = vodClient;
this.packageInfoTaskDB = nackageInfoTaskDB; this.packageInfoTaskDB = nackageInfoTaskDB;
this.redisManager = redisManager;
} }
// 根据 Content-Type 映射文件后缀 // 根据 Content-Type 映射文件后缀
@ -189,7 +187,7 @@ namespace VideoAnalysisCore.Common
if (!string.IsNullOrEmpty(taskInfo.PPTVideoUrl)) if (!string.IsNullOrEmpty(taskInfo.PPTVideoUrl))
{ {
await Download(taskInfo.PPTVideoUrl, localPath, taskPPTVideoName, await Download(taskInfo.PPTVideoUrl, localPath, taskPPTVideoName,
(s, e) => redisManager.SetTaskProgress(task, "PPT->" + Math.Round(e.ProgressPercentage, 1) (s, e) => RedisExpand.SetTaskProgress(task, "PPT->" + Math.Round(e.ProgressPercentage, 1)
)); ));
//try //try
//{ //{
@ -219,7 +217,7 @@ namespace VideoAnalysisCore.Common
{ {
//下载原视频 //下载原视频
await Download(fileUrl, localPath, taskVideoName, await Download(fileUrl, localPath, taskVideoName,
(s, e) => redisManager.SetTaskProgress(task, Math.Round(e.ProgressPercentage,1) (s, e) => RedisExpand.SetTaskProgress(task, Math.Round(e.ProgressPercentage,1)
)); ));
} }
catch catch

View File

@ -1,7 +1,6 @@
using FreeRedis; using FreeRedis;
using FreeRedis.Internal; using FreeRedis.Internal;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using NetTaste; using NetTaste;
using Newtonsoft.Json.Schema; using Newtonsoft.Json.Schema;
using SqlSugar.IOC; using SqlSugar.IOC;
@ -23,6 +22,7 @@ using VideoAnalysisCore.AICore.Whisper;
using VideoAnalysisCore.Model; using VideoAnalysisCore.Model;
using VideoAnalysisCore.Model.Dto; using VideoAnalysisCore.Model.Dto;
using VideoAnalysisCore.Model.Enum; using VideoAnalysisCore.Model.Enum;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace VideoAnalysisCore.Common namespace VideoAnalysisCore.Common
{ {
@ -31,7 +31,6 @@ namespace VideoAnalysisCore.Common
/// </summary> /// </summary>
public static class RedisExpandKey public static class RedisExpandKey
{ {
/// <summary> /// <summary>
/// 基础key /// 基础key
/// </summary> /// </summary>
@ -73,112 +72,45 @@ namespace VideoAnalysisCore.Common
public static string Task(object taskId) => BaseKey + "Task:" + taskId; public static string Task(object taskId) => BaseKey + "Task:" + taskId;
public static string IDTask => BaseKey + "Services:" + AppCommon.Config.ID; public static string IDTask => BaseKey + "Services:" + AppCommon.Config.ID;
public static string TaskGPT(object taskId) => Task(taskId) + ":GPTCached"; public static string TaskGPT(object taskId) => Task(taskId) + ":GPTCached";
/// <summary>
/// 初始化 redis
/// <para>需要在初始化配置文件时候调用</para>
/// </summary>
public static void AddTaskSubscribe(this IServiceCollection service)
{
Console.WriteLine($"{DateTime.Now}=>初始化 Redis任务队列");
service.AddSingleton<RedisInit>();
}
public static void AddRedisExpand(this IServiceCollection service)
{
Console.WriteLine($"{DateTime.Now}=>初始化 Redis");
var redis = new RedisClient(AppCommon.Config.Redis.ConnectionString);
redis.Serialize = obj => JsonSerializer.Serialize(obj);
redis.Deserialize = (json, type) => JsonSerializer.Deserialize(json, type);
service.AddSingleton(redis);
service.AddSingleton<RedisManager>();
}
}
public class RedisInit
{
public FFMPGEHandle FFMPGE { get; set; }
public SenseVoice senseVoice { get; set; }
public RedisManager redisManager { get; set; }
public RedisInit(FFMPGEHandle fFMPGE, SenseVoice senseVoice, RedisManager redisManager)
{
FFMPGE = fFMPGE;
this.senseVoice = senseVoice;
this.redisManager = redisManager;
Init();
redisManager.InitChannel();
}
public void Init()
{
var SubscribeList = RedisManager.SubscribeList;
SubscribeList.Add(RedisChannelEnum., (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<DownloadFile>() is null)
throw new Exception("DownloadFile 未注入");
else
return scope.ServiceProvider.GetService<DownloadFile>()?.RunTask(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum., FFMPGE.RunAsync);
SubscribeList.Add(RedisChannelEnum., senseVoice.RunTask);
//SubscribeList.Add(RedisChannelEnum.解析说话人,Speaker.Run);
SubscribeList.Add(RedisChannelEnum.AI课程类型,
(task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
return scope.ServiceProvider.GetService<IBserGPT>()?.GetVideoType(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum.AI模型分析, (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
return scope.ServiceProvider.GetService<IBserGPT>()?.GetKnow(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum.AI分析试题, (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
return scope.ServiceProvider.GetService<IBserGPT>()?.GetVideoQuestion(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum., redisManager.TaskEnd);
}
} }
/// <summary> /// <summary>
/// redis拓展 /// redis拓展
/// </summary> /// </summary>
public class RedisManager public static class RedisExpand
{ {
public static bool StopTask { get; set; } = false;
/// <summary>
/// redis 连接
/// </summary>
public static RedisClient Redis = new RedisClient(AppCommon.Config.Redis.ConnectionString);
public static Dictionary<RedisChannelEnum, Func<string,Task>> SubscribeList = new Dictionary<RedisChannelEnum, Func<string, Task>>(); public static Dictionary<RedisChannelEnum, Func<string,Task>> SubscribeList = new Dictionary<RedisChannelEnum, Func<string, Task>>();
/// <summary> /// <summary>
/// 队列池 /// 队列池
/// </summary> /// </summary>
static SubscribeListObject? Subscribe; static SubscribeListObject? Subscribe;
public RedisClient Redis { get; set; }
public Repository<VideoTask> videoTaskDB { get; set; }
public RedisManager(RedisClient redis, Repository<VideoTask> videoTaskDB) /// <summary>
/// 初始化 redis
/// <para>需要在初始化配置文件时候调用</para>
/// </summary>
public static void AddRedisExpand(this IServiceCollection service)
{ {
Redis = redis; Console.WriteLine($"{DateTime.Now}=>初始化 Redis");
this.videoTaskDB = videoTaskDB; Redis.Serialize = obj => JsonSerializer.Serialize(obj);
Redis.Deserialize = (json, type) => JsonSerializer.Deserialize(json, type);
Task.Run(() =>
{
Thread.Sleep(1000 * 10);
InitChannel();
});
} }
/// <summary> /// <summary>
/// 缓存GPT任务缓存 /// 缓存GPT任务缓存
/// </summary> /// </summary>
/// <param name="taskId"></param> /// <param name="taskId"></param>
public void SetTaskGPTCached(object taskId,string time, object? data) public static void SetTaskGPTCached(object taskId,string time, object? data)
{ {
Redis.Set(RedisExpandKey.TaskGPT(taskId) + ":" + time, data, 3600 * 24); Redis.Set(RedisExpandKey.TaskGPT(taskId) + ":" + time, data, 3600 * 24);
} }
@ -186,7 +118,7 @@ namespace VideoAnalysisCore.Common
/// 加入到消费队列 /// 加入到消费队列
/// </summary> /// </summary>
/// <param name="taskIds"></param> /// <param name="taskIds"></param>
public void JoinQueue(params long[] taskIds) public static void JoinQueue(params long[] taskIds)
{ //事务 { //事务
if (taskIds is null || taskIds.Length == 0) if (taskIds is null || taskIds.Length == 0)
return; return;
@ -201,7 +133,7 @@ namespace VideoAnalysisCore.Common
/// 获取任务进度 /// 获取任务进度
/// </summary> /// </summary>
/// <param name="taskId"></param> /// <param name="taskId"></param>
public float GetTaskProgress(object taskId) public static float GetTaskProgress(object taskId)
{ {
return Redis.HMGet<float>(RedisExpandKey.Task(taskId), "Progress")[0]; return Redis.HMGet<float>(RedisExpandKey.Task(taskId), "Progress")[0];
} }
@ -210,7 +142,7 @@ namespace VideoAnalysisCore.Common
/// </summary> /// </summary>
/// <param name="p">进度百分比</param> /// <param name="p">进度百分比</param>
/// <param name="taskId"></param> /// <param name="taskId"></param>
public void SetTaskProgress(object taskId, object p) public static void SetTaskProgress(object taskId, object p)
{ {
Redis.HMSet(RedisExpandKey.Task(taskId), "Progress", p.ToString()); Redis.HMSet(RedisExpandKey.Task(taskId), "Progress", p.ToString());
@ -220,7 +152,7 @@ namespace VideoAnalysisCore.Common
/// </summary> /// </summary>
/// <param name="enum">枚举</param> /// <param name="enum">枚举</param>
/// <param name="taskId">任务id</param> /// <param name="taskId">任务id</param>
public async Task InsertChannel(RedisChannelEnum @enum, object taskId) public static async Task InsertChannel(RedisChannelEnum @enum, object taskId)
{ {
if (taskId is null) throw new Exception("taskId为空"); if (taskId is null) throw new Exception("taskId为空");
if (Redis is null) throw new Exception("redis未初始化"); if (Redis is null) throw new Exception("redis未初始化");
@ -256,7 +188,7 @@ namespace VideoAnalysisCore.Common
} }
} }
public async Task TaskEnd(string task) public static async Task TaskEnd(string task)
{ {
var tId = long.Parse(task); var tId = long.Parse(task);
//var gptRes = (await Redis //var gptRes = (await Redis
@ -265,8 +197,8 @@ namespace VideoAnalysisCore.Common
// throw new Exception("未能读取到GPT处理结果"); // throw new Exception("未能读取到GPT处理结果");
//删除任务执行状态 //删除任务执行状态
await Redis.LRemAsync(RedisExpandKey.IDTask,1,task); await Redis.LRemAsync(RedisExpandKey.IDTask,1,task);
var taskData = await videoTaskDB var taskData = await DbScoped.Sugar.Queryable<VideoTask>()
.GetFirstAsync(s => s.Id == tId); .FirstAsync(s => s.Id == tId);
if (taskData.Captions == "[]") if (taskData.Captions == "[]")
taskData.Captions = (await Redis.HMGetAsync(RedisExpandKey.Task(task), "Captions")).First(); taskData.Captions = (await Redis.HMGetAsync(RedisExpandKey.Task(task), "Captions")).First();
//if (taskData.Speaker == "[]") //if (taskData.Speaker == "[]")
@ -279,7 +211,7 @@ namespace VideoAnalysisCore.Common
taskData.ErrorMessage = string.Empty; taskData.ErrorMessage = string.Empty;
taskData.LastEnum = RedisChannelEnum.; taskData.LastEnum = RedisChannelEnum.;
taskData.EndTime = DateTime.Now; taskData.EndTime = DateTime.Now;
await videoTaskDB.AsUpdateable(taskData) await DbScoped.Sugar.Updateable(taskData)
.UpdateColumns(it => new .UpdateColumns(it => new
{ {
//it.ChatAnalysis, //it.ChatAnalysis,
@ -298,36 +230,56 @@ namespace VideoAnalysisCore.Common
/// <summary> /// <summary>
/// 初始化 队列 任务 /// 初始化 队列 任务
/// </summary> /// </summary>
public async void InitChannel() public static async void InitChannel()
{ {
if (Redis is null) throw new Exception("redis未初始化"); if (Redis is null) throw new Exception("redis未初始化");
SubscribeList.Add(RedisChannelEnum., (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<DownloadFile>() is null)
throw new Exception("DownloadFile 未注入");
else
return scope.ServiceProvider.GetService<DownloadFile>()?.RunTask(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum., FFMPGEHandle.RunAsync);
SubscribeList.Add(RedisChannelEnum., SenseVoice.RunTask);
//SubscribeList.Add(RedisChannelEnum.解析说话人,Speaker.Run);
SubscribeList.Add(RedisChannelEnum.AI课程类型,
(task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
return scope.ServiceProvider.GetService<IBserGPT>()?.GetVideoType(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum.AI模型分析, (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
return scope.ServiceProvider.GetService<IBserGPT>()?.GetKnow(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum.AI分析试题, (task) =>
{
using var scope = AppCommon.Services?.CreateScope();
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
throw new Exception("IBserGPT 未注入");
else
return scope.ServiceProvider.GetService<IBserGPT>()?.GetVideoQuestion(task) ?? Task.CompletedTask;
});
SubscribeList.Add(RedisChannelEnum., TaskEnd);
//处理之前程序结束前未能执行完的情况 ReceivingTaskAsync();
var oldTaskCount = Redis.LLen(RedisExpandKey.IDTask);
if (oldTaskCount > 0)
{
var oldTaskArr = Redis.LRange(RedisExpandKey.IDTask, 0, oldTaskCount);
Redis.LTrim(RedisExpandKey.IDTask, 1, 0);//删除 redis 列表
foreach (var oldTask in oldTaskArr)
{
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "-------------> 接收上次未完成任务 " + oldTask);
await ClearTaskError(long.Parse(oldTask));
var lastEnum = (await Redis.HMGetAsync<RedisChannelEnum>(RedisExpandKey.Task(oldTask), "LastEnum")).FirstOrDefault();
await InsertChannel(lastEnum, oldTask);
}
}
else
{
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "-------------> 接收新任务!");
ReceivingTaskAsync();
}
} }
public static bool StopTask { get; set; } = false;
/// <summary> /// <summary>
/// 停止接收新任务 /// 停止接收新任务
/// </summary> /// </summary>
public void StopTaskAsync() public static void StopTaskAsync()
{ {
StopTask = true; StopTask = true;
try try
@ -345,30 +297,27 @@ namespace VideoAnalysisCore.Common
/// <summary> /// <summary>
/// 开始接收新任务 /// 开始接收新任务
/// </summary> /// </summary>
public void RestartTask() public static void RestartTaskAsync()
{ {
StopTask = false; StopTask = false;
NewTask(); NewTaskAsync();
} }
/// <summary> /// <summary>
/// 重新执行新任务 /// 重新执行新任务
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public void NewTask() public static async void NewTaskAsync()
{ {
// 取消 消费机的任务订阅 // 取消 消费机的任务订阅
if (StopTask) if (StopTask)
{
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "-------------> 接收任务已经暂停 ");
return; return;
}
ReceivingTaskAsync(); ReceivingTaskAsync();
} }
/// <summary> /// <summary>
/// 重新接收新任务 /// 重新接收新任务
/// </summary> /// </summary>
public void ReceivingTaskAsync() public static void ReceivingTaskAsync()
{ {
if (AppCommon.Config.TaskSetting.IS_Server) if (AppCommon.Config.TaskSetting.IS_Server)
{ {
@ -377,6 +326,15 @@ namespace VideoAnalysisCore.Common
} }
Task.Run(async () => Task.Run(async () =>
{ {
var oldTask = await Redis.LPopAsync(RedisExpandKey.IDTask);
if (!string.IsNullOrEmpty(oldTask))
{
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "-------------> 接收重试任务 " + oldTask);
await ClearTaskError(long.Parse(oldTask));
var lastEnum = (await Redis.HMGetAsync<RedisChannelEnum>(RedisExpandKey.Task(oldTask), "LastEnum")).FirstOrDefault();
await InsertChannel(lastEnum, oldTask);
return;
}
lock (Redis) lock (Redis)
{ {
if (Subscribe?.IsUnsubscribed == false)//排除重试机制后 多次接收任务导致内存泄露 if (Subscribe?.IsUnsubscribed == false)//排除重试机制后 多次接收任务导致内存泄露
@ -402,7 +360,7 @@ namespace VideoAnalysisCore.Common
/// <param name="taskID"></param> /// <param name="taskID"></param>
/// <param name="ex"></param> /// <param name="ex"></param>
/// <returns></returns> /// <returns></returns>
public async Task<bool> SetTaskErrorMessage(long taskID, Exception? ex) public static async Task<bool> SetTaskErrorMessage(long taskID, Exception? ex)
{ {
var error = string.Empty; var error = string.Empty;
if (ex != null) if (ex != null)
@ -416,7 +374,7 @@ namespace VideoAnalysisCore.Common
Console.WriteLine(ex.StackTrace); Console.WriteLine(ex.StackTrace);
Console.WriteLine("=============================================="); Console.WriteLine("==============================================");
//清除失败任务 重新接收任务 //清除失败任务 重新接收任务
NewTask(); NewTaskAsync();
} }
return await SetTaskError(taskID, error); return await SetTaskError(taskID, error);
} }
@ -425,17 +383,17 @@ namespace VideoAnalysisCore.Common
/// </summary> /// </summary>
/// <param name="taskID"></param> /// <param name="taskID"></param>
/// <returns></returns> /// <returns></returns>
public async Task<bool> ClearTaskError(long taskID) =>await SetTaskError(taskID, string.Empty); public static async Task<bool> ClearTaskError(long taskID) =>await SetTaskError(taskID, string.Empty);
/// <summary> /// <summary>
/// 修改任务的错误信息 /// 修改任务的错误信息
/// </summary> /// </summary>
/// <param name="taskID"></param> /// <param name="taskID"></param>
/// <param name="error"></param> /// <param name="error"></param>
/// <returns></returns> /// <returns></returns>
public async Task<bool> SetTaskError(long taskID, string? error) public static async Task<bool> SetTaskError(long taskID, string? error)
{ {
Redis.HMSet(RedisExpandKey.Task(taskID), "ErrorMessage", error); Redis.HMSet(RedisExpandKey.Task(taskID), "ErrorMessage", error);
return await videoTaskDB.AsUpdateable() return await DbScoped.Sugar.Updateable<VideoTask>()
.SetColumns(it => it.ErrorMessage == error)//SetColumns是可以叠加的 写2个就2个字段赋值 .SetColumns(it => it.ErrorMessage == error)//SetColumns是可以叠加的 写2个就2个字段赋值
.Where(it => it.Id == taskID) .Where(it => it.Id == taskID)
.ExecuteCommandAsync() == 1; .ExecuteCommandAsync() == 1;
@ -447,7 +405,7 @@ namespace VideoAnalysisCore.Common
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="taskId"></param> /// <param name="taskId"></param>
/// <param name="action"></param> /// <param name="action"></param>
public async Task TouchChannel(RedisChannelEnum key, string taskId, Func<string, Task> action = null) public static async Task TouchChannel(RedisChannelEnum key, string taskId, Func<string, Task> action = null)
{ {
if (taskId is null) return; if (taskId is null) return;
var tID = long.Parse(taskId); var tID = long.Parse(taskId);
@ -463,7 +421,7 @@ namespace VideoAnalysisCore.Common
Redis.HMSet(RedisExpandKey.Task(taskId), "Progress", 0); Redis.HMSet(RedisExpandKey.Task(taskId), "Progress", 0);
lock (Redis) lock (Redis)
{ {
videoTaskDB.AsUpdateable() DbScoped.SugarScope.Updateable<VideoTask>()
.SetColumns(it => it.LastEnum == key) .SetColumns(it => it.LastEnum == key)
.Where(it => it.Id == tID) .Where(it => it.Id == tID)
.ExecuteCommand(); .ExecuteCommand();

View File

@ -28,19 +28,15 @@ namespace VideoAnalysisCore.Controllers
{ {
private readonly IMapper mp; private readonly IMapper mp;
private readonly Repository<VideoTask> videoTaskDB; private readonly Repository<VideoTask> videoTaskDB;
private readonly RedisManager redisManager;
private readonly Repository<VideoKonwPoint> videoKonwDB; private readonly Repository<VideoKonwPoint> videoKonwDB;
private readonly Repository<CourseInfo> courseInfoDB; private readonly Repository<CourseInfo> courseInfoDB;
public readonly SenseVoice senseVoice;
public ApiController(Repository<VideoTask> videoTaskDB, public ApiController(Repository<VideoTask> videoTaskDB,
IMapper mp, Repository<VideoKonwPoint> videoKonwDB, Repository<CourseInfo> courseInfoDB, RedisManager redisManager, SenseVoice senseVoice) IMapper mp, Repository<VideoKonwPoint> videoKonwDB, Repository<CourseInfo> courseInfoDB)
{ {
this.videoTaskDB = videoTaskDB; this.videoTaskDB = videoTaskDB;
this.mp = mp; this.mp = mp;
this.videoKonwDB = videoKonwDB; this.videoKonwDB = videoKonwDB;
this.courseInfoDB = courseInfoDB; this.courseInfoDB = courseInfoDB;
this.redisManager = redisManager;
this.senseVoice = senseVoice;
} }
private string GetClientIpAddress() private string GetClientIpAddress()
@ -80,16 +76,13 @@ namespace VideoAnalysisCore.Controllers
/// <summary> /// <summary>
/// 初始化主库表 /// 初始化主库表
/// </summary> /// </summary>
/// <param name="task">ÊÇ·ñÖ´ÐÐÈÎÎñ</param> /// <param name="url">ÎļþÁ÷</param>
/// <returns></returns> /// <returns></returns>
[HttpGet(Name = "StartTask")] [HttpGet(Name = "tets1")]
public IActionResult StartTask(bool task) public IActionResult tets1(string task)
{ {
if(task) var courseArr = courseInfoDB.AsQueryable().ToArray();
redisManager.RestartTask(); return Ok(courseArr);
else
redisManager.StopTaskAsync();
return Ok();
} }
/// <summary> /// <summary>
/// 语音识别 /// 语音识别
@ -104,7 +97,7 @@ namespace VideoAnalysisCore.Controllers
using HttpClient client = new HttpClient(); using HttpClient client = new HttpClient();
// 发送GET请求获取网络文件流 // 发送GET请求获取网络文件流
using var networkStream = await client.GetStreamAsync(url); using var networkStream = await client.GetStreamAsync(url);
var res = await senseVoice.RunTask(networkStream); var res = await SenseVoice.RunTask(networkStream);
return Ok(res); return Ok(res);
} }
catch (Exception ex) catch (Exception ex)
@ -121,7 +114,7 @@ namespace VideoAnalysisCore.Controllers
public async Task<IActionResult> AudioRecognition(IFormFile file) public async Task<IActionResult> AudioRecognition(IFormFile file)
{ {
using var s = file.OpenReadStream(); using var s = file.OpenReadStream();
var res = await senseVoice.RunTask(s); var res = await SenseVoice.RunTask(s);
return Ok(res); return Ok(res);
} }
@ -208,8 +201,8 @@ namespace VideoAnalysisCore.Controllers
.GetProperties(BindingFlags.Public | BindingFlags.Instance) .GetProperties(BindingFlags.Public | BindingFlags.Instance)
.ToDictionary(s => s.Name, s => s.GetValue(task)); .ToDictionary(s => s.Name, s => s.GetValue(task));
await videoTaskDB.InsertAsync(task); await videoTaskDB.InsertAsync(task);
redisManager.Redis.HMSet(RedisExpandKey.Task(task.Id), hashEntries); RedisExpand.Redis.HMSet(RedisExpandKey.Task(task.Id), hashEntries);
redisManager.Redis.LPush(RedisExpandKey.ChannelKey, task.Id); RedisExpand.Redis.LPush(RedisExpandKey.ChannelKey, task.Id);
return Ok(task.Id); return Ok(task.Id);
} }

View File

@ -38,11 +38,10 @@ namespace VideoAnalysisCore.Controllers
private readonly Repository<NodePackageInfo> nodePackageInfoDB; private readonly Repository<NodePackageInfo> nodePackageInfoDB;
private readonly Repository<VideoQuestion> videoQuestionDB; private readonly Repository<VideoQuestion> videoQuestionDB;
private readonly Repository<VideoQuestionKonw> videoQuestionKonwDB; private readonly Repository<VideoQuestionKonw> videoQuestionKonwDB;
private readonly RedisManager redisManager;
public LJZK_Controller(IMapper mp, Repository<NodeSubscription> nodesubscriptionDB, public LJZK_Controller(IMapper mp, Repository<NodeSubscription> nodesubscriptionDB,
Repository<VideoTask> videoTaskDB = null, Repository<VideoKonwPoint> videoKonwPointDB = null Repository<VideoTask> videoTaskDB = null, Repository<VideoKonwPoint> videoKonwPointDB = null
, Repository<NodePackageInfo> nodePackageInfoDB = null, Repository<VideoQuestion> videoQuestionDB = null, Repository<VideoQuestionKonw> videoQuestionKonwDB = null, Repository<CourseInfo> courseInfoDB = null, RedisManager redisManager = null) , Repository<NodePackageInfo> nodePackageInfoDB = null, Repository<VideoQuestion> videoQuestionDB = null, Repository<VideoQuestionKonw> videoQuestionKonwDB = null, Repository<CourseInfo> courseInfoDB = null)
{ {
this.mp = mp; this.mp = mp;
this.nodesubscriptionDB = nodesubscriptionDB; this.nodesubscriptionDB = nodesubscriptionDB;
@ -52,7 +51,6 @@ namespace VideoAnalysisCore.Controllers
this.videoQuestionDB = videoQuestionDB; this.videoQuestionDB = videoQuestionDB;
this.videoQuestionKonwDB = videoQuestionKonwDB; this.videoQuestionKonwDB = videoQuestionKonwDB;
this.courseInfoDB = courseInfoDB; this.courseInfoDB = courseInfoDB;
this.redisManager = redisManager;
} }
@ -127,7 +125,7 @@ namespace VideoAnalysisCore.Controllers
if (videos is null || videos.Count == 0) if (videos is null || videos.Count == 0)
return Ok(); return Ok();
var ids = videos.Select(s => s.Id).ToArray(); var ids = videos.Select(s => s.Id).ToArray();
redisManager.JoinQueue(ids); RedisExpand.JoinQueue(ids);
return Ok(); return Ok();
} }

View File

@ -36,76 +36,76 @@ namespace VideoAnalysisCore.Job
public async Task Invoke() public async Task Invoke()
{ {
throw new Exception("已经弃用"); throw new Exception("已经弃用");
// Console.WriteLine($"{DateTime.Now} 执行=>文件节点订阅"); Console.WriteLine($"{DateTime.Now} 执行=>文件节点订阅");
// var videoIdArr = videotaskDB.AsQueryable().Select(v => v.TagId).Distinct().ToArray(); var videoIdArr = videotaskDB.AsQueryable().Select(v => v.TagId).Distinct().ToArray();
// var tasks = await nodesubscriptionDB.GetListAsync(s => s.Enable && s.Subject ==SubjectEnum.数学); var tasks = await nodesubscriptionDB.GetListAsync(s => s.Enable && s.Subject ==SubjectEnum.);
// foreach (var item in tasks) foreach (var item in tasks)
// { {
// var fileNodeId = item.NodeId; var fileNodeId = item.NodeId;
// var data = attachmentsDB.Context.Ado var data = attachmentsDB.Context.Ado
// .SqlQuery<Attachments>($""" .SqlQuery<Attachments>($"""
//SELECT top {TopLength} SELECT top {TopLength}
// * *
//FROM FROM
// Attachments Attachments
//WHERE WHERE
// Id IN ( Id IN (
// SELECT SELECT
// AttachmentsId AttachmentsId
// FROM FROM
// Material Material
// WHERE WHERE
// id IN ( id IN (
// SELECT SELECT
// MaterialId MaterialId
// FROM FROM
// FileContentMaterial FileContentMaterial
// WHERE WHERE
// FileContentId IN ( SELECT id FROM FileContent WHERE BagId IN ( SELECT Id FROM FileDirectory WHERE Id={fileNodeId} AND types = 1 AND DeleteState = 0 ) ) FileContentId IN ( SELECT id FROM FileContent WHERE BagId IN ( SELECT Id FROM FileDirectory WHERE Id={fileNodeId} AND types = 1 AND DeleteState = 0 ) )
// AND DeleteState = 0 AND DeleteState = 0
// AND ( MaterialName NOT LIKE '%PPT%' OR MaterialName NOT LIKE '%ppt%' ) AND ( MaterialName NOT LIKE '%PPT%' OR MaterialName NOT LIKE '%ppt%' )
// ) )
// ) )
// AND Type = '录播视频' AND Type = ''
// AND ( AND (
// NAME NOT LIKE '%PPT%' NAME NOT LIKE '%PPT%'
// OR NAME NOT LIKE '%ppt%' OR NAME NOT LIKE '%ppt%'
// ) and id>{item.LastId} ) and id>{item.LastId}
//"""); """);
// if (data is null || data.Count == 0) if (data is null || data.Count == 0)
// continue; continue;
// Console.WriteLine($"{DateTime.Now} 视频订阅=>Node:{item.NodeId} 数量{data.Count}"); Console.WriteLine($"{DateTime.Now} 视频订阅=>Node:{item.NodeId} 数量{data.Count}");
// var videos = new List<VideoTask>(data.Count); var videos = new List<VideoTask>(data.Count);
// foreach (var s in data) foreach (var s in data)
// { {
// if (videoIdArr.Contains(s.VideoCode)) if (videoIdArr.Contains(s.VideoCode))
// continue; continue;
// //videos.Add(new VideoTask() //videos.Add(new VideoTask()
// //{ //{
// // Id = YitIdHelper.NextId(), // Id = YitIdHelper.NextId(),
// // ComeFrom = "127.0.0.1", // ComeFrom = "127.0.0.1",
// // ApiToken = "", // ApiToken = "",
// // //Type = item.TaskType, // //Type = item.TaskType,
// // Subject = item.Subject, // Subject = item.Subject,
// // Tag = item.NodeId.ToString(), // Tag = item.NodeId.ToString(),
// // TagId = s.VideoCode, // TagId = s.VideoCode,
// // MediaUrl = string.Empty, // MediaUrl = string.Empty,
// //}); //});
// } }
// var maxId = data.Max(s => s.Id); var maxId = data.Max(s => s.Id);
// //入库 更新最后扫描记录 //入库 更新最后扫描记录
// await nodesubscriptionDB.AsUpdateable() await nodesubscriptionDB.AsUpdateable()
// .SetColumns(it => it.LastId == maxId) .SetColumns(it => it.LastId == maxId)
// .Where(it => it.Id == item.Id) .Where(it => it.Id == item.Id)
// .ExecuteCommandAsync(); .ExecuteCommandAsync();
// await videotaskDB.InsertRangeAsync(videos); await videotaskDB.InsertRangeAsync(videos);
// var ids = videos.Select(s => s.Id).ToArray(); var ids = videos.Select(s => s.Id).ToArray();
// RedisExpand.JoinQueue(ids); RedisExpand.JoinQueue(ids);
// } }
} }
} }
} }