目录
背景
项目中需要在浏览器中播放RTSP流,实在是不想折腾ActiveX控件
1、麻烦(开发麻烦、使用时设置也麻烦)
2、非IE浏览器不兼容
解决方案
使用OpenCvSharp+Nancy写一个解码服务,提供http接口,返回解码后Mat对象的Base64字符串,前端页面循环调用并展示。
效果
浏览器播放RTSP流
代码
前端代码
<span class="label label-primary">rtsp播放测试
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8" />
- <title>rtsp播放测试</title>
- <link rel="stylesheet" href="bootstrap.min.css" />
- <script src="jquery-1.8.0.js" type="text/javascript"></script>
- </head>
- <body>
- <div class="container">
- <br />
- <div class="row">
- <div class="panel panel-primary">
- <div class="panel-heading">
- <span class="label label-primary">rtsp播放测试</span>
- <br />
- </div>
- <div class="panel-body">
- <input type="text" value="" id="txtRTSPURL" style="width: 500px;" /><br />
- <br />
- <input type="button" value="打开" id="btnOpen" />
- <input type="button" value="播放" id="btnPlay" />
- <input type="button" value="停止" id="btnStop" />
- <input type="button" value="测试获取一帧" id="btnTest" />
- </br> </br>
- <img id="imgId" src="" style="width: 1024px" />
- </div>
- </div>
- </div>
- </div>
- </body>
- <script type="text/jscript">
-
-
- $(function () {
-
- $("#btnOpen").click(function () {
- var rtsp_url = $("#txtRTSPURL").val();
- $.ajax({
- type: "post",
- url: base_url + "/open",
- dataType: 'json',
- data: { "rtsp_url": rtsp_url },
- success: function (d) {
- if (d.code == 1) {
- alert("打开成功")
- } else {
- alert("打开失败:" + d.message)
- }
- }
- })
-
- })
-
-
- $("#btnTest").click(function () {
-
- $.ajax({
- type: "post",
- url: base_url + "/getframe",
- dataType: 'json',
- data: "",
- success: function (d) {
- if (d.code == 1) {
- console.log(d.data);
- $("#imgId").attr("src", "data:image/jpg;base64," + d.data);
-
- } else {
- alert("播放失败:" + d.message)
- }
- }
- })
-
- })
-
- $("#btnPlay").click(function () {
-
- try {
- flag = true;
- showImage();
- } catch (e) {
- }
-
- })
-
- $("#btnStop").click(function () {
- flag = false;
- $.ajax({
- type: "post",
- url: base_url + "/close",
- dataType: 'json',
- data: "",
- success: function (d) {
- if (d.code == 1) {
-
- } else {
- alert("关闭失败:" + d.message)
- }
- }
- })
- })
-
- })
-
- var base_url = "http://127.0.0.1:8082";
- var flag = false;
-
- function showImage() {
- $.ajax({
- type: "post",
- url: base_url + "/getframe",
- dataType: 'json',
- data: "",
- success: function (d) {
- if (d.code == 1) {
- $("#imgId").attr("src", "data:image/jpg;base64," + d.data);
- if (flag) {
- showImage();
- }
- } else {
- alert("播放失败:" + d.message)
- }
- }
- })
-
- }
-
- </script>
- </html>
后端代码
- using Nancy;
- using Newtonsoft.Json;
- using NLog;
- using OpenCvSharp;
- using OpenVINO.OCRService.Common;
- using System;
- using System.Threading;
- using System.Threading.Tasks;
-
- namespace CaptureService
- {
- public class CaptureModule : NancyModule
- {
-
- private Logger _log = NLog.LogManager.GetCurrentClassLogger();
-
- public static readonly object _locker = new object();
-
- public CaptureModule()
- {
- //跨域处理
- After.AddItemToEndOfPipeline((ctx) => ctx.Response
- .WithHeader("Access-Control-Allow-Origin", "*")
- .WithHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS")
- .WithHeader("Access-Control-Allow-Headers", "Accept, Origin, Content-type"));
-
- Get("/", p =>
- {
- return "Hello MediaCaptureService";
- });
-
- Post("/open", p =>
- {
- AjaxReturn ar = new AjaxReturn();
-
- if (Program.open)
- {
- ar.code = 0;
- ar.message = "已开启,如需重新开启,请先关闭!";
- _log.Info(JsonConvert.SerializeObject(ar));
- return Response.AsJson<AjaxReturn>(ar);
- }
-
- string rtsp_url = Request.Form["rtsp_url"];
- if (string.IsNullOrEmpty(rtsp_url))
- {
- ar.code = 0;
- ar.message = "参数[rtsp_url]不能为空";
- _log.Info(JsonConvert.SerializeObject(ar));
- return Response.AsJson<AjaxReturn>(ar);
- }
-
- Program.rtsp_url = rtsp_url;
- Program.ctsCapture = new CancellationTokenSource();
- Program.open = true;
-
- try
- {
- Task.Factory.StartNew(() =>
- {
- Program.capture = new VideoCapture(Program.rtsp_url);
- if (Program.capture.IsOpened())
- {
- int index = 0;
- Mat frame = new Mat();
- while (true)
- {
- if (Program.ctsCapture.IsCancellationRequested) break;
- Program.capture.Read(frame);
- if (Program.matQueue.Count >= 5)
- {
- continue;
- }
- Program.matQueue.Enqueue(frame);
- //_log.Info(Program.matQueue.Count);
- //Cv2.ImWrite(index + ".jpg", frame);
- //index++;
- }
- if (Program.capture != null)
- {
- Program.capture.Release();
- }
- }
- });
-
- ar.code = 1;
- ar.message = "success";
- }
- catch (Exception ex)
- {
- ar.code = 0;
- ar.message = ex.Message;
- _log.Error(ex, "开启异常");
- }
- return Response.AsJson<AjaxReturn>(ar);
- });
-
- Post("/close", p =>
- {
- AjaxReturn ar = new AjaxReturn();
- try
- {
- Program.open = false;
- if (Program.ctsCapture != null)
- {
- Program.ctsCapture.Cancel();
- }
- ar.code = 1;
- ar.message = "success";
- }
- catch (Exception ex)
- {
- ar.code = 0;
- ar.message = ex.Message;
- _log.Error(ex, "关闭异常");
- }
- return Response.AsJson<AjaxReturn>(ar);
- });
-
- Post("/getframe", p =>
- {
- AjaxReturn ar = new AjaxReturn();
-
-
- if (!Program.open)
- {
- ar.code = 0;
- ar.message = "网络流未打开,请先打开!";
- _log.Info(JsonConvert.SerializeObject(ar));
- return Response.AsJson<AjaxReturn>(ar);
- }
-
- if (Program.matQueue.Count == 0)
- {
- ar.code = 1;
- ar.message = "图像队列为空";
- _log.Info(JsonConvert.SerializeObject(ar));
- return Response.AsJson<AjaxReturn>(ar);
- }
-
- try
- {
-
- Mat frame = new Mat();
- if (!Program.matQueue.TryDequeue(out frame))
- {
- ar.code = 0;
- ar.message = "获取图像失败";
- _log.Info(JsonConvert.SerializeObject(ar));
- return Response.AsJson<AjaxReturn>(ar);
- }
-
- ar.code = 1;
- ar.message = "success";
-
- var bytes = frame.ToBytes();
- ar.data = Convert.ToBase64String(bytes);
-
- }
- catch (Exception ex)
- {
- ar.code = 0;
- ar.message = ex.Message;
- _log.Error(ex, "获取摄像头画面异常");
- }
- return Response.AsJson<AjaxReturn>(ar);
- });
-
- }
-
- }
-
- }
下载
天天代码码天天
微信公众号
.NET 人工智能实践


评论记录:
回复评论: