【发布时间】:2021-09-08 14:26:13
【问题描述】:
我从这里获取了一些代码,它们似乎可以通过基本上将 mjpg 依赖于另一个控制器来完成这项工作。 Frame-by-frame MJPEG streaming with C#/ASP.NET MVC
当时这似乎可行,但现在返回代码时却不行。
图像出现并且该部分有效,但它似乎基本上阻止了对 API 的任何其他请求(例如左、右)约 1-3 分钟。这是在 Chrome 和 Edge 中。
在开发人员工具箱中,请求会随着时间/大小不断增加。所以这就像 Chrome 正在等待什么或者我没有发送什么。
想法?
public class CameraController : ApiController
{
private MJPEGStream mjpegStream = new MJPEGStream();
private bool frameAvailable = false;
private Bitmap frame = null;
private string BOUNDARY = "frame";
private WebClient Client { get; set; }
private string URL { get; set; }
private string CameraNumber { get; set; }
/// <summary>
/// Initializer for the MJPEGstream
/// </summary>
CameraController()
{
Client = new WebClient { Credentials = new NetworkCredential(ConfigurationManager.AppSettings["WebCamUser"], ConfigurationManager.AppSettings["WebCamPassword"]) };
URL = ConfigurationManager.AppSettings["WebCamIP"].ToString();
CameraNumber = ConfigurationManager.AppSettings["WebCameraNumber"].ToString();
mjpegStream.Source = ConfigurationManager.AppSettings["WebCamIP"].ToString()+@"/mjpg/video.mjpg";
mjpegStream.ForceBasicAuthentication = true;
mjpegStream.Login = ConfigurationManager.AppSettings["WebCamUser"];
mjpegStream.Password = ConfigurationManager.AppSettings["WebCamPassword"];
mjpegStream.NewFrame += new NewFrameEventHandler(showFrameEvent);
}
[HttpGet]
public string Image()
{
var imageName = DateTime.Now.ToString("yyyyMMddHHmmssffff") + ".jpg";
//ok
//just have something here that deletes anything older than 2 mins
string[] files = Directory.GetFiles(System.Web.Hosting.HostingEnvironment.MapPath("~/Content/Temp/"));
foreach (string file in files)
{
FileInfo fi = new FileInfo(file);
if (fi.CreationTime < DateTime.Now.AddMinutes(-2))
{
fi.Delete();
}
}
var p = Path.Combine(System.Web.Hosting.HostingEnvironment.MapPath("~/Content/Temp/"), imageName);
Client.DownloadFile(URL + "/axis-cgi/jpg/image.cgi", p);
return imageName;
}
[HttpGet]
public bool Left()
{
var response = Client.DownloadString(URL + "/axis-cgi/com/ptz.cgi?camera=" + CameraNumber + "&move=left");
return true;
}
[HttpGet]
public bool Right()
{
var response = Client.DownloadString(URL + "/axis-cgi/com/ptz.cgi?camera=" + CameraNumber + "&move=right");
return true;
}
[HttpGet]
public bool Up()
{
var response = Client.DownloadString(URL + "/axis-cgi/com/ptz.cgi?camera=" + CameraNumber + "&move=up");
return true;
}
[HttpGet]
public bool Down()
{
var response = Client.DownloadString(URL + "/axis-cgi/com/ptz.cgi?camera=" + CameraNumber + "&move=down");
return true;
}
[HttpGet]
public bool ZoomIn()
{
var response = Client.DownloadString(URL + "/axis-cgi/com/ptz.cgi?camera=" + CameraNumber + "&rzoom=2500");
return true;
}
[HttpGet]
public bool ZoomOut()
{
var response = Client.DownloadString(URL + "/axis-cgi/com/ptz.cgi?camera=" + CameraNumber + "&rzoom=-2500");
return true;
}
[HttpGet]
public string GetImageVideoFallback()
{
var image = Client.DownloadData(URL + "/axis-cgi/jpg/image.cgi");
var base64 = Convert.ToBase64String(image);
var imgSrc = String.Format("data:image/jpg;base64,{0}", base64);
return imgSrc;
}
[HttpGet]
public HttpResponseMessage GetVideoContent()
{
mjpegStream.Start();
var response = Request.CreateResponse();
Func<Stream, HttpContent, TransportContext, Task> func = StartStream;
response.Content = new PushStreamContent(func);
response.Content.Headers.Remove("Content-Type");
response.Content.Headers.TryAddWithoutValidation("Content-Type", "multipart/x-mixed-replace;boundary=" + BOUNDARY);
return response;
}
/// <summary>
/// Craete an appropriate header.
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
private byte[] CreateHeader(int length)
{
string header =
"--" + BOUNDARY + "\r\n" +
"Content-Type:image/jpeg\r\n" +
"Content-Length:" + length + "\r\n\r\n";
return Encoding.UTF8.GetBytes(header);
}
public byte[] CreateFooter()
{
return Encoding.UTF8.GetBytes("\r\n");
}
/// <summary>
/// Write the given frame to the stream
/// </summary>
/// <param name="stream">Stream</param>
/// <param name="frame">Bitmap format frame</param>
private async Task WriteFrameAsync(Stream stream, Bitmap frame)
{
// prepare image data
byte[] imageData = null;
// this is to make sure memory stream is disposed after using
using (MemoryStream ms = new MemoryStream())
{
frame.Save(ms, ImageFormat.Jpeg);
imageData = ms.ToArray();
}
// prepare header
byte[] header = CreateHeader(imageData.Length);
// prepare footer
byte[] footer = CreateFooter();
// Start writing data
await stream.WriteAsync(header, 0, header.Length);
await stream.WriteAsync(imageData, 0, imageData.Length);
//await stream.WriteAsync(footer, 0, footer.Length);
await Task.Delay(1000 / 30);
await stream.FlushAsync();
}
/// <summary>
/// While the MJPEGStream is running and clients are connected,
/// continue sending frames.
/// </summary>
/// <param name="stream">Stream to write to.</param>
/// <param name="httpContent">The content information</param>
/// <param name="transportContext"></param>
private async Task StartStream(Stream stream, HttpContent httpContent, TransportContext transportContext)
{
while (mjpegStream.IsRunning && HttpContext.Current.Response.IsClientConnected)
{
if (frameAvailable)
{
try
{
frameAvailable = false;
await WriteFrameAsync(stream, frame);
await Task.Delay(1000 / 30);
}
catch (Exception) { }
}
else
{
Thread.Sleep(100);
}
}
stopStream();
stream.Flush();
stream.Close();
stream.Dispose();
}
/// <summary>
/// This event is thrown when a new frame is detected by the MJPEGStream
/// </summary>
/// <param name="sender">Object that is sending the event</param>
/// <param name="eventArgs">Data from the event, including the frame</param>
private void showFrameEvent(object sender, NewFrameEventArgs eventArgs)
{
frame = new Bitmap(eventArgs.Frame);
frameAvailable = true;
}
/// <summary>
/// Stop the stream.
/// </summary>
private void stopStream()
{
//System.Diagnostics.Debug.WriteLine("Stop stream");
mjpegStream.Stop();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
stopStream();
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
base.Dispose(disposing);
}
}
【问题讨论】:
标签: c# api google-chrome streaming