Compare commits
5 Commits
0de07e733a
...
22e1a87a68
| Author | SHA1 | Date |
|---|---|---|
|
|
22e1a87a68 | |
|
|
4361e7fa0f | |
|
|
d49550807b | |
|
|
bbad3da13a | |
|
|
2acc0d4239 |
|
|
@ -369,3 +369,4 @@ VideoAnalysis/WebUI/node_modules/
|
||||||
VideoAnalysis/WebUI/dist/
|
VideoAnalysis/WebUI/dist/
|
||||||
VideoAnalysis/WebUI/.vscode/
|
VideoAnalysis/WebUI/.vscode/
|
||||||
/VideoAnalysis/device_id.config
|
/VideoAnalysis/device_id.config
|
||||||
|
/Learn.VideoAnalysis.API/device_id.config
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ namespace Learn.VideoAnalysis.API.Expand
|
||||||
Console.WriteLine($"{DateTime.Now}=>初始化 Coravel");
|
Console.WriteLine($"{DateTime.Now}=>初始化 Coravel");
|
||||||
service.AddScheduler();
|
service.AddScheduler();
|
||||||
service.AddTransient<TaskFileClearJob>();
|
service.AddTransient<TaskFileClearJob>();
|
||||||
|
service.AddTransient<ClearAllCacheJob>();
|
||||||
service.AddTransient<NodePackageJob>();
|
service.AddTransient<NodePackageJob>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,10 +54,25 @@ namespace Learn.VideoAnalysis.API.Expand
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
/// <exception cref="CustomException"></exception>
|
/// <exception cref="CustomException"></exception>
|
||||||
public void ExecutingFileCached(ActionExecutingContext context)
|
public void ExecutingCached(ActionExecutingContext context)
|
||||||
{
|
{
|
||||||
//特殊处理:ResultIgnore,不进行返回结果包装,原样输出
|
//特殊处理:ResultIgnore,不进行返回结果包装,原样输出
|
||||||
var endpoint = context.HttpContext.GetEndpoint();
|
var endpoint = context.HttpContext.GetEndpoint();
|
||||||
|
var request = context.HttpContext.Request;
|
||||||
|
// 1. 只有非 GET 请求且不是文件上传时才读取 Body
|
||||||
|
if (!request.Method.Equals("GET", StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& !request.HasFormContentType)
|
||||||
|
{
|
||||||
|
// 确保从头开始读
|
||||||
|
request.Body.Position = 0;
|
||||||
|
// 使用 leaveOpen: true 防止 StreamReader 关闭底层的 Request.Body
|
||||||
|
using (var reader = new System.IO.StreamReader(request.Body, System.Text.Encoding.UTF8, detectEncodingFromByteOrderMarks: false, bufferSize: 1024, leaveOpen: true))
|
||||||
|
{
|
||||||
|
var body = reader.ReadToEnd();
|
||||||
|
context.HttpContext.Items["RequestBodyRaw"] = body;
|
||||||
|
request.Body.Position = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
// 直接返回原始结果,不封装
|
// 直接返回原始结果,不封装
|
||||||
if (endpoint?.Metadata.GetMetadata<HttpLogEnable>() == null) return;
|
if (endpoint?.Metadata.GetMetadata<HttpLogEnable>() == null) return;
|
||||||
if (context.HttpContext.Request.HasFormContentType &&
|
if (context.HttpContext.Request.HasFormContentType &&
|
||||||
|
|
@ -74,6 +89,8 @@ namespace Learn.VideoAnalysis.API.Expand
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行接口前400 处理
|
/// 执行接口前400 处理
|
||||||
|
|
@ -149,34 +166,19 @@ namespace Learn.VideoAnalysis.API.Expand
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task AddHttpLogAsync(HttpContext context, BaseReturn<object>? result = null, Exception? e = null)
|
public async Task AddHttpLogAsync(HttpContext context, BaseReturn<object>? result = null, Exception? e = null)
|
||||||
{
|
{
|
||||||
//特殊处理:ResultIgnore,不进行返回结果包装,原样输出
|
|
||||||
var endpoint = context.GetEndpoint();
|
|
||||||
// 所有请求都记录
|
|
||||||
//if (endpoint?.Metadata.GetMetadata<HttpLogEnable>() == null&& e is null) return;
|
|
||||||
|
|
||||||
string request = null;
|
string request = null;
|
||||||
var logId = Yitter.IdGenerator.YitIdHelper.NextId();
|
var logId = Yitter.IdGenerator.YitIdHelper.NextId();
|
||||||
if (!context.Request.Method.Equals("GET", StringComparison.InvariantCultureIgnoreCase))
|
if (!context.Request.Method.Equals("GET", StringComparison.InvariantCultureIgnoreCase))
|
||||||
{
|
|
||||||
context.Request.EnableBuffering();
|
|
||||||
//记录请求参数
|
|
||||||
if (context.Request.Body.CanSeek)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var fileArr = context.Items.ContainsKey("FileCached") ? context.Items["FileCached"] as (IFormFile file, MemoryStream stream)[] : null;
|
var fileArr = context.Items.ContainsKey("FileCached") ? context.Items["FileCached"] as (IFormFile file, MemoryStream stream)[] : null;
|
||||||
if (context.Request.HasFormContentType && fileArr != null)
|
if (context.Request.HasFormContentType && fileArr != null)
|
||||||
{
|
{
|
||||||
// 设置保存目录(例如:项目根目录下的Uploads文件夹)
|
|
||||||
string uploadsFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UploadLogs", logId.ToString());
|
string uploadsFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UploadLogs", logId.ToString());
|
||||||
// 创建目录(如果不存在)
|
|
||||||
if (!Directory.Exists(uploadsFolder))
|
if (!Directory.Exists(uploadsFolder))
|
||||||
Directory.CreateDirectory(uploadsFolder);
|
Directory.CreateDirectory(uploadsFolder);
|
||||||
foreach (var fileInfo in fileArr)
|
foreach (var fileInfo in fileArr)
|
||||||
{
|
{
|
||||||
// 生成安全文件名(防止路径遍历攻击)
|
|
||||||
string uniqueFileName = Guid.NewGuid().ToString().Substring(0, 5) + "_" + Path.GetFileName(fileInfo.file.FileName);
|
string uniqueFileName = Guid.NewGuid().ToString().Substring(0, 5) + "_" + Path.GetFileName(fileInfo.file.FileName);
|
||||||
// 保存文件
|
|
||||||
using var stream = new FileStream(Path.Combine(uploadsFolder, uniqueFileName), FileMode.Create, FileAccess.Write);
|
using var stream = new FileStream(Path.Combine(uploadsFolder, uniqueFileName), FileMode.Create, FileAccess.Write);
|
||||||
fileInfo.stream.Position = 0;
|
fileInfo.stream.Position = 0;
|
||||||
await fileInfo.stream.CopyToAsync(stream);
|
await fileInfo.stream.CopyToAsync(stream);
|
||||||
|
|
@ -184,18 +186,11 @@ namespace Learn.VideoAnalysis.API.Expand
|
||||||
}
|
}
|
||||||
request = $"请求体包含{context.Request.Form.Files.Count()}个文件 目录 {uploadsFolder}";
|
request = $"请求体包含{context.Request.Form.Files.Count()}个文件 目录 {uploadsFolder}";
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
}
|
||||||
|
if (context.Items.ContainsKey("RequestBodyRaw"))
|
||||||
{
|
{
|
||||||
context.Request.Body.Position = 0;
|
request = context.Items["RequestBodyRaw"] as string;
|
||||||
using var sr = new System.IO.StreamReader(context.Request.Body);
|
|
||||||
request = await sr.ReadToEndAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
request = "处理请求入参时发生了错误 \r\n" + ex.ToString() + "\r\n 原有请求数据 " + request;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//写入队列
|
//写入队列
|
||||||
await DbScoped.Sugar.CopyNew()
|
await DbScoped.Sugar.CopyNew()
|
||||||
|
|
@ -205,7 +200,7 @@ namespace Learn.VideoAnalysis.API.Expand
|
||||||
Url = context.Request.Path + context.Request.QueryString,
|
Url = context.Request.Path + context.Request.QueryString,
|
||||||
Method = context.Request.Method,
|
Method = context.Request.Method,
|
||||||
Request = request,
|
Request = request,
|
||||||
IP = $"{context.Connection?.RemoteIpAddress?.ToString()}",
|
IP = GetClientIp(context),
|
||||||
ResponseCode = result?.Code ?? -1,
|
ResponseCode = result?.Code ?? -1,
|
||||||
Response = (result != null ? JsonSerializer.Serialize(result) : null) ,
|
Response = (result != null ? JsonSerializer.Serialize(result) : null) ,
|
||||||
Authorization = context.Request.Headers.ContainsKey("Authorization")
|
Authorization = context.Request.Headers.ContainsKey("Authorization")
|
||||||
|
|
@ -218,21 +213,31 @@ namespace Learn.VideoAnalysis.API.Expand
|
||||||
}).ExecuteCommandAsync();
|
}).ExecuteCommandAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetClientIp(HttpContext context)
|
||||||
|
{
|
||||||
|
var headers = context.Request.Headers;
|
||||||
|
var ip = headers["X-Forwarded-For"].FirstOrDefault();
|
||||||
|
if (!string.IsNullOrWhiteSpace(ip))
|
||||||
|
{
|
||||||
|
ip = ip.Split(',', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault()?.Trim();
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(ip))
|
||||||
|
{
|
||||||
|
ip = headers["X-Real-IP"].FirstOrDefault();
|
||||||
|
}
|
||||||
|
if (string.IsNullOrWhiteSpace(ip) && context.Connection.RemoteIpAddress != null)
|
||||||
|
{
|
||||||
|
ip = context.Connection.RemoteIpAddress.ToString();
|
||||||
|
}
|
||||||
|
return ip ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
public override async void OnActionExecuting(ActionExecutingContext context)
|
public override async void OnActionExecuting(ActionExecutingContext context)
|
||||||
{
|
{
|
||||||
// 过期的
|
|
||||||
//if (context.HttpContext.GetEndpoint()?
|
|
||||||
// .Metadata.GetMetadata<IAllowAnonymous>() is null)
|
|
||||||
//{
|
|
||||||
// context.Result = new UnauthorizedResult();
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
Executing400(context);
|
Executing400(context);
|
||||||
ExecutingFileCached(context);
|
ExecutingCached(context);
|
||||||
base.OnActionExecuting(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -248,6 +253,9 @@ namespace Learn.VideoAnalysis.API.Expand
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine($"{DateTime.Now}=>接口规范出现异常");
|
||||||
|
Console.WriteLine(ex.Message);
|
||||||
|
Console.WriteLine(ex.StackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
base.OnActionExecuted(context);
|
base.OnActionExecuted(context);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using Coravel;
|
using Coravel;
|
||||||
using Coravel.Scheduling.Schedule;
|
using Coravel.Scheduling.Schedule;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
@ -21,6 +21,7 @@ namespace Learn.VideoAnalysis.Expand
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
service.AddTransient<TaskFileClearJob>();
|
service.AddTransient<TaskFileClearJob>();
|
||||||
#endif
|
#endif
|
||||||
|
service.AddTransient<ClearAllCacheJob>();
|
||||||
service.AddTransient<NodePackageJob>();
|
service.AddTransient<NodePackageJob>();
|
||||||
}
|
}
|
||||||
public static void UseCoravelExpand(this IApplicationBuilder provider)
|
public static void UseCoravelExpand(this IApplicationBuilder provider)
|
||||||
|
|
@ -28,8 +29,10 @@ namespace Learn.VideoAnalysis.Expand
|
||||||
provider.ApplicationServices.UseScheduler(scheduler =>
|
provider.ApplicationServices.UseScheduler(scheduler =>
|
||||||
{
|
{
|
||||||
//任务缓存清理
|
//任务缓存清理
|
||||||
scheduler.Schedule<TaskFileClearJob>().HourlyAt(10);
|
// scheduler.Schedule<TaskFileClearJob>().HourlyAt(10);
|
||||||
//scheduler.Schedule<TaskFileClearJob>().DailyAt(1,0);
|
//强制清理所有缓存内容
|
||||||
|
scheduler.Schedule<ClearAllCacheJob>().Hourly();
|
||||||
|
//scheduler.Schedule<ClearAllCacheJob>().EverySeconds(40);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,8 +106,6 @@ namespace Learn.VideoAnalysis
|
||||||
AppCommon.Services = app.Services;
|
AppCommon.Services = app.Services;
|
||||||
app.UseMiddleware<BasicAuthMiddleware>("Swagger");
|
app.UseMiddleware<BasicAuthMiddleware>("Swagger");
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
//开启redis队列服务
|
|
||||||
_ = app.Services.GetRequiredService<RedisInit>();
|
|
||||||
app.UseSwagger();
|
app.UseSwagger();
|
||||||
app.UseSwaggerUI();
|
app.UseSwaggerUI();
|
||||||
app.UseExceptionHandler("/Error");
|
app.UseExceptionHandler("/Error");
|
||||||
|
|
@ -133,7 +131,12 @@ namespace Learn.VideoAnalysis
|
||||||
app.UseCorsExpand();
|
app.UseCorsExpand();
|
||||||
app.UseSqlSugarExpand();
|
app.UseSqlSugarExpand();
|
||||||
app.UseCoravelExpand();
|
app.UseCoravelExpand();
|
||||||
app.UseServiceSystem();
|
app.UseServiceSystem(() =>
|
||||||
|
{
|
||||||
|
//开启redis队列服务
|
||||||
|
_ = AppCommon.Services.GetRequiredService<RedisInit>();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@
|
||||||
"ChatGpt": {
|
"ChatGpt": {
|
||||||
//"Host": "https://api.g4f.icu/",
|
//"Host": "https://api.g4f.icu/",
|
||||||
"Host": "https://api.oaibest.com/",
|
"Host": "https://api.oaibest.com/",
|
||||||
"ApiKey": "sk-D15tBln31N7dI9Fi7lds7OySFv5tOEK7DMNsG5rY2E6DCr4s",
|
"ApiKey": "sk-uuCt3AZHawc9B543Yq5bxluO8aW35ArCY5fFnkh2LaJpFYA7",
|
||||||
"Path": "v1/chat/completions"
|
"Path": "v1/chat/completions"
|
||||||
},
|
},
|
||||||
"DeepSeek": {
|
"DeepSeek": {
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,10 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
public const string Deepseek_Reasoner = "deepseek-reasoner";
|
public const string Deepseek_Reasoner = "deepseek-reasoner";
|
||||||
public const string Deepseek_Chat = "deepseek-chat";
|
public const string Deepseek_Chat = "deepseek-chat";
|
||||||
|
|
||||||
|
//渠道限制没有并发
|
||||||
public const string Gemini_3_Chat_thinking = "gemini-3-pro-preview-thinking";
|
//public const string Gemini_3_Chat_thinking = "gemini-3-pro-preview-thinking";
|
||||||
public const string Gemini_3_Chat = "gemini-3-pro-preview";
|
public const string Gemini_3_Chat = "gemini-3-pro-preview";
|
||||||
|
public const string Gemini_3_Chat_flash = "gemini-3-flash-preview";
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using VideoAnalysisCore.Common;
|
using VideoAnalysisCore.Common;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using VideoAnalysisCore.Model;
|
using VideoAnalysisCore.Model;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
@ -189,8 +189,7 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
$"字幕列表 {rCaptionArr}。" +
|
$"字幕列表 {rCaptionArr}。" +
|
||||||
$"输出格式 json字符串 对象格式{fileNameResFormat}";
|
$"输出格式 json字符串 对象格式{fileNameResFormat}";
|
||||||
var task = taskInfo.Id.ToString();
|
var task = taskInfo.Id.ToString();
|
||||||
var fileNameInfoRes = await geminiClient.ChatAsync<FileNameInfo>
|
var fileNameInfoRes = await geminiClient.ChatAsync<FileNameInfo>(task, fileNamePostMessages, "授课章节");
|
||||||
(task, fileNamePostMessages, "授课章节");
|
|
||||||
taskInfo.Sections = fileNameInfoRes.授课章节;
|
taskInfo.Sections = fileNameInfoRes.授课章节;
|
||||||
await videoTaskDB.AsUpdateable()
|
await videoTaskDB.AsUpdateable()
|
||||||
.SetColumns(it => it.Sections == fileNameInfoRes.授课章节)
|
.SetColumns(it => it.Sections == fileNameInfoRes.授课章节)
|
||||||
|
|
@ -426,7 +425,7 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
""";
|
""";
|
||||||
|
|
||||||
await redisManager.AddTaskLog(taskInfo.Id, $"开始分析视频内容 {tryCount}");
|
await redisManager.AddTaskLog(taskInfo.Id, $"开始分析视频内容 {tryCount}");
|
||||||
var res = await geminiClient.ChatAsync<List<VideoKnowRes>>(taskInfo.Id.ToString(), postMessages, "分析字幕", ChatGPTType.Gemini_3_Chat_thinking);
|
var res = await geminiClient.ChatAsync<List<VideoKnowRes>>(taskInfo.Id.ToString(), postMessages, "分析字幕", ChatGPTType.Gemini_3_Chat);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -569,6 +568,8 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task<SenseVoiceRes[]> AnalysisVideoQuestions(VideoTask taskInfo, List<KnowledgeInfo> knowledgeInfos)
|
private async Task<SenseVoiceRes[]> AnalysisVideoQuestions(VideoTask taskInfo, List<KnowledgeInfo> knowledgeInfos)
|
||||||
{
|
{
|
||||||
|
await redisManager.AddTaskLog(taskInfo.Id, $"==>提取试题功能已禁用");
|
||||||
|
return null;
|
||||||
await redisManager.AddTaskLog(taskInfo.Id, $"==>{taskInfo.Id} 提取试题");
|
await redisManager.AddTaskLog(taskInfo.Id, $"==>{taskInfo.Id} 提取试题");
|
||||||
if (taskInfo is null || string.IsNullOrEmpty(taskInfo.PPTKeyFrame))
|
if (taskInfo is null || string.IsNullOrEmpty(taskInfo.PPTKeyFrame))
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -700,6 +701,7 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<TaskRes> GetKnow(string task)
|
public async Task<TaskRes> GetKnow(string task)
|
||||||
{
|
{
|
||||||
|
|
||||||
var taskId = long.Parse(task);
|
var taskId = long.Parse(task);
|
||||||
var taskInfo = await videoTaskDB.AsQueryable()
|
var taskInfo = await videoTaskDB.AsQueryable()
|
||||||
.Where(s => s.Id == taskId)
|
.Where(s => s.Id == taskId)
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ namespace VideoAnalysisCore.AICore.GPT.Gemini
|
||||||
Message[] messageArr = [
|
Message[] messageArr = [
|
||||||
new Message(postMessages,"user"),
|
new Message(postMessages,"user"),
|
||||||
];
|
];
|
||||||
model = model ?? ChatGPTType.Gemini_3_Chat;
|
model = model ?? ChatGPTType.Gemini_3_Chat_flash;
|
||||||
messageArr = messageArr.Where(s => s != null).ToArray();
|
messageArr = messageArr.Where(s => s != null).ToArray();
|
||||||
var chatReq = new ChatRequest
|
var chatReq = new ChatRequest
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using SherpaOnnx;
|
using SherpaOnnx;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
|
@ -49,7 +49,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SherpaVad
|
public class SherpaVad
|
||||||
{
|
{
|
||||||
static VadModelConfig VADModelConfig = default!;
|
private VadModelConfig VADModelConfig;
|
||||||
|
|
||||||
private readonly RedisManager redisManager;
|
private readonly RedisManager redisManager;
|
||||||
private int WindowSize = 512;
|
private int WindowSize = 512;
|
||||||
|
|
@ -137,6 +137,7 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
|
||||||
// 使用 Span 操作原始数据
|
// 使用 Span 操作原始数据
|
||||||
ReadOnlySpan<float> allSamples = reader.Samples.AsSpan();
|
ReadOnlySpan<float> allSamples = reader.Samples.AsSpan();
|
||||||
int numSamples = allSamples.Length;
|
int numSamples = allSamples.Length;
|
||||||
|
VADModelConfig.SampleRate = reader.SampleRate;
|
||||||
int sampleRate = VADModelConfig.SampleRate;
|
int sampleRate = VADModelConfig.SampleRate;
|
||||||
int numIter = numSamples / WindowSize;
|
int numIter = numSamples / WindowSize;
|
||||||
var totalSecond = numSamples / (float)sampleRate;
|
var totalSecond = numSamples / (float)sampleRate;
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ namespace VideoAnalysisCore.Common
|
||||||
public static string FrameName = "frame_";
|
public static string FrameName = "frame_";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除 AI分析任务的缓存文件
|
/// 删除 AI分析任务视频/PPT的缓存文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="taskId"></param>
|
/// <param name="taskId"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
|
@ -144,6 +144,30 @@ namespace VideoAnalysisCore.Common
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除 AI分析任务的缓存文件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="taskId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task<bool> DeleteTaskAllFileAsync(long? taskId, RedisManager redisManager)
|
||||||
|
{
|
||||||
|
if (taskId is null || taskId == 0) return false;
|
||||||
|
var path = taskId.ToString().LocalPath();
|
||||||
|
if (!string.IsNullOrEmpty(path) && Directory.Exists(path))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.Delete(path, true);
|
||||||
|
await redisManager.AddTaskLog(taskId, $"已清理所有缓存文件: {taskId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await redisManager.AddTaskLog(taskId, $"删除缓存文件 {taskId} 时出错: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 对象转化为JSON字符串
|
/// 对象转化为JSON字符串
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,9 @@ namespace VideoAnalysisCore.Common
|
||||||
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
|
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!context.Request.Method.Equals("GET", StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& !context.Request.HasFormContentType)
|
||||||
|
context.Request.EnableBuffering();
|
||||||
await _next(context);
|
await _next(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using Downloader;
|
using Downloader;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using SqlSugar.IOC;
|
using SqlSugar.IOC;
|
||||||
|
|
@ -94,15 +94,17 @@ namespace VideoAnalysisCore.Common
|
||||||
private readonly Repository<NodePackageInfo> packageInfoTaskDB;
|
private readonly Repository<NodePackageInfo> packageInfoTaskDB;
|
||||||
private readonly Client vodClient;
|
private readonly Client vodClient;
|
||||||
private readonly RedisManager redisManager;
|
private readonly RedisManager redisManager;
|
||||||
|
private readonly IServiceProvider serviceProvider;
|
||||||
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, RedisManager redisManager, IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
this.videoTaskDB = videoTaskDB;
|
this.videoTaskDB = videoTaskDB;
|
||||||
this.vodClient = vodClient;
|
this.vodClient = vodClient;
|
||||||
this.packageInfoTaskDB = nackageInfoTaskDB;
|
this.packageInfoTaskDB = nackageInfoTaskDB;
|
||||||
this.redisManager = redisManager;
|
this.redisManager = redisManager;
|
||||||
|
this.serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据 Content-Type 映射文件后缀
|
// 根据 Content-Type 映射文件后缀
|
||||||
|
|
@ -266,9 +268,28 @@ namespace VideoAnalysisCore.Common
|
||||||
download.DownloadFileCompleted += async (object? sender, AsyncCompletedEventArgs e) =>
|
download.DownloadFileCompleted += async (object? sender, AsyncCompletedEventArgs e) =>
|
||||||
{
|
{
|
||||||
if (download.Status == DownloadStatus.Failed && e.Error != null)
|
if (download.Status == DownloadStatus.Failed && e.Error != null)
|
||||||
|
{
|
||||||
|
// 检查磁盘空间不足异常
|
||||||
|
if (e.Error.Message.Contains("not enough space on the disk", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{DateTime.Now} 下载失败:磁盘空间不足。尝试清理缓存...");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var scope = serviceProvider.CreateScope();
|
||||||
|
var clearJob = scope.ServiceProvider.GetRequiredService<TaskFileClearJob>();
|
||||||
|
await clearJob.Invoke();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"清理缓存失败: {ex.Message}");
|
||||||
|
}
|
||||||
|
res.SetException(new Exception($"磁盘空间不足,下载失败。请手动清理盘符 {Path.GetPathRoot(localPath)}。详细错误:{e.Error.Message}"));
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
res.SetException(e.Error);
|
res.SetException(e.Error);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (download.Status == DownloadStatus.Completed)
|
else if (download.Status == DownloadStatus.Completed)
|
||||||
{
|
{
|
||||||
res.SetResult();
|
res.SetResult();
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace VideoAnalysisCore.Common.Expand
|
||||||
/// 系统服务
|
/// 系统服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="app1"></param>
|
/// <param name="app1"></param>
|
||||||
public static void UseServiceSystem(this IHost app1)
|
public static void UseServiceSystem(this IHost app1,Action? action=null)
|
||||||
{
|
{
|
||||||
var app = app1.Services;
|
var app = app1.Services;
|
||||||
// 注册启动后的回调
|
// 注册启动后的回调
|
||||||
|
|
@ -46,7 +46,10 @@ namespace VideoAnalysisCore.Common.Expand
|
||||||
.Replace("+", "127.0.0.1");
|
.Replace("+", "127.0.0.1");
|
||||||
var uri = new Uri(normalizedAddress);
|
var uri = new Uri(normalizedAddress);
|
||||||
int port = uri.Port; // 这里的 port 就是你要的数字 (int)
|
int port = uri.Port; // 这里的 port 就是你要的数字 (int)
|
||||||
|
if (OperatingSystem.IsWindows())
|
||||||
OpenBrowser($"http://localhost:{uri.Port}/ui/index.html");
|
OpenBrowser($"http://localhost:{uri.Port}/ui/index.html");
|
||||||
|
if(action != null)
|
||||||
|
action();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -414,7 +414,9 @@ namespace VideoAnalysisCore.Common
|
||||||
}).ExecuteCommandAsync();
|
}).ExecuteCommandAsync();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await ExpandFunction.DeleteTaskFileAsync(tId, this);
|
//await ExpandFunction.DeleteTaskFileAsync(tId, this);
|
||||||
|
|
||||||
|
await ExpandFunction.DeleteTaskAllFileAsync(tId, this);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
|
@ -429,6 +431,7 @@ namespace VideoAnalysisCore.Common
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task InitChannel()
|
public async Task InitChannel()
|
||||||
{
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
if (Redis is null) throw new Exception("redis未初始化");
|
if (Redis is null) throw new Exception("redis未初始化");
|
||||||
//处理之前程序结束前未能执行完的情况
|
//处理之前程序结束前未能执行完的情况
|
||||||
var oldTaskCount = Redis.LLen(RedisExpandKey.IDTask);
|
var oldTaskCount = Redis.LLen(RedisExpandKey.IDTask);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ namespace VideoAnalysisCore.Controllers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 通用接口
|
/// 通用接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Authorize(AuthenticationSchemes = Authentication.vdAdmin)]
|
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
public class PublicController : ControllerBase
|
public class PublicController : ControllerBase
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
using Coravel.Invocable;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VideoAnalysisCore.Common;
|
||||||
|
|
||||||
|
namespace VideoAnalysisCore.Job
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 每小时强制清理缓存文件夹下所有内容的任务
|
||||||
|
/// </summary>
|
||||||
|
public class ClearAllCacheJob : IInvocable
|
||||||
|
{
|
||||||
|
public Task Invoke()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var cacheDir = AppCommon.TaskCachedFile;
|
||||||
|
if (!Directory.Exists(cacheDir))
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"{DateTime.Now} 开始强制清理缓存目录: {cacheDir}");
|
||||||
|
|
||||||
|
// 获取所有子目录
|
||||||
|
var directories = Directory.GetDirectories(cacheDir);
|
||||||
|
var i = 0;
|
||||||
|
foreach (var dir in directories)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 检查文件夹创建时间,如果是30分钟前的则删除(防止删除正在运行的任务)
|
||||||
|
if (Directory.GetCreationTime(dir) < DateTime.Now.AddMinutes(-30))
|
||||||
|
{
|
||||||
|
Directory.Delete(dir, true);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// 正在使用的文件夹会抛出异常,忽略即可
|
||||||
|
Console.WriteLine($"清理目录 {dir} 时发生错误 (可能正在使用): {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Console.WriteLine($"已删除过期缓存数量 {i}");
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"强制清理缓存任务发生异常: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using AlibabaCloud.SDK.Vod20170321;
|
using AlibabaCloud.SDK.Vod20170321;
|
||||||
using Coravel.Invocable;
|
using Coravel.Invocable;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using System;
|
using System;
|
||||||
|
|
@ -31,16 +31,16 @@ namespace VideoAnalysisCore.Job
|
||||||
this.videotaskDB = videotaskDB;
|
this.videotaskDB = videotaskDB;
|
||||||
this.redisManager = redisManager;
|
this.redisManager = redisManager;
|
||||||
}
|
}
|
||||||
public void DeleteTaskAllCaches()
|
public async Task DeleteTaskAllCachesAsync()
|
||||||
{
|
{
|
||||||
|
|
||||||
var startTime = -5;
|
var startTime = 0;
|
||||||
var timeSpan = startTime - 999;
|
var timeSpan = startTime - 999;
|
||||||
// 计算 6 天前已完成任务缓存
|
// 计算 {startTime} 天前已完成任务缓存
|
||||||
DateTime twoDaysAgo = DateTime.Now.AddDays(startTime);
|
DateTime twoDaysAgo = DateTime.Now.AddDays(startTime);
|
||||||
DateTime endDaysAgo = DateTime.Now.AddDays(timeSpan);
|
DateTime endDaysAgo = DateTime.Now.AddDays(timeSpan);
|
||||||
|
|
||||||
// 查询 2 天前任务执行完成的记录
|
// 查询 {startTime} 天前任务执行完成的记录
|
||||||
var completedTasks = videotaskDB.AsQueryable()
|
var completedTasks = videotaskDB.AsQueryable()
|
||||||
.Where(t => (
|
.Where(t => (
|
||||||
//筛选 结束任务 或者 错误任务
|
//筛选 结束任务 或者 错误任务
|
||||||
|
|
@ -54,23 +54,9 @@ namespace VideoAnalysisCore.Job
|
||||||
|
|
||||||
// 遍历查询结果,删除缓存文件
|
// 遍历查询结果,删除缓存文件
|
||||||
foreach (var taskId in completedTasks)
|
foreach (var taskId in completedTasks)
|
||||||
{
|
await ExpandFunction.DeleteTaskAllFileAsync(taskId, redisManager);
|
||||||
var path = taskId.ToString().LocalPath();
|
|
||||||
if (!string.IsNullOrEmpty(path) && Directory.Exists(path))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Directory.Delete(path, true);
|
|
||||||
Console.WriteLine($"已删除缓存文件: {taskId}");
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
public async Task DeleteTaskVideoCachesAsync()
|
||||||
{
|
|
||||||
Console.WriteLine($"删除缓存文件 {taskId} 时出错: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public async void DeleteTaskVideoCaches()
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -104,8 +90,8 @@ namespace VideoAnalysisCore.Job
|
||||||
public async Task Invoke()
|
public async Task Invoke()
|
||||||
{
|
{
|
||||||
Console.WriteLine($"{DateTime.Now} 执行=>{this.GetType().FullName}");
|
Console.WriteLine($"{DateTime.Now} 执行=>{this.GetType().FullName}");
|
||||||
DeleteTaskVideoCaches();
|
await DeleteTaskVideoCachesAsync();
|
||||||
DeleteTaskAllCaches();
|
await DeleteTaskAllCachesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue