parent
6981314257
commit
59c8171ce8
|
|
@ -56,6 +56,13 @@ namespace VideoAnalysisRazor.Layouts
|
||||||
Name = "登录页",
|
Name = "登录页",
|
||||||
Key = "Login",
|
Key = "Login",
|
||||||
HideInMenu = true,
|
HideInMenu = true,
|
||||||
|
},
|
||||||
|
new MenuDataItem
|
||||||
|
{
|
||||||
|
Path = "/VideoTaskShow",
|
||||||
|
Name = "视频任务预览",
|
||||||
|
Key = "VideoTaskShow",
|
||||||
|
HideInMenu = true,
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,10 @@
|
||||||
<Button Type="@ButtonType.Primary" Danger @onclick="() => ReStartClick(rowData.Data)">
|
<Button Type="@ButtonType.Primary" Danger @onclick="() => ReStartClick(rowData.Data)">
|
||||||
重试
|
重试
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
<Button Type="@ButtonType.Primary" Icon="@IconType.Outline.Search" @onclick="() => PreviewTask(rowData.Data)">
|
||||||
|
预览任务
|
||||||
|
</Button>
|
||||||
</DescriptionsItem>
|
</DescriptionsItem>
|
||||||
|
|
||||||
<DescriptionsItem Title="任务时间轴" Span="5">
|
<DescriptionsItem Title="任务时间轴" Span="5">
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ 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 INotificationService _notice { get; set; } = default!;
|
[Inject] private INotificationService _notice { get; set; } = default!;
|
||||||
|
|
@ -56,6 +57,10 @@ namespace Learn.VideoAnalysis.Components.Pages
|
||||||
reStartTask = query;
|
reStartTask = query;
|
||||||
modalShow = true;
|
modalShow = true;
|
||||||
}
|
}
|
||||||
|
void PreviewTask(VideoTaskDto task)
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo("/VideoTaskShow/"+task.Id);
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 重试
|
/// 重试
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
@page "/VideoTaskShow/{tid}"
|
||||||
|
<div>
|
||||||
|
<input type="file" id="videoFile" accept="video/*">
|
||||||
|
<input type="file" id="subtitleFile" accept=".json">
|
||||||
|
<input type="file" id="segmentsFile" accept=".json">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="video-container">
|
||||||
|
<video id="videoPlayer" controls></video>
|
||||||
|
<div id="subtitleArea" class="subtitles"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="segmentsContainer"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const
|
||||||
|
const videoPlayer = document.getElementById('videoPlayer');
|
||||||
|
const subtitleArea = document.getElementById('subtitleArea');
|
||||||
|
|
||||||
|
|
||||||
|
let subtitles = @captionsArr
|
||||||
|
let segments = @videoKnows
|
||||||
|
let displayButton = []
|
||||||
|
let lastSegments = null;
|
||||||
|
window.onload(() => {
|
||||||
|
videoPlayer.src = @videoPath
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
videoPlayer.addEventListener('timeupdate', function () {
|
||||||
|
const currentTime = videoPlayer.currentTime;
|
||||||
|
subtitleArea.textContent = '';
|
||||||
|
|
||||||
|
subtitles.forEach(subtitle => {
|
||||||
|
|
||||||
|
let textContent = subtitle.Text || subtitle.Content;
|
||||||
|
if (currentTime >= subtitle.Start
|
||||||
|
&& currentTime <= subtitle.End
|
||||||
|
&& subtitleArea.textContent != textContent) {
|
||||||
|
|
||||||
|
subtitleArea.textContent = textContent;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let segment = displayButton.find(s => currentTime >= s.开始秒
|
||||||
|
&& currentTime <= s.结束秒)
|
||||||
|
if (segment) {
|
||||||
|
segment.button.style.backgroundColor = "rgb(238, 200, 118)";
|
||||||
|
if (lastSegments && lastSegments != segment) lastSegments.button.style.backgroundColor = "rgb(240, 249, 235)";
|
||||||
|
lastSegments = segment
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function getF(segment) {
|
||||||
|
let sf = parseInt(segment.开始秒 / 60)
|
||||||
|
let sm = parseInt(segment.开始秒 % 60)
|
||||||
|
let ef = parseInt(segment.结束秒 / 60)
|
||||||
|
let em = parseInt(segment.结束秒 % 60)
|
||||||
|
return `${sf}:${sm} - ${ef}:${em}`
|
||||||
|
}
|
||||||
|
function displaySegments() {
|
||||||
|
const segmentsContainer = document.getElementById('segmentsContainer');
|
||||||
|
segmentsContainer.innerHTML = '';
|
||||||
|
segments.forEach(segment => {
|
||||||
|
const button = document.createElement('button');
|
||||||
|
displayButton.push(segment);
|
||||||
|
segment.button = button;
|
||||||
|
button.textContent =
|
||||||
|
`${getF(segment)} ${segment.主题}`;
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
videoPlayer.currentTime = segment.开始秒;
|
||||||
|
videoPlayer.play();
|
||||||
|
});
|
||||||
|
segmentsContainer.appendChild(button);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
using AntDesign;
|
||||||
|
using AntDesign.TableModels;
|
||||||
|
using FFmpeg.NET.Services;
|
||||||
|
using Learn.VideoAnalysis.Controllers.Dto;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
|
using Microsoft.AspNetCore.DataProtection.KeyManagement;
|
||||||
|
using SqlSugar;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VideoAnalysisCore.AICore.GPT.Dto;
|
||||||
|
using VideoAnalysisCore.AICore.SherpaOnnx;
|
||||||
|
using VideoAnalysisCore.Common;
|
||||||
|
using VideoAnalysisCore.Enum;
|
||||||
|
using VideoAnalysisCore.Model;
|
||||||
|
using VideoAnalysisCore.Model.Dto;
|
||||||
|
|
||||||
|
namespace Learn.VideoAnalysis.Components.Pages
|
||||||
|
{
|
||||||
|
public partial class VideoTaskShow : ComponentBase
|
||||||
|
{
|
||||||
|
|
||||||
|
[Inject] private ConfirmService ComfirmService { get; set; } = default!;
|
||||||
|
[Inject] private IHttpContextAccessor HttpContext { get; set; } = default!;
|
||||||
|
[Inject] private Repository<VideoTask> taskDB { get; set; } = default!;
|
||||||
|
|
||||||
|
private VideoTask nowTask { get; set; } = default!;
|
||||||
|
private string videoPath { get; set; } = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 字幕
|
||||||
|
/// </summary>
|
||||||
|
private SenseVoiceRes[] captionsArr { get; set; } = default!;
|
||||||
|
/// <summary>
|
||||||
|
/// 分段
|
||||||
|
/// </summary>
|
||||||
|
private VideoKnowRes[] videoKnows { get; set; } = default!;
|
||||||
|
/// <summary>
|
||||||
|
/// 在渲染页面之后
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="firstRender"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化
|
||||||
|
/// </summary>
|
||||||
|
protected override async void OnInitialized()
|
||||||
|
{
|
||||||
|
var routeData = HttpContext.HttpContext.GetRouteData();
|
||||||
|
if (routeData is null)
|
||||||
|
return;
|
||||||
|
long taskId = (long)routeData.Values["id"];
|
||||||
|
nowTask = await taskDB.GetFirstAsync(s => s.Id == taskId);
|
||||||
|
if(nowTask is null)
|
||||||
|
return;
|
||||||
|
captionsArr = RedisExpand.Redis.HMGet<SenseVoiceRes[]>(RedisExpandKey.Task(taskId), "Captions").FirstOrDefault();
|
||||||
|
videoKnows = RedisExpand.Redis.HMGet<VideoKnowRes[]>(RedisExpandKey.Task(taskId), "VideoKnows").FirstOrDefault();
|
||||||
|
videoPath = AppCommon.GetVideoPath(nowTask.Id.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> Comfirm(string message)
|
||||||
|
{
|
||||||
|
return await ComfirmService.Show(message, "提示", ConfirmButtons.YesNo, ConfirmIcon.Warning) == ConfirmResult.Yes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
|
||||||
|
* {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#video-container {
|
||||||
|
position: relative;
|
||||||
|
width: 1600px;
|
||||||
|
height: 850px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
video {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitles {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -40px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#segmentsContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 265px;
|
||||||
|
height: 850px;
|
||||||
|
gap: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
float: left;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
padding: 10px;
|
||||||
|
align-content: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#segmentsContainer button {
|
||||||
|
width: 100%;
|
||||||
|
height: 60px;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
color: rgb(103, 194, 58);
|
||||||
|
background-color: rgb(240, 249, 235);
|
||||||
|
border: 1px solid rgb(179, 225, 157);
|
||||||
|
}
|
||||||
|
|
||||||
|
#segmentsContainer button:hover {
|
||||||
|
background-color: rgb(248, 230, 191) !important;
|
||||||
|
border: 1px solid rgb(206, 187, 81);
|
||||||
|
}
|
||||||
|
|
@ -83,8 +83,7 @@ namespace Learn.VideoAnalysis.Controllers
|
||||||
public async Task<IActionResult> Test(long taskId)
|
public async Task<IActionResult> Test(long taskId)
|
||||||
{
|
{
|
||||||
//重新开始执行GPT分析
|
//重新开始执行GPT分析
|
||||||
RedisExpand.InsertChannel(RedisChannelEnum.ChatModelAnalysis
|
chatGPT.GetKnow(taskId.ToString());
|
||||||
, taskId);
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,6 +205,7 @@ namespace Learn.VideoAnalysis.Controllers
|
||||||
Subject = req.Subject,
|
Subject = req.Subject,
|
||||||
Tag = req.Tag,
|
Tag = req.Tag,
|
||||||
TagId = req.TagId,
|
TagId = req.TagId,
|
||||||
|
MediaName = req.MediaName
|
||||||
};
|
};
|
||||||
//入库
|
//入库
|
||||||
task.Id = await videoTaskDB.InsertReturnBigIdentityAsync(task);
|
task.Id = await videoTaskDB.InsertReturnBigIdentityAsync(task);
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,12 @@ namespace Learn.VideoAnalysis.Controllers.Dto
|
||||||
[Url(ErrorMessage = "请输入有效的 URL")]
|
[Url(ErrorMessage = "请输入有效的 URL")]
|
||||||
public string MediaUrl { get; set; } = string.Empty;
|
public string MediaUrl { get; set; } = string.Empty;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 资源名称
|
||||||
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "资源名称是必要的")]
|
||||||
|
[Url(ErrorMessage = "请输入有效的 资源名称")]
|
||||||
|
public string MediaName { get; set; } = string.Empty;
|
||||||
|
/// <summary>
|
||||||
/// ApiKey
|
/// ApiKey
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Required(ErrorMessage = "接口Token是必填项")]
|
[Required(ErrorMessage = "接口Token是必填项")]
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using Mapster;
|
||||||
using VideoAnalysisCore.AICore.GPT;
|
using VideoAnalysisCore.AICore.GPT;
|
||||||
using VideoAnalysisCore.AICore.GPT.KIMI;
|
using VideoAnalysisCore.AICore.GPT.KIMI;
|
||||||
using VideoAnalysisCore.AICore.GPT.ChatGPT;
|
using VideoAnalysisCore.AICore.GPT.ChatGPT;
|
||||||
|
using Microsoft.Extensions.FileProviders;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -101,7 +102,15 @@ namespace Learn.VideoAnalysis
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles(new StaticFileOptions
|
||||||
|
{
|
||||||
|
FileProvider = new PhysicalFileProvider(AppCommon.TaskCachedFile),
|
||||||
|
RequestPath = "/video",
|
||||||
|
//OnPrepareResponse = ctx => //»º´æ
|
||||||
|
//{
|
||||||
|
// ctx.Context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.CacheControl] = "public,max - age = 31536000";
|
||||||
|
//}
|
||||||
|
});
|
||||||
app.UseAntiforgery();
|
app.UseAntiforgery();
|
||||||
|
|
||||||
app.MapRazorComponents<App>()
|
app.MapRazorComponents<App>()
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,19 @@
|
||||||
"ApiKey": "sk-8BvvhESZIkgUbiaaJhglPxFa4o2X9H3xEv9lXELrWWwGxHWY"
|
"ApiKey": "sk-8BvvhESZIkgUbiaaJhglPxFa4o2X9H3xEv9lXELrWWwGxHWY"
|
||||||
},
|
},
|
||||||
"ChatGpt": {
|
"ChatGpt": {
|
||||||
"Host": "https://api.oaibest.com/",
|
"Host": "https://api.g4f.icu/",
|
||||||
|
//"Host": "https://api.oaibest.com/",
|
||||||
"ApiKey": "sk-D15tBln31N7dI9Fi7lds7OySFv5tOEK7DMNsG5rY2E6DCr4s"
|
"ApiKey": "sk-D15tBln31N7dI9Fi7lds7OySFv5tOEK7DMNsG5rY2E6DCr4s"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"DB": {
|
"DB": {
|
||||||
"ConnectionString": "AllowLoadLocalInfile=true;Server=192.168.2.9;User ID=root;Password=qwe123!@#;Port=3306;Database=learn.videoanalysis;CharSet=utf8mb4;pooling=true;SslMode=None",
|
"ConnectionString": "AllowLoadLocalInfile=true;Server=192.168.2.9;User ID=root;Password=qwe123!@#;Port=3306;Database=learn.videoanalysis;CharSet=utf8mb4;pooling=true;SslMode=None",
|
||||||
"SqlType": "MySql",
|
"SqlType": "MySql",
|
||||||
"UpdateTable": true,
|
"UpdateTable": true
|
||||||
|
},
|
||||||
|
"KnowsDB": {
|
||||||
|
"ConnectionString": "Server=47.109.35.116;Database=ResourceBank;UID=live;Password=Woshiren^&*();MultipleActiveResultSets=true;Encrypt=True;TrustServerCertificate=True;",
|
||||||
|
"SqlType": "SqlServer"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,5 +16,6 @@ namespace VideoAnalysisCore.AICore.GPT
|
||||||
/// <param name="task">任务id</param>
|
/// <param name="task">任务id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<TaskRes> CallGPT(string task);
|
public Task<TaskRes> CallGPT(string task);
|
||||||
|
public Task<TaskRes> GetKnow(string task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ using System.Reflection;
|
||||||
using VideoAnalysisCore.Model.Dto;
|
using VideoAnalysisCore.Model.Dto;
|
||||||
using VideoAnalysisCore.AICore.GPT.Dto;
|
using VideoAnalysisCore.AICore.GPT.Dto;
|
||||||
using VideoAnalysisCore.AICore.GPT;
|
using VideoAnalysisCore.AICore.GPT;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.AICore.GPT.ChatGPT
|
namespace VideoAnalysisCore.AICore.GPT.ChatGPT
|
||||||
{
|
{
|
||||||
|
|
@ -19,16 +20,184 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
|
||||||
private readonly ChatGPTClient chatClient;
|
private readonly ChatGPTClient chatClient;
|
||||||
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;
|
||||||
/// <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)
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<VideoKnowRes> MergeRes(VideoKnowRes[] timeBases)
|
||||||
|
{
|
||||||
|
if (timeBases == null || timeBases.Count() == 0)
|
||||||
|
{
|
||||||
|
return new List<VideoKnowRes>();
|
||||||
|
}
|
||||||
|
var mergedList = new List<VideoKnowRes>();
|
||||||
|
// 初始化合并段
|
||||||
|
var current = timeBases.First();
|
||||||
|
foreach (var next in timeBases)
|
||||||
|
{
|
||||||
|
// 如果类型相同,则扩展时间段
|
||||||
|
if (current.主题 == next.主题)
|
||||||
|
{
|
||||||
|
current.结束秒 = Math.Max(current.结束秒.Value, next.结束秒.Value);
|
||||||
|
current.内容总结 += next.内容总结;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 类型不同,将当前时间段加入结果列表,并开始新时间段
|
||||||
|
mergedList.Add(current);
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 添加最后的时间段
|
||||||
|
mergedList.Add(current);
|
||||||
|
return mergedList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取知识点
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="task">任务id</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<TaskRes> GetKnow(string task)
|
||||||
|
{
|
||||||
|
var taskId = long.Parse(task);
|
||||||
|
var taskInfo = await videoTaskDB.AsQueryable()
|
||||||
|
.Where(s => s.Id == taskId)
|
||||||
|
.FirstAsync();
|
||||||
|
var subject = "数学";
|
||||||
|
var xkwKnows = await knowledgeInfoDB.AsQueryable()
|
||||||
|
.Where(s => s.Course_Id == 27
|
||||||
|
&& s.Depth == 2)
|
||||||
|
.Select(s => s.Name).ToArrayAsync();
|
||||||
|
string title = "周三(1.3)《第八章——统计与概率:超几何分布的极限为二项分布》";
|
||||||
|
var fileNameResFormat = "{授课章节: string|null, 授课内容:string}";
|
||||||
|
var fileNamePostMessages = title +
|
||||||
|
" 这是一堂课的标题,请你帮我分析一些关于课堂方面的内容." +
|
||||||
|
$"1.分析出高中{subject}课堂授课的主要章节(例如 章节: 数列),章节范围限定在[{xkwKnows}]范围." +
|
||||||
|
$"2.分析出这堂课的主要授课内容." +
|
||||||
|
$"输出格式 json字符串 对象格式{fileNameResFormat}";
|
||||||
|
var fileNameInfoRes = await ChatAsync<FileNameInfo>(task, fileNamePostMessages, fileNameResFormat);
|
||||||
|
|
||||||
|
var captions = ExpandFunction.GetSpeakerCaptions(task);
|
||||||
|
var criteriaBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
var resFormat = """[{"StartTime":开始秒(number),"EndTime":结束秒(number),"Section":章节(string),"Theme":主题(string),"Content":内容总结(string)}]""";
|
||||||
|
var know = await knowledgeInfoDB.GetFirstAsync(s => s.Name == fileNameInfoRes.授课章节);
|
||||||
|
var knowledgeInfos = await knowledgeInfoDB.AsQueryable().ToChildListAsync(s => s.Parent_Id, know.Id);
|
||||||
|
var knows = "数列的概念,数列的定义,项的表示,数列的表示方法,通项公式,递推公式,图像表示,数列的类型,等差数列,等比数列,其他特殊数列,数列的性质,单调性,有限性,数列的求和,等差数列求和公式,等比数列求和公式,数列极限,递推关系";
|
||||||
|
knows = string.Join(',', knowledgeInfos.Select(s => s.Name));
|
||||||
|
var postMessages =
|
||||||
|
$"你的任务是分析视频字幕内容并提取出中国高考考试试题方法点,然后根据步骤分析出内容片段" +
|
||||||
|
$"按以下步骤完成:" +
|
||||||
|
$"1.识别方法点:提取字幕内容中与{subject}考试相关的方法点。" +
|
||||||
|
$"2.分类方法点:按学科方法点,细化到具体章节与主题(例如“章节:数列 主题:数列的基本概念”)。" +
|
||||||
|
$"3.分析总结:基于提取出的方法点名称来匹配我提供的方法点名称" +
|
||||||
|
$"提供的方法点名称(基本概念,课堂练习,{knows},例题讲解)。" +
|
||||||
|
$"4.关联合并相似的知识点来合并为内容片段。" +
|
||||||
|
$"内容片段使用关联知识点中的最小(开始秒)和(最大)结束秒,主题为关联知识点的主题分析,内容总结为关联知识点的内容总结分析。" +
|
||||||
|
$"延长内容片段时间区间来获取更加详细的上下文。" +
|
||||||
|
$"输入:包含时间戳的视频字幕文本。" +
|
||||||
|
$"以下是包含时间的视频字幕文本。" +
|
||||||
|
$"字幕格式(说话人:开始秒:结束秒:内容|下一段字幕).字幕列表 {captions.Captions}" +
|
||||||
|
$"输出格式({resFormat})";
|
||||||
|
//var postMessages =
|
||||||
|
// $"你是一名专业的教育视频内容分析助手,主要任务是分析视频字幕内容,精准提取出与中国高考数学考试相关的试题方法点。" +
|
||||||
|
// $"按以下步骤完成:" +
|
||||||
|
// $"1.准确识别方法点:从字幕中提取与{subject}考试紧密相关的方法点,尤其关注与给定方法点类别相关的内容" +
|
||||||
|
// $"2.深入分析总结:依据给定的方法点类别进行约束,确定提取出的方法点所属类别。" +
|
||||||
|
// $"给定方法点包括(基本概念,课堂练习,例题讲解,解题技巧,{gjz})。" +
|
||||||
|
// $"3.细致分类方法点:按照学科方法点进行分类,具体细化到特定章节与主题,格式为 “章节:具体章节名称 主题:具体主题名称" +
|
||||||
|
// $"4.合理合并相似方法点为内容片段,确保内容的连贯性和逻辑性" +
|
||||||
|
// $"5.关联每个内容片段的方法点所有的时间并结构化输出。" +
|
||||||
|
// $"尽可能延内容片段时间区间,以获取详细的方法点上下文。" +
|
||||||
|
// $"输入:包含时间戳的视频字幕文本。输出格式:开始秒,结束秒,主题,内容总结" +
|
||||||
|
// $"以下是包含时间的视频字幕文本。" +
|
||||||
|
// $"字幕格式(说话人:开始秒:结束秒:内容|下一段字幕).字幕列表 {captions.Captions}" +
|
||||||
|
// $"返回固定的JSON格式({resFormat})";
|
||||||
|
|
||||||
|
var questionRes =await ChatAsync<VideoKnowRes[]>(task, postMessages, resFormat);
|
||||||
|
await RedisExpand.Redis
|
||||||
|
.HMSetAsync(RedisExpandKey.Task(task), "VideoKnows", questionRes);
|
||||||
|
|
||||||
|
var postMessages1 =
|
||||||
|
$"你的任务是分析json内容并合并含义相似的主题为新的主题" +
|
||||||
|
$"按以下步骤完成:" +
|
||||||
|
$"1.合理合并主题字段重复相似的对象为新的json对象,确保内容的连贯性和逻辑性。" +
|
||||||
|
$"2.合并对象属性持续时间低于60秒的对象" +
|
||||||
|
$"3.结构化输出。" +
|
||||||
|
$"输入:json对象 包含总结开始秒,结束秒,持续时间,主题,章节,内容总结" +
|
||||||
|
$"以下是包含json内容的文本。" +
|
||||||
|
$" {JsonSerializer.Serialize(questionRes)}" +
|
||||||
|
$"返回固定的JSON格式({resFormat})";
|
||||||
|
|
||||||
|
|
||||||
|
var questionRes1 = await ChatAsync<VideoKnowRes[]>(task, postMessages1, resFormat);
|
||||||
|
//questionRes1 = MergeRes(questionRes1).ToArray();
|
||||||
|
|
||||||
|
var gptRes = new TaskRes(captions);
|
||||||
|
await RedisExpand.Redis
|
||||||
|
.HMSetAsync(RedisExpandKey.Task(task), "ChatAnalysis", gptRes);
|
||||||
|
RedisExpand.InsertChannel(RedisChannelEnum.EndTask, task);
|
||||||
|
return gptRes;
|
||||||
|
}
|
||||||
|
public async Task<T> ChatAsync<T>(string task,string postMessages,string resFormat)
|
||||||
|
{
|
||||||
|
var maxTokens = 4000;
|
||||||
|
var chatRep = new ChatRequest
|
||||||
|
{
|
||||||
|
max_tokens = maxTokens,
|
||||||
|
temperature = 0.3f,
|
||||||
|
messages = [
|
||||||
|
new Message(postMessages,"system"),
|
||||||
|
new Message(resFormat,"assistant"),
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
RedisExpand.SetTaskGPTReqCached(task, chatRep);
|
||||||
|
var chatResp = await chatClient.Chat(chatRep);
|
||||||
|
var chatResContent = chatResp?.res;
|
||||||
|
if (string.IsNullOrEmpty(chatResContent))
|
||||||
|
throw new Exception("GPT返回message无效结果");
|
||||||
|
if (chatResp != null)
|
||||||
|
RedisExpand.SetTaskGPTCached(task, new object[] { chatResp.Value.res, chatResp.Value.u });
|
||||||
|
|
||||||
|
chatResContent = chatResContent?.Replace("字幕内容", "课堂情况");
|
||||||
|
chatResContent = chatResContent?.Replace("\n", "");
|
||||||
|
chatResContent = chatResContent?.Replace("```json", "");
|
||||||
|
chatResContent = chatResContent?.Replace("```", "");
|
||||||
|
chatResContent = chatResContent?.Replace("}{", "},{");
|
||||||
|
chatResContent = chatResContent?.Replace("}|{", "},{");
|
||||||
|
chatResContent = chatResContent?.Trim();
|
||||||
|
var startsStr = typeof(T).IsArray? "[" :"{";
|
||||||
|
var endStr = typeof(T).IsArray? "]" : "}";
|
||||||
|
if (!chatResContent.StartsWith(startsStr))
|
||||||
|
chatResContent = startsStr + chatResContent;
|
||||||
|
if (!chatResContent.EndsWith(endStr))
|
||||||
|
chatResContent = chatResContent + endStr;
|
||||||
|
var questionRes = JsonSerializer.Deserialize<T>(chatResContent);
|
||||||
|
if (questionRes is null)
|
||||||
|
throw new Exception("ChatGPT返回无效结果");
|
||||||
|
//var totalTokens = chatResp?.u.total_tokens ?? 0;
|
||||||
|
//if (totalTokens > 1)
|
||||||
|
//{
|
||||||
|
// var tid = long.Parse(task);
|
||||||
|
// await videoTaskDB.AsUpdateable()
|
||||||
|
// .SetColumns(it => it.TotalTokens == totalTokens)//SetColumns是可以叠加的 写2个就2个字段赋值
|
||||||
|
// .Where(it => it.Id == tid)
|
||||||
|
// .ExecuteCommandAsync();
|
||||||
|
//}
|
||||||
|
return questionRes;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 访问GPT
|
/// 访问GPT
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,28 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.AICore.GPT.Dto
|
namespace VideoAnalysisCore.AICore.GPT.Dto
|
||||||
{
|
{
|
||||||
|
public class VideoKnowRes
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 问题解释
|
||||||
|
/// </summary>
|
||||||
|
public float? 开始秒 { get; set; }
|
||||||
|
public float? 结束秒 { get; set; }
|
||||||
|
public float? 持续时间 => (结束秒 ?? 0) - 开始秒??0;
|
||||||
|
public string? 主题 { get; set; }
|
||||||
|
public string? 章节 { get; set; }
|
||||||
|
public string? 内容总结 { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
public class FileNameInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 问题解释
|
||||||
|
/// </summary>
|
||||||
|
public string? 授课章节 { get; set; }
|
||||||
|
public string? 授课内容 { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
public class QuestionRes
|
public class QuestionRes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace VideoAnalysisCore.AICore.GPT.KIMI
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// kimi 文本模型
|
/// kimi 文本模型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class KIMI_GPT : IBserGPT
|
public class KIMI_GPT // : IBserGPT
|
||||||
{
|
{
|
||||||
private readonly MoonshotClient moonshotClient;
|
private readonly MoonshotClient moonshotClient;
|
||||||
private readonly Repository<CourseGradingCriteria> criteriaDB;
|
private readonly Repository<CourseGradingCriteria> criteriaDB;
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,8 @@ namespace VideoAnalysisCore.AICore.SherpaOnnx
|
||||||
}
|
}
|
||||||
|
|
||||||
await RedisExpand.Redis.HMSetAsync(RedisExpandKey.Task(task), "Captions", res);
|
await RedisExpand.Redis.HMSetAsync(RedisExpandKey.Task(task), "Captions", res);
|
||||||
RedisExpand.InsertChannel(Enum.RedisChannelEnum.ParsingSpeaker, task);
|
//RedisExpand.InsertChannel(Enum.RedisChannelEnum.ParsingSpeaker, task);
|
||||||
|
RedisExpand.InsertChannel(Enum.RedisChannelEnum.ChatModelAnalysis, task);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,16 @@ using FreeRedis;
|
||||||
using Microsoft.Extensions.DependencyModel;
|
using Microsoft.Extensions.DependencyModel;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using SqlSugar.IOC;
|
using SqlSugar.IOC;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.Loader;
|
using System.Runtime.Loader;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using UserCenter.Model.Interface;
|
||||||
using VideoAnalysisCore.AICore.SherpaOnnx;
|
using VideoAnalysisCore.AICore.SherpaOnnx;
|
||||||
using VideoAnalysisCore.Enum;
|
using VideoAnalysisCore.Enum;
|
||||||
|
using VideoAnalysisCore.Interface;
|
||||||
using VideoAnalysisCore.Model.Dto;
|
using VideoAnalysisCore.Model.Dto;
|
||||||
using Whisper.net;
|
using Whisper.net;
|
||||||
|
|
||||||
|
|
@ -29,22 +33,26 @@ namespace VideoAnalysisCore.Common
|
||||||
/// 主库数据库表类型
|
/// 主库数据库表类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly IEnumerable<Type> DbMatserType;
|
public static readonly IEnumerable<Type> DbMatserType;
|
||||||
|
public static readonly IEnumerable<Type> KnowsType;
|
||||||
static AppCommon()
|
static AppCommon()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
Assemblies = ExpandFunction.GetAssemblies();
|
Assemblies = ExpandFunction.GetAssemblies();
|
||||||
var assembliesType = Assemblies.Where(s => s.FullName.Contains("VideoAnalysis")).SelectMany(s => s.ExportedTypes
|
var assembliesType = Assemblies.Where(s => s.FullName.Contains("VideoAnalysis")).SelectMany(s => s.ExportedTypes
|
||||||
.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false)));
|
.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false)));
|
||||||
DbMatserType = assembliesType;
|
DbMatserType = assembliesType
|
||||||
|
.Where(u => u.GetInterfaces().Contains(typeof(IDB)));
|
||||||
|
KnowsType = assembliesType
|
||||||
|
.Where(u =>u.GetInterfaces().Contains(typeof(IKnowsDB)));
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
//.Where(u => !u.IsDefined(typeof(SplitTableAttribute), false))
|
//.Where(u => !u.IsDefined(typeof(SplitTableAttribute), false))
|
||||||
//.Where(u => !typeof(Model.DataCenterYH.IDataCenterYHModel).IsAssignableFrom(u))
|
//.Where(u => !typeof(Model.DataCenterYH.IDataCenterYHModel).IsAssignableFrom(u))
|
||||||
//.Where(u => !u.IsSubclassOf(typeof(YQ_BaseEntity)));
|
//.Where(u => !u.IsSubclassOf(typeof(YQ_BaseEntity)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -66,6 +74,13 @@ namespace VideoAnalysisCore.Common
|
||||||
public static string AIModelFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AICore", "_Static");
|
public static string AIModelFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AICore", "_Static");
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取视频路径
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tid"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetVideoPath(string tid) =>
|
||||||
|
Path.Combine(TaskCachedFile, tid, tid + ".mp4");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -140,35 +155,46 @@ namespace VideoAnalysisCore.Common
|
||||||
{
|
{
|
||||||
var captionsArr = RedisExpand.Redis.HMGet<SenseVoiceRes[]>(RedisExpandKey.Task(task), "Captions").FirstOrDefault();
|
var captionsArr = RedisExpand.Redis.HMGet<SenseVoiceRes[]>(RedisExpandKey.Task(task), "Captions").FirstOrDefault();
|
||||||
var speakerArr = RedisExpand.Redis.HMGet<OfflineSpeakerRes[]>(RedisExpandKey.Task(task), "Speaker").FirstOrDefault();
|
var speakerArr = RedisExpand.Redis.HMGet<OfflineSpeakerRes[]>(RedisExpandKey.Task(task), "Speaker").FirstOrDefault();
|
||||||
if (captionsArr is null || captionsArr.Length == 0
|
if (captionsArr is null || captionsArr.Length == 0)
|
||||||
|| speakerArr is null || speakerArr.Length == 0)
|
//|| speakerArr is null || speakerArr.Length == 0)
|
||||||
throw new Exception("音频解析数据异常");
|
throw new Exception("音频解析数据异常");
|
||||||
// 教师说话人Id
|
// 教师说话人Id
|
||||||
var techerId = speakerArr.GroupBy(s=>s.SpeakerIndex).Select(s => (s.Key,s.Sum(x=>x.Total)))
|
var techerId = speakerArr is null || !speakerArr.Any()
|
||||||
|
? 0
|
||||||
|
:speakerArr.GroupBy(s=>s.SpeakerIndex).Select(s => (s.Key,s.Sum(x=>x.Total)))
|
||||||
.OrderByDescending(s=>s.Item2).First().Key;
|
.OrderByDescending(s=>s.Item2).First().Key;
|
||||||
var teacherSpeaking = 0f;
|
var teacherSpeaking = 0f;
|
||||||
var studentSpeaking = 0f;
|
var studentSpeaking = 0f;
|
||||||
var results = new Dictionary<SenseVoiceRes, List<int>>();
|
var results = new Dictionary<SenseVoiceRes, List<int>>();
|
||||||
foreach (var segment in captionsArr)
|
if (speakerArr is null || speakerArr.Count() == 0)
|
||||||
{
|
{
|
||||||
var spList = new List<int>();
|
var ss = new List<int> { 1 };
|
||||||
foreach (var speakerRes in speakerArr)
|
results = captionsArr.ToDictionary(s => s, s=> ss);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var segment in captionsArr)
|
||||||
{
|
{
|
||||||
if (speakerRes.Start > segment.End)
|
var spList = new List<int>();
|
||||||
break;
|
foreach (var speakerRes in speakerArr)
|
||||||
if (segment.Start <= speakerRes.End
|
|
||||||
&& segment.End >= speakerRes.Start)
|
|
||||||
{
|
{
|
||||||
if (speakerRes.SpeakerIndex == techerId)
|
if (speakerRes.Start > segment.End)
|
||||||
teacherSpeaking += speakerRes.Total;
|
break;
|
||||||
else
|
if (segment.Start <= speakerRes.End
|
||||||
studentSpeaking += speakerRes.Total;
|
&& segment.End >= speakerRes.Start)
|
||||||
spList.Add(speakerRes.SpeakerIndex);
|
{
|
||||||
|
if (speakerRes.SpeakerIndex == techerId)
|
||||||
|
teacherSpeaking += speakerRes.Total;
|
||||||
|
else
|
||||||
|
studentSpeaking += speakerRes.Total;
|
||||||
|
spList.Add(speakerRes.SpeakerIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
var sp = spList.Distinct().ToList();
|
||||||
|
if (sp.Count > 0)
|
||||||
|
results.Add(segment, sp);
|
||||||
}
|
}
|
||||||
var sp = spList.Distinct().ToList();
|
|
||||||
if(sp.Count>0)
|
|
||||||
results.Add(segment, sp);
|
|
||||||
}
|
}
|
||||||
//拼接 提示词字幕源
|
//拼接 提示词字幕源
|
||||||
var stringBuilder = new StringBuilder();
|
var stringBuilder = new StringBuilder();
|
||||||
|
|
@ -352,6 +378,10 @@ namespace VideoAnalysisCore.Common
|
||||||
/// 数据库配置
|
/// 数据库配置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DBConfig DB { get; set; } = new DBConfig();
|
public DBConfig DB { get; set; } = new DBConfig();
|
||||||
|
/// <summary>
|
||||||
|
/// 知识点数据库
|
||||||
|
/// </summary>
|
||||||
|
public DBConfig KnowsDB { get; set; } = new DBConfig();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -213,7 +213,7 @@ namespace VideoAnalysisCore.Common
|
||||||
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
|
if (scope is null || scope.ServiceProvider.GetService<IBserGPT>() is null)
|
||||||
throw new Exception("IBserGPT 未注入");
|
throw new Exception("IBserGPT 未注入");
|
||||||
else
|
else
|
||||||
return scope.ServiceProvider.GetService<IBserGPT>()?.CallGPT(task) ?? Task.CompletedTask;
|
return scope.ServiceProvider.GetService<IBserGPT>()?.GetKnow(task) ?? Task.CompletedTask;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
SubscribeList.Add(RedisChannelEnum.EndTask,
|
SubscribeList.Add(RedisChannelEnum.EndTask,
|
||||||
|
|
@ -277,6 +277,7 @@ namespace VideoAnalysisCore.Common
|
||||||
.Where(it => it.Id == taskID)
|
.Where(it => it.Id == taskID)
|
||||||
.ExecuteCommandAsync() == 1;
|
.ExecuteCommandAsync() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 触发
|
/// 触发
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using VideoAnalysisCore.Interface;
|
||||||
using VideoAnalysisCore.Model;
|
using VideoAnalysisCore.Model;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.Common
|
namespace VideoAnalysisCore.Common
|
||||||
|
|
@ -13,7 +14,10 @@ namespace VideoAnalysisCore.Common
|
||||||
{
|
{
|
||||||
public Repository()
|
public Repository()
|
||||||
{
|
{
|
||||||
base.Context = DbScoped.SugarScope;
|
if(typeof(T).GetInterfaces().Contains(typeof(IKnowsDB)))
|
||||||
|
base.Context = DbScoped.SugarScope.GetConnection(1001);
|
||||||
|
else
|
||||||
|
base.Context = DbScoped.SugarScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,13 @@ namespace VideoAnalysisCore.Common
|
||||||
DbType =AppCommon.Config.DB.SqlType,
|
DbType =AppCommon.Config.DB.SqlType,
|
||||||
IsAutoCloseConnection = true//自动释放
|
IsAutoCloseConnection = true//自动释放
|
||||||
},
|
},
|
||||||
|
new IocConfig()
|
||||||
|
{
|
||||||
|
ConfigId =1001,
|
||||||
|
ConnectionString = AppCommon.Config.KnowsDB.ConnectionString,
|
||||||
|
DbType =AppCommon.Config.KnowsDB.SqlType,
|
||||||
|
IsAutoCloseConnection = true//自动释放
|
||||||
|
},
|
||||||
};
|
};
|
||||||
services.AddSingleton(typeof(Repository<>));
|
services.AddSingleton(typeof(Repository<>));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace VideoAnalysisCore.Interface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 表属于IDB
|
||||||
|
/// </summary>
|
||||||
|
interface IDB
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace VideoAnalysisCore.Interface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 表属于KnowsDB
|
||||||
|
/// </summary>
|
||||||
|
interface IKnowsDB
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Net;
|
||||||
using UserCenter.Model.Enum;
|
using UserCenter.Model.Enum;
|
||||||
using VideoAnalysisCore.AICore.SherpaOnnx;
|
using VideoAnalysisCore.AICore.SherpaOnnx;
|
||||||
using VideoAnalysisCore.Enum;
|
using VideoAnalysisCore.Enum;
|
||||||
|
using VideoAnalysisCore.Interface;
|
||||||
using Whisper.net;
|
using Whisper.net;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.Model
|
namespace VideoAnalysisCore.Model
|
||||||
|
|
@ -14,7 +15,7 @@ namespace VideoAnalysisCore.Model
|
||||||
/// 课堂评分标准
|
/// 课堂评分标准
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarTable("coursegradingcriteria")]
|
[SugarTable("coursegradingcriteria")]
|
||||||
public class CourseGradingCriteria
|
public class CourseGradingCriteria: IDB
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Id
|
/// Id
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,11 @@ namespace VideoAnalysisCore.Model.Dto
|
||||||
[DisplayName("媒体路径")]
|
[DisplayName("媒体路径")]
|
||||||
public string MediaUrl { get; set; } = string.Empty;
|
public string MediaUrl { get; set; } = string.Empty;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 媒体名称
|
||||||
|
/// </summary>
|
||||||
|
[DisplayName("媒体名称")]
|
||||||
|
public string MediaName { get; set; } = string.Empty;
|
||||||
|
/// <summary>
|
||||||
/// 自定义ID
|
/// 自定义ID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayName("自定义ID")]
|
[DisplayName("自定义ID")]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
using SqlSugar;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VideoAnalysisCore.Interface;
|
||||||
|
|
||||||
|
namespace VideoAnalysisCore.Model.Dto
|
||||||
|
{
|
||||||
|
[SugarTable("knowledgeinfo")]
|
||||||
|
public class KnowledgeInfo: IKnowsDB
|
||||||
|
{
|
||||||
|
[SugarColumn(IsPrimaryKey = true, ColumnDescription = "Id 主键", ColumnName = "id")]
|
||||||
|
public long Id { get; set; }
|
||||||
|
[SugarColumn(ColumnDescription = "自己数据库Id", ColumnName = "thisid")]
|
||||||
|
public long ThisId { get; set; }
|
||||||
|
[SugarColumn(InsertServerTime = true, ColumnDescription = "创建时间", ColumnName = "createtime")]
|
||||||
|
public DateTime CreateTime { get; set; }
|
||||||
|
[SugarColumn(UpdateServerTime = true, InsertServerTime = true, IsNullable = true, ColumnDescription = "更新时间", ColumnName = "updatetime")]
|
||||||
|
public DateTime UpdateTime { get; set; }
|
||||||
|
[SugarColumn(ColumnDescription = "是否删除 true=删除", DefaultValue = "false", ColumnName = "deletestate")]
|
||||||
|
public bool DeleteState { get; set; }
|
||||||
|
[SugarColumn(ColumnDescription = "排序", ColumnName = "ordinal", DefaultValue = "0")]
|
||||||
|
public int Ordinal { get; set; }
|
||||||
|
|
||||||
|
[SugarColumn(ColumnDataType = "nvarchar(200)", ColumnDescription = "知识点名称", ColumnName = "name", IsNullable = true)]
|
||||||
|
public string Name { get; set; }
|
||||||
|
[SugarColumn(ColumnDescription = "节点深度,一级节点的深度为1,二级节点的深度为2,以此类推。", ColumnName = "depth", IsNullable = true)]
|
||||||
|
public long Depth { get; set; }
|
||||||
|
[SugarColumn(ColumnDescription = "适用于精简版", ColumnName = "for_lite", IsNullable = true)]
|
||||||
|
public bool For_Lite { get; set; }
|
||||||
|
[SugarColumn(ColumnDescription = "父节点ID", ColumnName = "parent_id", IsNullable = true)]
|
||||||
|
public long Parent_Id { get; set; }
|
||||||
|
[SugarColumn(ColumnDescription = "root节点的ID", ColumnName = "root_id", IsNullable = true)]
|
||||||
|
public long Root_Id { get; set; }
|
||||||
|
[SugarColumn(ColumnDataType = "nvarchar(100)", ColumnDescription = "节点类型,可用值:NODE、KNOWLEDGE_POINT、TESTING_POINT,分别代表普通节点、知识点、考点。", ColumnName = "type", IsNullable = true)]
|
||||||
|
public string Type { get; set; }
|
||||||
|
[SugarColumn(ColumnDescription = "课程ID", ColumnName = "course_id", IsNullable = true)]
|
||||||
|
public long Course_Id { get; set; }
|
||||||
|
[SugarColumn(InsertServerTime = true, ColumnDescription = "学科网创建时间", ColumnName = "create_time", IsNullable = true)]
|
||||||
|
public DateTime Create_Time { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ using UserCenter.Model.Enum;
|
||||||
using VideoAnalysisCore.AICore.GPT.Dto;
|
using VideoAnalysisCore.AICore.GPT.Dto;
|
||||||
using VideoAnalysisCore.AICore.SherpaOnnx;
|
using VideoAnalysisCore.AICore.SherpaOnnx;
|
||||||
using VideoAnalysisCore.Enum;
|
using VideoAnalysisCore.Enum;
|
||||||
|
using VideoAnalysisCore.Interface;
|
||||||
using Whisper.net;
|
using Whisper.net;
|
||||||
|
|
||||||
namespace VideoAnalysisCore.Model
|
namespace VideoAnalysisCore.Model
|
||||||
|
|
@ -14,7 +15,7 @@ namespace VideoAnalysisCore.Model
|
||||||
/// 视频任务模型
|
/// 视频任务模型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarTable("videotask")]
|
[SugarTable("videotask")]
|
||||||
public class VideoTask
|
public class VideoTask: IDB
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 任务id
|
/// 任务id
|
||||||
|
|
@ -27,6 +28,10 @@ namespace VideoAnalysisCore.Model
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string MediaUrl { get; set; } = string.Empty;
|
public string MediaUrl { get; set; } = string.Empty;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 媒体文件名称
|
||||||
|
/// </summary>
|
||||||
|
public string MediaName { get; set; } = string.Empty;
|
||||||
|
/// <summary>
|
||||||
/// 下载后本地媒体目录
|
/// 下载后本地媒体目录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string LocalMediaPath { get; set; } = string.Empty;
|
public string LocalMediaPath { get; set; } = string.Empty;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue