调试视频

pull/3/head
刘鑫 3 months ago
parent b5f2a84a65
commit 5fa957470b
  1. 5
      WeiCloud.Fusion/AspireApp/Manage.AppHost.AppHost/AppHost.cs
  2. 1
      WeiCloud.Fusion/AspireApp/Manage.AppHost.AppHost/Manage.AppHost.AppHost.csproj
  3. 139
      WeiCloud.Fusion/VideoService/Video.API/Controllers/DaHua/VideoManageController.cs
  4. 2
      WeiCloud.Fusion/VideoService/Video.API/Video.API.csproj
  5. 51
      WeiCloud.Fusion/VideoService/Video.Application/ApiResult.cs
  6. 0
      WeiCloud.Fusion/VideoService/Video.Application/IdentityClientConfig.cs
  7. 0
      WeiCloud.Fusion/VideoService/Video.Application/RequestDto/DahuaVideoQueryDto.cs
  8. 0
      WeiCloud.Fusion/VideoService/Video.Application/ResponeDto/DahuaVideoResDto.cs
  9. 0
      WeiCloud.Fusion/VideoService/Video.Application/Video.Application.csproj
  10. 4
      WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/DahuaGeneralCtlService.cs
  11. 58
      WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/IRootVideoPlaybackService.cs
  12. 199
      WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/RootVideoPlaybackService.cs
  13. 2
      WeiCloud.Fusion/VideoService/Video.DomainService/Video.DomainService.csproj
  14. 19
      WeiCloud.Fusion/WeiCloud.Fusion.sln

@ -3,10 +3,13 @@ var builder = DistributedApplication.CreateBuilder(args);
var apiService = builder.AddProject<Projects.Manage_AppHost_ApiService>("apiservice")
.WithHttpHealthCheck("/health");
var videoapi = builder.AddProject<Projects.Video_API>("videoapi");
builder.AddProject<Projects.Manage_AppHost_Web>("webfrontend")
.WithReference(videoapi)
.WithExternalHttpEndpoints()
.WithHttpHealthCheck("/health")
.WithReference(apiService)
.WaitFor(apiService);
builder.Build().Run();
builder.Build().Run();

@ -11,6 +11,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\VideoService\Video.API\Video.API.csproj" />
<ProjectReference Include="..\Manage.AppHost.ApiService\Manage.AppHost.ApiService.csproj" />
<ProjectReference Include="..\Manage.AppHost.Web\Manage.AppHost.Web.csproj" />
</ItemGroup>

@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using Video.Application;
using Video.DomainService;
namespace Video.API.Controllers.DaHua
{
@ -6,6 +8,139 @@ namespace Video.API.Controllers.DaHua
[ApiController]
public class VideoManageController : ControllerBase
{
private readonly ILogger<VideoManageController> _logger;
private readonly IRootVideoPlaybackService _rootVideoPlaybackService;
private readonly IConfiguration _configuration;
public VideoManageController(ILogger<VideoManageController> logger, IRootVideoPlaybackService rootVideoPlaybackService, IConfiguration configuration)
{
_logger = logger;
_rootVideoPlaybackService = rootVideoPlaybackService;
_configuration = configuration;
}
#region 大华视频处理
/// <summary>
/// 大华视频的登录获取Token
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost("token/dh")]
public async Task<ApiResult<string>> GetDaHToken(LoginRequestDto dto)
{
return await _rootVideoPlaybackService.GetDaHToken(dto);
}
/// <summary>
/// 大华视频回放
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost("playback/dh")]
public async Task<ApiResult<UrlDataDto>> StartAndPlaybackDH(PlaybackReqDto dto)
{
return await _rootVideoPlaybackService.GetDaHRecordVideoUrl(dto);
}
/// <summary>
/// 大华的录像回放地址(rtsp)
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost("rtspplayback/dh")]
public async Task<ApiResult<UrlDataDto>> RtspPlaybackByTime(PlaybackReqDto dto)
{
return await _rootVideoPlaybackService.RtspPlaybackByTime(dto);
}
/// <summary>
/// 大华视频的实时流地址
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost("realtime/dh")]
public async Task<ApiResult<UrlDataDto>> GetRealtimeUrl(StreamReqDto dto)
{
return await _rootVideoPlaybackService.GetRealtimeUrl(dto);
}
/// <summary>
/// 大华视频的实时流地址(rtsp方式)
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost("rtspstart/dh")]
public async Task<ApiResult<UrlDataDto>> RtspStartVideoUrl(StreamReqDto dto)
{
return await _rootVideoPlaybackService.RtspStartVideoUrl(dto);
}
/// <summary>
/// 大华设备通道
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost("channel/dh")]
public async Task<ApiResult<PageInfoDto>> GetChannelCodes(ChannelPageReqDto dto)
{
return await _rootVideoPlaybackService.GetChannelCodes(dto);
}
/// <summary>
/// 大华视频的下载
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpGet("download/dh")]
public async Task<IActionResult> DownloadVideoAsync(PlayDownloadReqDto dto)
{
var remoteUrl =
$"https://{_configuration["DahHost"]}/evo-apigw/evo-httpnode/vod/cam/download.mp4" +
$"?vcuid={dto.Vcuid}" +
$"&subtype=1" +
$"&starttime={dto.Starttime:yyyy_MM_dd_HH_mm_ss}" +
$"&endtime={dto.Endtime:yyyy_MM_dd_HH_mm_ss}" +
$"&videoType={dto.VideoType}" +
$"&token={dto.Token}" +
$"&recordType={dto.RecordType}";
try
{
var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (_, _, _, _) => true
};
using var http = new HttpClient(handler);
var resp = await http.GetAsync(remoteUrl, HttpCompletionOption.ResponseHeadersRead);
resp.EnsureSuccessStatusCode();
var stream = await resp.Content.ReadAsStreamAsync();
var contentType = "video/mp4";
return File(stream, contentType, "video.mp4");
}
catch (Exception ex)
{
return StatusCode(500, new { success = false, message = "下载失败", error = ex.Message });
}
}
/// <summary>
/// 大华登出
/// </summary>
/// <param name="authorization"></param>
/// <param name="openId"></param>
/// <param name="userClient"></param>
/// <returns></returns>
[HttpGet("logout/dh")]
public async Task<ApiResult<object>> Logout(string authorization, string? openId, int? userClient)
{
return await _rootVideoPlaybackService.Logout(authorization, openId, userClient);
}
#endregion 大华视频处理
}
}
}

@ -4,6 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
@ -22,6 +23,7 @@
<ItemGroup>
<ProjectReference Include="..\..\WeiCloud.Utils\WeiCloud.Utils.csproj" />
<ProjectReference Include="..\Video.Application\Video.Application.csproj" />
<ProjectReference Include="..\Video.DomainService\Video.DomainService.csproj" />
</ItemGroup>

@ -0,0 +1,51 @@
namespace Video.Application
{
public class ApiResult<T>
{
public int Code { get; set; }
public string Msg { get; set; }
public string InnerMsg { get; set; }
public T Data { get; set; }
public static ApiResult<T> IsSuccess(T data, string msg = "请求成功")
{
return new ApiResult<T>() { Code = 200, Data = data, Msg = msg };
}
/// <summary>
/// 服务端处理错误
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public static ApiResult<T> IsFail(string msg)
{
return new ApiResult<T> { Code = 2005, Msg = msg };
}
/// <summary>
/// 服务端处理错误
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public static ApiResult<T> IsNoFound(string msg = null)
{
return new ApiResult<T> { Code = 2005, Msg = msg ?? "数据不存在" };
}
/// <summary>
/// 客户端错误
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public static ApiResult<T> IsBadReq(string msg)
{
return new ApiResult<T> { Code = 2006, Msg = msg };
}
}
public class ApiHubResult<T> : ApiResult<T>
{
public long? Projectid { get; set; }
public long? Constid { get; set; }
}
}

@ -693,8 +693,8 @@ namespace Video.DomainService
private static String EncryptByPublicKey(String context, String publicKey)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
///rsa.FromXmlString(ConvertToXmlPublicJavaKey(publicKey));
RSACryptoServiceProvider rsa = new();
rsa.ImportParameters(FromXmlStringExtensions(ConvertToXmlPublicJavaKey(publicKey)));
byte[] byteText = System.Text.Encoding.UTF8.GetBytes(context);
byte[] byteEntry = rsa.Encrypt(byteText, false);

@ -0,0 +1,58 @@
using Video.Application;
namespace Video.DomainService
{
public interface IRootVideoPlaybackService
{
/// <summary>
/// 大华视频回放
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
Task<ApiResult<UrlDataDto>> GetDaHRecordVideoUrl(PlaybackReqDto dto);
/// <summary>
/// 大华的token获取
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
Task<ApiResult<string>> GetDaHToken(LoginRequestDto dto);
/// <summary>
/// 大华的实时视频
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
Task<ApiResult<UrlDataDto>> GetRealtimeUrl(StreamReqDto dto);
/// <summary>
/// rtsp实时预览接口方式
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
Task<ApiResult<UrlDataDto>> RtspStartVideoUrl(StreamReqDto dto);
/// <summary>
/// rtsp录像回放
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
Task<ApiResult<UrlDataDto>> RtspPlaybackByTime(PlaybackReqDto dto);
/// <summary>
/// 大华设备通道分页查询
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
Task<ApiResult<PageInfoDto>> GetChannelCodes(ChannelPageReqDto dto);
/// <summary>
/// 大华登出
/// </summary>
/// <param name="authorization"></param>
/// <param name="openId"></param>
/// <param name="userClient"></param>
/// <returns></returns>
Task<ApiResult<object>> Logout(string authorization, string? openId, int? userClient);
}
}

