完善 任务预览功能

This commit is contained in:
小肥羊 2025-01-10 18:25:28 +08:00
parent 59c8171ce8
commit eb45f0fd41
10 changed files with 139 additions and 90 deletions

View File

@ -18,7 +18,7 @@
<Routes @rendermode="InteractiveServer" />
<script type="text/javascript" src="@("https://unpkg.com/@antv/g2plot@2.4.17/dist/g2plot.min.js")"></script>
<script src="_content/AntDesign/js/ant-design-blazor.js"></script>
<script src="_content/AntDesign.Charts/ant-design-charts-blazor.js"></script>
@* <script src="_content/AntDesign.Charts/ant-design-charts-blazor.js"></script> *@
<script src="_framework/blazor.web.js"></script>
</body>

View File

@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Security.Policy;
namespace Learn.VideoAnalysis.Components.Pages.Dto
{
public class TaskShowRoute : PageModel
{
public int ID;
public void OnGet(int id)
{
ID = id;
}
}
}

View File

@ -1,80 +1,72 @@
@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>
@page "/VideoTaskShow/{taskId:long}"
<div id="video-container">
<video id="videoPlayer" controls></video>
@if (videoKnows != null)
{
<div id="segmentsContainer">
@for (int i = 0; i < videoKnows.Length; i++)
{
var item = videoKnows[i];
<button class="kBtn" onclick="spClick(@i,this)">@getF(item) @item.Theme </button>
}
</div>
}
<video id="videoPlayer" controls autoplay>
<source type="video/mp4" />
</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;
window.b = []
window.subtitles = []
var displayButton = []
var lastSegments = null;
function init() {
const videoPlayer = document.getElementById('videoPlayer');
const subtitleArea = document.getElementById('subtitleArea');
//视频时间变化时
videoPlayer.addEventListener('timeupdate', function () {
if (displayButton.length == 0) initKD()
const currentTime = videoPlayer.currentTime;
subtitleArea.textContent = '';
//字幕
window.subtitles.forEach(subtitle => {
let textContent = subtitle.text
if (currentTime >= subtitle.start
&& currentTime <= subtitle.end
&& subtitleArea.textContent != textContent) {
subtitleArea.textContent = textContent;
}
});
//时间片
let segment = displayButton.find(s => currentTime >= s.startTime
&& currentTime <= s.endTime)
if (segment) {
segment.button.style.backgroundColor = "rgb(238, 200, 118)";
if (lastSegments && lastSegments != segment) lastSegments.button.style.backgroundColor = "rgb(240, 249, 235)";
lastSegments = segment
}
});
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);
});
function initKD() {
let btns = document.getElementsByClassName("kBtn")
if(btns.length == 0) return
displayButton = window.b.map((s, i) => { return { ...s, button: btns[i] } })
}
//后端传递初始化数据
function setDB(a, b,c) {
console.log("setDB", a, b,c)
window.subtitles = a
window.b = b
const videoPlayer = document.getElementById('videoPlayer');
videoPlayer.src=c
init()
}
//点击时间片时
function spClick(i, button) {
videoPlayer.currentTime = displayButton[i].startTime;
}
</script>
@code {
}

View File

@ -5,6 +5,7 @@ using Learn.VideoAnalysis.Controllers.Dto;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.JSInterop;
using SqlSugar;
using System.Linq.Expressions;
using System.Threading.Tasks;
@ -14,15 +15,21 @@ using VideoAnalysisCore.Common;
using VideoAnalysisCore.Enum;
using VideoAnalysisCore.Model;
using VideoAnalysisCore.Model.Dto;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace Learn.VideoAnalysis.Components.Pages
{
public partial class VideoTaskShow : ComponentBase
{
/// <summary>
/// 任务id
/// </summary>
[Parameter]
public long? taskId { get; set; }
[Inject] private ConfirmService ComfirmService { get; set; } = default!;
[Inject] private IHttpContextAccessor HttpContext { get; set; } = default!;
[Inject] private Repository<VideoTask> taskDB { get; set; } = default!;
[Inject] private IJSRuntime JSRuntime { get; set; } = default!;
private VideoTask nowTask { get; set; } = default!;
private string videoPath { get; set; } = default!;
@ -42,24 +49,37 @@ namespace Learn.VideoAnalysis.Components.Pages
/// <returns></returns>
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
}
}
public string getF(VideoKnowRes segment)
{
var sf = (int)((segment.StartTime ?? 0) / 60);
var sm = (int)((segment.StartTime ?? 0) % 60);
var ef = (int)((segment.EndTime ?? 0) / 60);
var em = (int)((segment.EndTime ?? 0) % 60);
return $"{sf}:{sm} - {ef}: {em}";
}
/// <summary>
/// 初始化
/// </summary>
protected override async void OnInitialized()
{
var routeData = HttpContext.HttpContext.GetRouteData();
if (routeData is null)
if (this.taskId is null)
return;
long taskId = (long)routeData.Values["id"];
long taskId = this.taskId.Value;
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());
await JSRuntime.InvokeVoidAsync("setDB", captionsArr,videoKnows, videoPath);
StateHasChanged();
}
private async Task<bool> Comfirm(string message)

View File

@ -6,27 +6,37 @@
#video-container {
position: relative;
width: 1600px;
width: 1660px;
height: 850px;
float: left;
overflow-x: hidden;
}
video {
width: 100%;
height: 100%;
width: 94%;
height: 85%;
}
.subtitles {
position: absolute;
bottom: -40px;
bottom: 200px;
width: 100%;
text-align: center;
color: white;
background-color: rgba(0, 0, 0, 0.7);
font-size: 18px;
}
#segmentsContainer:is(:hover) {
width: 400px;
right: 0px;
}
#segmentsContainer {
transition:right 0.7s;
z-index:999;
overflow-x: hidden;
background-color: #e3e3e3c2;
position: absolute;
right: -180px;
display: flex;
flex-direction: column;
width: 265px;

View File

@ -101,6 +101,7 @@ namespace Learn.VideoAnalysis
// app.UseExceptionHandler("/Login");
//}
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions
{

View File

@ -46,10 +46,10 @@ namespace VideoAnalysisCore.AICore.GPT.ChatGPT
foreach (var next in timeBases)
{
// 如果类型相同,则扩展时间段
if (current. == next.)
if (current.Theme == next.Theme)
{
current. = Math.Max(current..Value, next..Value);
current. += next.;
current.EndTime = Math.Max(current.EndTime.Value, next.EndTime.Value);
current.Content += next.Content;
}
else
{

View File

@ -15,12 +15,24 @@ namespace VideoAnalysisCore.AICore.GPT.Dto
/// <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 float? StartTime { get; set; }
public float? EndTime { get; set; }
/// <summary>
/// 持续时间
/// </summary>
public float? KeepTime => (EndTime ?? 0) - StartTime ?? 0;
/// <summary>
/// 主题
/// </summary>
public string? Theme { get; set; }
/// <summary>
/// 章节
/// </summary>
public string? Section { get; set; }
/// <summary>
/// 内容总结
/// </summary>
public string? Content { get; set; }
}
public class FileNameInfo

View File

@ -79,8 +79,7 @@ namespace VideoAnalysisCore.Common
/// </summary>
/// <param name="tid"></param>
/// <returns></returns>
public static string GetVideoPath(string tid) =>
Path.Combine(TaskCachedFile, tid, tid + ".mp4");
public static string GetVideoPath(string tid) => $"./video/{tid}/{tid}.mp4";
}
/// <summary>

View File

@ -167,7 +167,7 @@ namespace VideoAnalysisCore.Common
var taskData = await DbScoped.SugarScope.Queryable<VideoTask>()
.FirstAsync(s => s.Id == tId);
taskData.ChatAnalysis = gptRes;
taskData.ChatAnalysisScore = gptRes.Assessment.Merit?.Sum(s => s.Score) ?? 0;
taskData.ChatAnalysisScore = gptRes?.Assessment?.Merit?.Sum(s => s.Score) ?? 0;
taskData.ErrorMessage = string.Empty;
taskData.LastEnum = RedisChannelEnum.EndTask;
await DbScoped.SugarScope.Updateable(taskData)