feat: 支持实际摄像头视频流

This commit is contained in:
2025-07-03 17:51:12 +08:00
parent 178ac0de67
commit e84a784517
4 changed files with 1323 additions and 438 deletions

View File

@@ -1,8 +1,9 @@
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
/// <summary>
/// [TODO:description]
/// 视频流控制器,支持动态配置摄像头连接
/// </summary>
[ApiController]
[Route("api/[controller]")]
@@ -11,6 +12,20 @@ public class VideoStreamController : ControllerBase
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly server.Services.HttpVideoStreamService _videoStreamService;
/// <summary>
/// 摄像头配置请求模型
/// </summary>
public class CameraConfigRequest
{
[Required]
[RegularExpression(@"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", ErrorMessage = "IP地址")]
public string Address { get; set; } = "";
[Required]
[Range(1, 65535, ErrorMessage = "端口必须在1-65535范围内")]
public int Port { get; set; }
}
/// <summary>
/// 初始化HTTP视频流控制器
/// </summary>
@@ -47,12 +62,14 @@ public class VideoStreamController : ControllerBase
mjpegUrl = $"http://localhost:{_videoStreamService.ServerPort}/video-stream",
snapshotUrl = $"http://localhost:{_videoStreamService.ServerPort}/snapshot",
connectedClients = _videoStreamService.ConnectedClientsCount,
clientEndpoints = _videoStreamService.GetConnectedClientEndpoints()
clientEndpoints = _videoStreamService.GetConnectedClientEndpoints(),
cameraStatus = _videoStreamService.GetCameraStatus()
});
}
catch (Exception ex)
{
logger.Error(ex, "获取 HTTP 视频流服务状态失败"); return TypedResults.InternalServerError(ex.Message);
logger.Error(ex, "获取 HTTP 视频流服务状态失败");
return TypedResults.InternalServerError(ex.Message);
}
}
@@ -77,12 +94,123 @@ public class VideoStreamController : ControllerBase
format = "MJPEG",
htmlUrl = $"http://localhost:{_videoStreamService.ServerPort}/video-feed.html",
mjpegUrl = $"http://localhost:{_videoStreamService.ServerPort}/video-stream",
snapshotUrl = $"http://localhost:{_videoStreamService.ServerPort}/snapshot"
snapshotUrl = $"http://localhost:{_videoStreamService.ServerPort}/snapshot",
cameraAddress = _videoStreamService.CameraAddress,
cameraPort = _videoStreamService.CameraPort
});
}
catch (Exception ex)
{
logger.Error(ex, "获取 HTTP 视频流信息失败"); return TypedResults.InternalServerError(ex.Message);
logger.Error(ex, "获取 HTTP 视频流信息失败");
return TypedResults.InternalServerError(ex.Message);
}
}
/// <summary>
/// 配置摄像头连接参数
/// </summary>
/// <param name="config">摄像头配置</param>
/// <returns>配置结果</returns>
[HttpPost("ConfigureCamera")]
[EnableCors("Users")]
[ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
public async Task<IResult> ConfigureCamera([FromBody] CameraConfigRequest config)
{
try
{
logger.Info("配置摄像头连接: {Address}:{Port}", config.Address, config.Port);
var success = await _videoStreamService.ConfigureCameraAsync(config.Address, config.Port);
if (success)
{
return TypedResults.Ok(new
{
success = true,
message = "摄像头配置成功",
cameraAddress = config.Address,
cameraPort = config.Port
});
}
else
{
return TypedResults.BadRequest(new
{
success = false,
message = "摄像头配置失败",
cameraAddress = config.Address,
cameraPort = config.Port
});
}
}
catch (Exception ex)
{
logger.Error(ex, "配置摄像头连接失败");
return TypedResults.InternalServerError(ex.Message);
}
}
/// <summary>
/// 获取当前摄像头配置
/// </summary>
/// <returns>摄像头配置信息</returns>
[HttpGet("CameraConfig")]
[EnableCors("Users")]
[ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
public IResult GetCameraConfig()
{
try
{
logger.Info("获取摄像头配置");
var cameraStatus = _videoStreamService.GetCameraStatus();
return TypedResults.Ok(new
{
address = _videoStreamService.CameraAddress,
port = _videoStreamService.CameraPort,
isConfigured = cameraStatus.GetType().GetProperty("IsConfigured")?.GetValue(cameraStatus),
connectionString = $"{_videoStreamService.CameraAddress}:{_videoStreamService.CameraPort}"
});
}
catch (Exception ex)
{
logger.Error(ex, "获取摄像头配置失败");
return TypedResults.InternalServerError(ex.Message);
}
}
/// <summary>
/// 测试摄像头连接
/// </summary>
/// <returns>连接测试结果</returns>
[HttpPost("TestCameraConnection")]
[EnableCors("Users")]
[ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
public async Task<IResult> TestCameraConnection()
{
try
{
logger.Info("测试摄像头连接");
var (isSuccess, message) = await _videoStreamService.TestCameraConnectionAsync();
return TypedResults.Ok(new
{
success = isSuccess,
message = message,
cameraAddress = _videoStreamService.CameraAddress,
cameraPort = _videoStreamService.CameraPort,
timestamp = DateTime.Now
});
}
catch (Exception ex)
{
logger.Error(ex, "测试摄像头连接失败");
return TypedResults.InternalServerError(ex.Message);
}
}