下载完成事件:触发后入库并启动 Jellyfin 轮询匹配

This commit is contained in:
2025-10-10 22:27:36 +08:00
parent 9036f967fc
commit bc39e38ac4
4 changed files with 328 additions and 17 deletions

View File

@@ -5,6 +5,10 @@ using FATrace.Model;
using LibVLCSharp.Shared;
using ReaLTaiizor.Forms;
using System.ComponentModel;
using FATrace.OEMApp.Services;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
namespace FATrace.OEMApp
{
@@ -88,6 +92,12 @@ namespace FATrace.OEMApp
/// </summary>
public string CurrentVideoPath { get; set; }
/// <summary>
/// 按文件名/路径去重,避免同一下载完成事件被重复处理
/// key: 文件名或路径(小写) value: 对应插入的 OEMRawUse.Id0 表示尚未完成插入)
/// </summary>
private readonly ConcurrentDictionary<string, long> _downloadProcessingKeys = new();
#endregion
@@ -132,6 +142,8 @@ namespace FATrace.OEMApp
{
HkCameraClient.NVRLoadVideoProcessEventHandler -= HkCameraClient_NVRLoadVideoProcessEventHandler;
HkCameraClient.NVRLoadVideoProcessEventHandler += HkCameraClient_NVRLoadVideoProcessEventHandler;
HkCameraClient.NVRLoadVideoCompleteEventHandler -= HkCameraClient_NVRLoadVideoCompleteEventHandler;
HkCameraClient.NVRLoadVideoCompleteEventHandler += HkCameraClient_NVRLoadVideoCompleteEventHandler;
// 进度轮询已在库方法内部自动启动,这里无需再次调用
HkCameraClient.StartDownloadProgressMonitor();
}
@@ -444,23 +456,73 @@ namespace FATrace.OEMApp
}
/// <summary>
/// Handles the event triggered when the NVR (Network Video Recorder) completes loading a video.
/// Video下载完成
/// 下载完成事件:触发后入库并启动 Jellyfin 轮询匹配
/// </summary>
/// <param name="sender">The source of the event. This can be <see langword="null"/> if the event is not raised by a specific object.</param>
/// <param name="e">A string containing information about the completed video load operation.</param>
/// <param name="sender"></param>
/// <param name="e"></param>
private void HkCameraClient_NVRLoadVideoCompleteEventHandler(object? sender, string e)
{
//先保存当前的信息
var returnValues = FSqlContext.FDb.Insert<OEMRawUse>(new OEMRawUse()
{
InBagCode=CurInBagCode,
RawName=CurInBagRawName,
User= CurUserName,
UrlState=false,
VideoUrl="",//暂时无法获取URL因为服务器还没有扫描到文件信息
}).ExecuteInserted();
// 计算用于去重的 key文件路径或文件名小写
var localNameOrPath = (!string.IsNullOrWhiteSpace(e) && (e.Contains("\\") || e.Contains("/") || e.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase)))
? e
: this.CurrentVideoPath;
var key = (System.IO.Path.GetFileName(localNameOrPath) ?? localNameOrPath).ToLowerInvariant();
// 若同一 key 已在处理中,则忽略本次回调
if (!_downloadProcessingKeys.TryAdd(key, 0))
{
System.Diagnostics.Debug.WriteLine($"[NVRLoadVideoComplete] 正在处理相同文件,忽略: {key}");
return;
}
// 先保存当前的信息,记录主键 Id
var rawUse = new OEMRawUse()
{
InBagCode = CurInBagCode,
RawName = CurInBagRawName,
User = CurUserName,
UrlState = false,
VideoUrl = string.Empty
};
long rawUseId = 0;
try
{
rawUseId = FSqlContext.FDb.Insert<OEMRawUse>(rawUse).ExecuteIdentity();
_downloadProcessingKeys[key] = rawUseId;
}
catch (Exception ex)
{
_downloadProcessingKeys.TryRemove(key, out _);
System.Diagnostics.Debug.WriteLine($"[NVRLoadVideoComplete] 插入 OEMRawUse 失败: {ex.Message}");
return;
}
// 后台执行,避免阻塞 UI 线程
Task.Run(async () =>
{
try
{
var monitor = new JellyfinMonitorService();
await monitor.MonitorAndUpdateAfterDownloadAsync(
oemRawUseId: rawUseId,
videoLocalPathOrName: localNameOrPath,
code: CurInBagCode,
rawName: CurInBagRawName,
userName: CurUserName,
cancellationToken: CancellationToken.None
).ConfigureAwait(false);
}
catch (Exception ex1)
{
System.Diagnostics.Debug.WriteLine($"[JellyfinMonitor] 异常: {ex1.Message}");
}
finally
{
// 移除去重 key允许后续相同文件再次处理如需重试
_downloadProcessingKeys.TryRemove(key, out _);
}
});
}
}
}