@ -0,0 +1,199 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Video.Application;
namespace Video.DomainService
{
public class RootVideoPlayBackService : IRootVideoPlaybackService
{
private readonly ILogger<RootVideoPlayBackService> _logger;
private readonly IConfiguration _cfg;
private readonly IDahuaGeneralCtlService _dahuaGeneralCtlService;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="logger"></param>
public RootVideoPlayBackService(ILogger<RootVideoPlayBackService> logger, IConfiguration configuration, IDahuaGeneralCtlService dahuaGeneralCtlService)
{
_logger = logger;
_cfg = configuration;
_dahuaGeneralCtlService = dahuaGeneralCtlService;
}
#region 大华视频处理
/// <summary>
/// 大华回放接口
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<ApiResult<UrlDataDto>> GetDaHRecordVideoUrl(PlaybackReqDto dto)
{
ApiResult<UrlDataDto> result = new ApiResult<UrlDataDto>() { Code = 200, Msg = "接口调用成功" };
var urlReult = await _dahuaGeneralCtlService.RecordVideoUrl(dto);
if (!urlReult.Success)
{
result.Code = 500;
result.Msg = urlReult.Msg;
_logger.LogWarning("大华录像回放接口调用失败:{Msg}", urlReult.Msg);
}
result.Data = urlReult.Data;
return result;
}
/// <summary>
/// 大华的鉴权
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<ApiResult<string>> GetDaHToken(LoginRequestDto dto)
{
ApiResult<string> result = new() { Code = 200, Msg = "接口调用成功" };
//1. 获取公钥
DaHApiResult<PublicKeyDto> publicKeyResult = await _dahuaGeneralCtlService.GetPublicKey();
if (!publicKeyResult.Success)
{
result.Code = 500;
result.Msg = publicKeyResult.Msg;
_logger.LogWarning("获取大华公钥失败:{Msg}", publicKeyResult.Msg);
}
//2. 鉴权
dto.PublicKey = publicKeyResult.Data.PublicKey;
DaHApiResult<LoginResDto> loginResult = await _dahuaGeneralCtlService.GetToken(dto);
if (!loginResult.Success)
{
result.Code = 500;
result.Msg = loginResult.Msg;
_logger.LogWarning("大华鉴权失败:{Msg}", loginResult.Msg);
return result;
}
//大华的规则
result.Data = loginResult.Data.AccessToken;
TokenEntry refreshed = new TokenEntry
{
AccessToken = result.Data,
RefreshToken = result.Data,
ExpireAt = DateTimeOffset.UtcNow.AddSeconds(120)
};
TokenCache.TokenMap[dto.ClientId] = refreshed;
return result;
}
/// <summary>
/// 大华实时
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<ApiResult<UrlDataDto>> GetRealtimeUrl(StreamReqDto dto)
{
ApiResult<UrlDataDto> result = new ApiResult<UrlDataDto>() { Code = 200, Msg = "接口调用成功" };
var urlReult = await _dahuaGeneralCtlService.RealtimeStreamUrl(dto);
if (!urlReult.Success)
{
result.Code = 500;
result.Msg = urlReult.Msg;
_logger.LogWarning("大华实时视频接口调用失败:{Msg}", urlReult.Msg);
}
result.Data = urlReult.Data;
return result;
}
/// <summary>
/// 大华设备通道分页查询
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<ApiResult<PageInfoDto>> GetChannelCodes(ChannelPageReqDto dto)
{
ApiResult<PageInfoDto> result = new ApiResult<PageInfoDto>() { Code = 200, Msg = "接口调用成功" };
var pageResult = await _dahuaGeneralCtlService.GetChannelPageList(dto);
if (!pageResult.Success)
{
result.Code = 500;
result.Msg = pageResult.Msg;
_logger.LogWarning("大华设备通道分页查询接口调用失败:{Msg}", pageResult.Msg);
}
result.Data = pageResult.Data;
return result;
}
/// <summary>
/// 大华登出
/// </summary>
/// <param name="authorization"></param>
/// <param name="openId"></param>
/// <param name="userClient"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<ApiResult<object>> Logout(string authorization, string? openId, int? userClient)
{
var result = new ApiResult<object>();
var logoutResult = await _dahuaGeneralCtlService.Logout(authorization, openId, userClient);
if (!logoutResult.Success)
{
result.Code = 500;
result.Msg = logoutResult.Msg;
_logger.LogWarning("大华登出接口调用失败:{Msg}", logoutResult.Msg);
}
else
{
result.Code = 200;
result.Msg = "登出成功";
}
return result;
}
/// <summary>
/// rtsp实时预览接口方式
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<ApiResult<UrlDataDto>> RtspStartVideoUrl(StreamReqDto dto)
{
ApiResult<UrlDataDto> result = new ApiResult<UrlDataDto>() { Code = 200, Msg = "接口调用成功" };
var urlReult = await _dahuaGeneralCtlService.RtspStartVideoUrl(dto);
if (!urlReult.Success)
{
result.Code = 500;
result.Msg = urlReult.Msg;
_logger.LogWarning("大华实时视频接口调用失败:{Msg}", urlReult.Msg);
}
result.Data = urlReult.Data;
return result;
}
/// <summary>
/// rtsp录像回放
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
public async Task<ApiResult<UrlDataDto>> RtspPlaybackByTime(PlaybackReqDto dto)
{
ApiResult<UrlDataDto> result = new ApiResult<UrlDataDto>() { Code = 200, Msg = "接口调用成功" };
var urlReult = await _dahuaGeneralCtlService.RtspPlaybackByTime(dto);
if (!urlReult.Success)
{
result.Code = 500;
result.Msg = urlReult.Msg;
_logger.LogWarning("大华录像回放接口调用失败:{Msg}", urlReult.Msg);
}
result.Data = urlReult.Data;
return result;
}
#endregion 大华视频处理
}
}

