using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
///
/// 视频流控制器,支持动态配置摄像头连接
///
[ApiController]
[Route("api/[controller]")]
public class VideoStreamController : ControllerBase
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private readonly server.Services.HttpVideoStreamService _videoStreamService;
///
/// 摄像头配置请求模型
///
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; }
}
///
/// 初始化HTTP视频流控制器
///
/// HTTP视频流服务
public VideoStreamController(server.Services.HttpVideoStreamService videoStreamService)
{
logger.Info("创建VideoStreamController,命名空间:{Namespace}", this.GetType().Namespace);
_videoStreamService = videoStreamService;
}
///
/// 获取 HTTP 视频流服务状态
///
/// 服务状态信息
[HttpGet("Status")]
[EnableCors("Users")]
[ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
public IResult GetStatus()
{
try
{
logger.Info("GetStatus方法被调用,控制器:{Controller},路径:api/VideoStream/Status", this.GetType().Name);
// 使用HttpVideoStreamService提供的状态信息
var status = _videoStreamService.GetServiceStatus();
// 转换为小写首字母的JSON属性(符合前端惯例)
return TypedResults.Ok(new
{
isRunning = true, // HTTP视频流服务作为后台服务始终运行
serverPort = _videoStreamService.ServerPort,
streamUrl = $"http://localhost:{_videoStreamService.ServerPort}/video-feed.html",
mjpegUrl = $"http://localhost:{_videoStreamService.ServerPort}/video-stream",
snapshotUrl = $"http://localhost:{_videoStreamService.ServerPort}/snapshot",
connectedClients = _videoStreamService.ConnectedClientsCount,
clientEndpoints = _videoStreamService.GetConnectedClientEndpoints(),
cameraStatus = _videoStreamService.GetCameraStatus()
});
}
catch (Exception ex)
{
logger.Error(ex, "获取 HTTP 视频流服务状态失败");
return TypedResults.InternalServerError(ex.Message);
}
}
///
/// 获取 HTTP 视频流信息
///
/// 流信息
[HttpGet("StreamInfo")]
[EnableCors("Users")]
[ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
public IResult GetStreamInfo()
{
try
{
logger.Info("获取 HTTP 视频流信息");
return TypedResults.Ok(new
{
frameRate = _videoStreamService.FrameRate,
frameWidth = _videoStreamService.FrameWidth,
frameHeight = _videoStreamService.FrameHeight,
format = "MJPEG",
htmlUrl = $"http://localhost:{_videoStreamService.ServerPort}/video-feed.html",
mjpegUrl = $"http://localhost:{_videoStreamService.ServerPort}/video-stream",
snapshotUrl = $"http://localhost:{_videoStreamService.ServerPort}/snapshot",
cameraAddress = _videoStreamService.CameraAddress,
cameraPort = _videoStreamService.CameraPort
});
}
catch (Exception ex)
{
logger.Error(ex, "获取 HTTP 视频流信息失败");
return TypedResults.InternalServerError(ex.Message);
}
}
///
/// 配置摄像头连接参数
///
/// 摄像头配置
/// 配置结果
[HttpPost("ConfigureCamera")]
[EnableCors("Users")]
[ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
public async Task 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);
}
}
///
/// 获取当前摄像头配置
///
/// 摄像头配置信息
[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);
}
}
///
/// 测试摄像头连接
///
/// 连接测试结果
[HttpPost("TestCameraConnection")]
[EnableCors("Users")]
[ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
public async Task 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);
}
}
///
/// 测试 HTTP 视频流连接
///
/// 连接测试结果
[HttpPost("TestConnection")]
[EnableCors("Users")]
[ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
public async Task TestConnection()
{
try
{
logger.Info("测试 HTTP 视频流连接");
// 尝试通过HTTP请求检查视频流服务是否可访问
using (var httpClient = new HttpClient())
{
httpClient.Timeout = TimeSpan.FromSeconds(2); // 设置较短的超时时间
var response = await httpClient.GetAsync($"http://localhost:{_videoStreamService.ServerPort}/");
// 只要能连接上就认为成功,不管返回状态
bool isConnected = response.IsSuccessStatusCode;
return TypedResults.Ok(isConnected);
}
}
catch (Exception ex)
{
logger.Error(ex, "HTTP 视频流连接测试失败");
// 连接失败但不抛出异常,而是返回连接失败的结果
return TypedResults.Ok(false);
}
}
}