前言
最近需要做一个视频里面的字符实时叠加,记录一下探索的过程。
机器型号,海康威视的NVR和摄像头应该都没问题,因为是向NVR发包,跟摄像头没什么关系。
我的NVR型号是DS-7104N-SN/P
(NVR应该都行的。sdk邮箱给我的时候我也没发型号)
直接看解决的方法:HTTP的格式和C#代码—->直接跳转
探索前过程
还是说一下功能需求吧,需要在监控的屏幕上叠加环境监测仪的数据。接受数据啥的这里就不说了。
按照协议进行转化,这里只说进行字符叠加的东西,emm就这样…
底层|应用层?
在探索前期很自然的有两种选择的方式
- 第一种,在底层进行叠加。因为监控视频的设备已经做好了,能够在视频上实时显示时间,那么讲道理也是可以自定义显示字符的。
- 第二种,在应用层进行叠加。因为最后人看监控是在软件或者网页上进行查看。可以在应用层上进行叠加。
两种方法当然都可以,但是我想了下还是觉得在底层比较好,而且NVR会根据画面位置的亮暗来改变字的颜色(白色或黑色)
找了一下海康威视的sdk的咨询邮箱,然后问了下,他们还是给了比较好的回答,虽然没有demo,但是给出了基本的答案。
您好!
没有封装好的接口,可以直接使用ISAPI协议实现,附件8.4.21~8.4.25章节就是OSD字符叠加配置的协议内容。
该协议是基于标准HTTP协议和XML协议的,可以自己创建socket连接发送命令,也可以直接通过WEB控件开发包的I_SendHTTPRequest这个接口透传相关命令。
资料总结
上面给出了这个信息,我掐指一算大概能知道一点结果了。(__下面的东西别问我怎么知道的,我觉得常识__)
NVR就是一个正在运行的server,字符显示和一堆配置文件都在这个server的/ISAPI/System/Video/
下面。
我们的字符位置当然就是/ISAPI/System/Video/inputs/channels/ID/overlays/text
下面咯,但是要注意ID改成对应的摄像头ID,因为监控可以同时显示多个摄像头嘛。然后实现的方法就是使用HTTP协议发包更改配置文件就能更改显示了对吧。
Postman探索
如何进行HTTP的发包。直接通过socket模拟(底层确实是这么实现的),在群里问了一下,知道了有这么一个chrome插件–Postman
,确实很好用啊。下载啥的就不用说了吧。没错,就是下图这货
发包
接下来就是发包了,发送GET请求很舒服啊。找到了自己想要的答案。如下图,其实到这里理论上就已经完成了。(记得写Authorization,NVR的账户密码,坑了几个小时)
点send之后下面框就有内容了,然后使用PUT,发送我们想要的覆盖的内容也就行了,POST方法没有成功。
发完之后看看监控屏幕,就已经达到了想要的效果。如下图
然后经过个人尝试,录屏还是会保存到视频中,因为是从底层的修改。
HTTP格式和C#代码
那么通过Postman的尝试,知道了格式,那么就可以写代码了。(什么?别告诉我你还不知道格式!那么给你一个工具,用来监听socket内容的工具,自己看socket里面发的什么内容,链接跳转工具链接)
HTTP格式
下面给出HTTP的格式,Authorization当然需要时你自己的。
(注意PUT /ISAPI/System/Video/inputs/channels/ID/overlays/text中ID的替换
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| PUT /ISAPI/System/Video/inputs/channels/1/overlays/text HTTP/1.1 Host: 192.168.1.100 Connection: keep-alive Content-Length: 418 Authorization: Basic YWRtaW46Y3VnMTIzNDU= Cache-Control: no-cache Content-Type: text/plain;charset=UTF-8
<TextOverlayList> <TextOverlay> <id>1</id> <enabled>true</enabled> <positionX>200.000000</positionX> <positionY>480.000000</positionY> <displayText>xuan</displayText> </TextOverlay> </TextOverlayList>
|
C#代码
因为做的东西使用的是C#平台啦,仅给出一次发包的代码,多次发包写个循环。写好一个xml的模板,C:\\Test.xml
,路径下,文件内容如下
1 2 3 4 5 6 7 8 9
| <TextOverlayList> <TextOverlay> <id>1</id> <enabled>true</enabled> <positionX>50.000000</positionX> <positionY>100.000000</positionY> <displayText>温度</displayText> </TextOverlay> </TextOverlayList>
|
然后在C#中读取文件,进行显示文字的修改,然后发包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
string xmlPath = "C:\\Test.xml"; XmlDocument xml = new XmlDocument(); xml.Load(xmlPath);
XmlNode text = xml.SelectSingleNode("/TextOverlayList/TextOverlay/displayText"); text.InnerText = "温度"; xml.Save(xmlPath); Console.WriteLine(text.InnerText);
string URI = "http://192.168.1.100/ISAPI/System/Video/inputs/channels/1/overlays/text"; Stream outstream = null; Stream instream = null; StreamReader sr = null;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(URI);
Encoding encoding = Encoding.GetEncoding("UTF-8"); byte[] data = System.Text.Encoding.UTF8.GetBytes(xml.InnerXml); req.Method = "PUT"; req.ContentType = "text/plain;charset=UTF-8";
string username = "admin"; string password = "cug12345"; string userPasswd = username + ":" + password; CredentialCache mycache = new CredentialCache(); mycache.Add(new Uri(URI), "Basic", new NetworkCredential(username, password)); req.Credentials = mycache; req.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(new ASCIIEncoding().GetBytes(userPasswd)));
outstream = req.GetRequestStream(); outstream.Write(data, 0, data.Length); outstream.Flush(); outstream.Close();
HttpWebResponse res = (HttpWebResponse)req.GetResponse();
res = req.GetResponse() as HttpWebResponse;
instream = res.GetResponseStream(); sr = new StreamReader(instream, encoding);
string content = sr.ReadToEnd(); Console.Write(content); Console.Read();
|
运行结果如下:
然后在画面上面就可以看到温度两个字了,写代码的时候记得看IP和你的IP是否对应。
参考资料
工具
工具和文档
注:文档是海康威视sdk邮箱发给我的。