@ -7,8 +7,8 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Video.Application\Video.Application.csproj" />
<ProjectReference Include="..\..\WeiCloud.Utils\WeiCloud.Utils.csproj" />
<ProjectReference Include="..\Video.Application\Video.Application.csproj" />
</ItemGroup>
</Project>

@ -39,7 +39,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Video.Store", "VideoService
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParkingLotService.API", "ParkingLotService\ParkingLotService.API\ParkingLotService.API.csproj", "{D97C471C-3190-4F8E-A916-7A056A65EDCE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Video.Application", "Video.Application\Video.Application.csproj", "{77D967FB-79E5-42AB-A773-E129DBD16C97}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WeiCloud.Core", "WeiCloud.Core\WeiCloud.Core.csproj", "{40B0D902-553C-C52F-71A2-56FB176FCCBD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Video.Application", "VideoService\Video.Application\Video.Application.csproj", "{9F2BD2C5-6496-419D-B87A-4F481E963C4D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -95,10 +97,14 @@ Global
{D97C471C-3190-4F8E-A916-7A056A65EDCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D97C471C-3190-4F8E-A916-7A056A65EDCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D97C471C-3190-4F8E-A916-7A056A65EDCE}.Release|Any CPU.Build.0 = Release|Any CPU
{77D967FB-79E5-42AB-A773-E129DBD16C97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77D967FB-79E5-42AB-A773-E129DBD16C97}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77D967FB-79E5-42AB-A773-E129DBD16C97}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77D967FB-79E5-42AB-A773-E129DBD16C97}.Release|Any CPU.Build.0 = Release|Any CPU
{40B0D902-553C-C52F-71A2-56FB176FCCBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{40B0D902-553C-C52F-71A2-56FB176FCCBD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{40B0D902-553C-C52F-71A2-56FB176FCCBD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{40B0D902-553C-C52F-71A2-56FB176FCCBD}.Release|Any CPU.Build.0 = Release|Any CPU
{9F2BD2C5-6496-419D-B87A-4F481E963C4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9F2BD2C5-6496-419D-B87A-4F481E963C4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F2BD2C5-6496-419D-B87A-4F481E963C4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F2BD2C5-6496-419D-B87A-4F481E963C4D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -116,7 +122,8 @@ Global
{6CBD9E97-4FEF-4DA2-ADFB-21B4D9DB366F} = {19A25984-FFA8-49BE-A710-6F269A406C61}
{058C0CAB-5956-4811-8340-86919DDB2845} = {19A25984-FFA8-49BE-A710-6F269A406C61}
{D97C471C-3190-4F8E-A916-7A056A65EDCE} = {0A3134C8-219C-4674-B152-1FA6561E4217}
{77D967FB-79E5-42AB-A773-E129DBD16C97} = {19A25984-FFA8-49BE-A710-6F269A406C61}
{40B0D902-553C-C52F-71A2-56FB176FCCBD} = {44DAA396-C724-480A-A2BC-9A33D29E8FEA}
{9F2BD2C5-6496-419D-B87A-4F481E963C4D} = {19A25984-FFA8-49BE-A710-6F269A406C61}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {379A56DA-D3F0-4E7E-8FF7-DA8E20015BF3}

Loading…
Cancel
Save