ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

网页播放监控视频:WEB播放器插件接入与排错指南

网页播放监控视频:WEB播放器插件接入与排错指南 刚过去的这个季度我连续被好几个项目问了差不多的事网页上要播放摄像头监控视频用哪个WEB播放器插件客户装的是某安防厂商的设备给了一堆接口文档前端同事看着ActiveX、NPAPI、WebVideoCtrl一脸懵。这篇文章就把这套方案里从插件原理、环境准备到代码接入和排错的全过程整理出来希望对接了监控需求的前端同学有点用。先说明一下下文统一用“该厂商”代指做监控设备的那家头部企业不点名字。实际项目里它的设备市场占有率很高WEB播放器插件也是用得最多的方案之一。我会尽量把底层逻辑讲透再给出能直接跑的代码和排查路径而不是只贴一段官方Demo让你照抄。1. 为什么页面放监控视频不能像放MP4那样简单1.1 监控摄像头输出的不是浏览器认识的视频流很多前端同学第一次接到摄像头预览需求时第一反应是给我一个RTSP地址我用video标签直接播放。这个想法很正常但现实很残酷。视频标签支持的是HTTP协议的渐进式视频文件以及HLS、DASH这类流媒体协议而绝大多数IPC网络摄像头和NVR网络录像机输出的主码流和子码流都是RTSP协议走的是RTSP/RTP序列默认端口是554。浏览器厂商根本没有内置RTSP解码和传输能力你拿video去塞一个rtsp://192.168.1.64:554/Streaming/Channels/101浏览器只会甩给你一个“不支持的源”或者无限转圈。这里面的原因是立体且复杂的RTSP涉及SDP会话协商、RTP分包、音视频同步还要考虑TCP/UDP传输方式这些都不是Web标准协议栈的一部分。只要浏览器不支持前端写再多JavaScript也没用。有人会问那为什么YouTube、B站这些网站能直接在网页上播直播因为它们后端已经把流转换成HLS或者DASH了服务器编码和切片之后再抛给浏览器。这个转码过程是需要算力和延迟代价的。如果是监控场景延迟超过一两秒云台操作和告警联动体验就会非常奇怪。1.2 插件方案是被“逼”出来的既然浏览器原生不支持RTSP那需要实现在网页里看摄像头的早期项目就只能靠插件。这个“插”字很形象浏览器没有的能力通过在本地安装一个组件来补充。这个组件能解RTSP协议、能调用系统的解码器、能直接操作显卡和窗口绘制画面而页面里的JavaScript只负责告诉它“你要播哪路流”“窗口在哪”画面渲染实际发生在插件的窗口区域里。该厂商的WEB播放器插件就是这么来的。它并不是这几年才出的新东西而是从IE时代一路演化过来的老将经历了ActiveX、OCX、NPAPI、Chrome扩展、本地服务等好几个阶段。到今天它仍然是Windows环境下最稳妥、延迟最低的监控预览方案之一前提是你能接受必须装插件这件事。这样做的好处非常明显延迟低通常能控制在几百毫秒功能全云台控制、对讲、抓图、录像、报警等都能用兼容性好对旧设备和旧系统支持完善。坏处也很突出只支持Windows和特定浏览器移动端全部绝缘新版本的Chrome和Edge对旧插件方式越来越不友好信创和国产化环境几乎用不了。如果你接触过类似项目应该能理解我这句话插件方案是权衡后的选择不是最优解但往往是当前客户系统里唯一“能用”的方案。2. WEB播放器插件的本质与版本差异2.1 插件到底是什么ActiveX、NPAPI、本地服务要正确使用这套东西先别把它当黑盒。该厂商的WEB播放器插件在不同阶段有完全不同的形态理解这一点能省掉一大半排错时间。最早是ActiveX控件典型文件是一个.ocx或.dll注册到Windows系统里通过IE的ActiveX机制在页面上渲染一个object标签区域。这个控件本质上是一个可以嵌入到网页的COM组件浏览器直接调用它播放视频画面甚至能嵌进页面布局。ActiveX的问题大家都知道IE独有、权限巨大、安全性差。但直到现在很多部队、园区、能源行业的安防系统仍然跑在IE兼容模式下这一批存量项目基本都靠ActiveX撑着。后来Chrome快速崛起自己带头淘汰了NPAPI插件ActiveX在Chrome里彻底没法用了。为了解决这个问题该厂商推出了基于Chrome的插件变种有的是通过本地安装一个独立服务浏览器页面通过WebSocket或者本地HTTP接口和这个服务通信服务负责拉流和解码然后用某种方式把视频数据推回页面有的则做成了Chrome扩展配合原生消息传递来工作。这两种形态页面上可能不再看到一个“控件”区域而是通过canvas或者video标签接收实时帧。所以你翻项目旧代码时会看到两种完全不同的调用方式一种是老式WebVideoCtrl通过object嵌入用classid指定控件另一种是后来基于WebSocket的JSSDK安装插件服务后页面通过地址和端口去连接本地服务。如果不先搞清楚项目里用的是哪一版拿新版SDK去对接老设备或者反过来都会遇到“插件已安装但页面不识别”的尴尬问题。2.2 不同浏览器下插件形态和API差异在真实项目里同一个网页可能要在IE、Chrome、EdgeChromium内核、360安全浏览器这些不同浏览器里跑。不同浏览器的插件形态不同前端代码也得跟着适配。先说IE要使用ActiveX控件页面里必须写一个object idwebVideoCtrl classidclsid:xxxx width... height.../object。然后JavaScript通过document.getElementById(webVideoCtrl)拿到控件对象再调用它的方法。这个方法也叫WebVideoCtrl但它是COM对象的方法不是纯JS对象。需要注意IE的位数必须和ActiveX控件位数一致32位插件就要求用32位IE64位IE往往找不到控件。这一条在我实际项目里坑过很多人。再说Chrome如果是新版插件页面里一般不用写object而是引入一个官方JS文件里面封装了WebVideoCtrl对象。这个对象内置了和本地服务的通信逻辑比如通过HTTP或WebSocket连接本地的某个端口。安装插件服务后本地服务会在127.0.0.1上监听一个端口JS调用它的时候底层会去连接这个端口。如果端口被占用、服务没启动、或者浏览器安全策略禁止了连接本地地址页面就会出现“插件初始化失败”。Edge和Chrome类似但要注意如果Edge版本过新可能对某些老的扩展机制有更严格限制。360之类双核浏览器极速模式基本和Chrome一致兼容模式可能走IE的逻辑。推荐做法是在项目里单独维护一个“浏览器环境检测”函数提前判断当前是IE还是Chrome然后加载对应的JS和初始化逻辑。2.3 选型决策什么时候坚持用插件我在做方案选型时会问三个问题第一客户端是不是全部Windows第二有没有必须用的浏览器版本要求第三移动端要不要看视频如果前两条满足、暂时不管移动端那用插件方案是性价比最高的。如果有一条不满足就要尽早考虑H5转码方案。插件方案还有一个隐形成本安装和升级。就算你已经接好了页面客户换了一台新电脑首先要装插件设置浏览器白名单否则页面还是白的。很多商务人员给客户演示往往就卡在这一步。所以在交付时最好做一个环境检测页面自动提示“插件未安装”“当前浏览器不被支持”“请以管理员身份安装”能极大减少电话支持。3. 接入前的环境准备少一步后面全是坑3.1 安装插件前的浏览器与系统检查接入之前先花20分钟把环境摸一遍。检查系统是Windows几检查浏览器类型和版本号检查浏览器是32位还是64位。特别是Windows Server系统IE增强安全配置默认开启极其容易拦截插件必须先关闭或者把站点加入受信任区域。插件的安装包一般放在设备附带的光盘里或者从官网的下载中心按型号和SDK版本去下载。建议自己先下载一个测试环境装好之后打开IE进入一个官方Demo页面确认能正常出画面再拿这套环境去开发。不要跳过这一步因为很多“开发半天发现插件没生效”的坑其实都是环境没搭好。安装时如果杀毒软件弹出警告不要盲目点拦截。ActiveX控件和本地服务很容易被误报为风险程序。可以把安装目录加入白名单或者暂时关闭实时防护后再装。装完之后确认两个东西系统服务列表里有没有对应的服务进程在运行浏览器扩展管理里有没有对应的插件扩展被启用。3.2 浏览器安全设置与本地控件权限如果你还在用IE这一步是必须的。打开IE的“Internet选项”在“安全”选项卡里把站点加到“受信任的站点”域名最好用IP。然后把该区域的安全级别调到“低”或者自定义级别里把“ActiveX控件和插件”相关的几个选项全部改成“启用”或“提示”。还要勾选“允许运行或安装软件即使签名无效”否则控件签名不在信任列表时会被拦下来。如果用的是Chrome和Edge的新版插件方式一般不涉及ActiveX但需要确认浏览器没有禁止“允许运行不安全的内容”。因为插件服务通常监听在127.0.0.1而你的页面可能是http://192.168.1.100:8080混合内容策略可能会阻止浏览器访问本地HTTP服务。解决办法是将站点设置为安全来源或者用HTTPS部署页面又或者在Chrome标记里临时允许不安全内容。这些细节在官方文档里很少一次性写清楚实际接入时极常见。3.3 引入官方JS封装理解初始化参数环境准备好之后在页面里引入官方提供的JS文件。老版本通常是webVideoCtrl.js新版本可能是一整个jessibuca风格的对象。我下面以最主流的WebVideoCtrl命名来写。引入方式很简单script src/path/to/webVideoCtrl.js/script然后页面上放一个用于承载视频的容器div idplayWindow/div这个容器不必是video标签插件初始化时会自动在里面创建视频窗口或插件对象。你要做的是记录这个容器的ID后面初始化时传入。理解初始化参数比敲代码更重要。初始化通常需要几类参数窗口尺寸、是否启用窗口拖拽、是否使用硬件加速、插件类型ActiveX还是本地服务。这些参数在不同版本中叫法不同但是大逻辑一致。示例var WebVideoCtrl; function initPlugin() { WebVideoCtrl new WebVideoCtrl(); WebVideoCtrl.I(playWindow, { bWndFull: true, iWndWidth: 640, iWndHeight: 480, oPlugin: { iType: 2, // 2表示视频插件 bNoPlugin: false // 是否禁用插件 } }); }需要用I()方法去初始化容器这个命名很简略但它是官方API不是我们自己封装的名字。初始化成功后可以调用CheckPluginVersion()之类的接口获取插件版本号用于判断是否安装成功。如果这一步就报“对象不支持此操作”多半是插件环境没生效后面所有调用都白搭。4. 手把手接入初始化、登录设备、开始播放4.1 构建播放窗口容器容器大小会影响视频拉伸效果推荐按显示区的比例来设置。如果你的页面是响应式布局建议在window.resize事件里动态调用插件窗口自适应的方法避免切分辨率后画面变形或出现黑边。另一个容易忽略的点是在SPA框架Vue、React中容器元素可能在插件初始化后才挂载到DOM上导致插件找不到节点。所以最稳妥的做法是在mounted或useEffect里等DOM渲染完成、nextTick之后再调用初始化。如果初始化太早容器宽高可能是0插件会认为你不需要显示画面。4.2 初始化WebVideoCtrl假设你已经引入了JS并且容器准备好了下面这段就能完成初始化function initWebVideoCtrl() { if (!window.WebVideoCtrl) { console.error(WebVideoCtrl对象不存在请检查JS引入或插件是否安装); return false; } WebVideoCtrl new WebVideoCtrl(); WebVideoCtrl.I(playWindow, { bWndFull: true, iWndWidth: 960, iWndHeight: 540, iMaxSplit: 4, // 最大分屏数 oPlugin: { iType: 2, bNoPlugin: false } }); // 可选注册事件回调 WebVideoCtrl.J({ onInit: function () { console.log(插件初始化成功); }, onError: function (errCode, errMsg) { console.error(插件错误, errCode, errMsg); } }); return true; }J()方法类似于注册事件监听器。onInit在插件完全就绪后触发之后你才可以去登录设备。我建议把登录和播放的逻辑全部放在onInit之后不要猜测“等个两秒就调用”那样容易在插件还没准备好时就抛出异常。4.3 登录设备并获取通道要让插件去拉某台摄像机的视频必须先让插件登录这台设备NVR或IPC。登录需要设备的IP、HTTP端口、用户名、密码。这里的HTTP端口通常是80不是RTSP的554注意区分。代码大致是var deviceInfo { szIp: 192.168.1.64, // 设备IP szPort: 80, // HTTP端口 szUserName: admin, szPassword: 12345 }; WebVideoCtrl.K(deviceInfo.szIp, deviceInfo.szPort, deviceInfo.szUserName, deviceInfo.szPassword, { success: function (data) { console.log(登录成功, data); // 登录成功后获取通道列表 WebVideoCtrl.M(192.168.1.64, 80, { success: function (channels) { console.log(通道列表, channels); startPreview(0); // 播第一个通道 } }); }, error: function (err) { console.error(登录失败, err); } });这里K()是登录M()是获取通道列表。不同版本的方法名可能不同但流程一致。注意admin账号密码一定不要直接硬编码在前端实际项目中应该由用户输入或者后端下发一次性票据。我这个例子只是为了演示插件调用顺序。如果设备有多个通道比如16路NVRchannels会是一个数组。你需要展示成下拉框或者按钮组用户选择通道后再播放。没有通道数据的设备一般是登录失败了或者账号没有视频权限。4.4 启动实时预览以及停止和清理拿到通道号后调用播放接口通常需要指定码流类型主码流高清、子码流流畅。一个典型组合是大屏显示用主码流九宫格或者手机端用子码流。切码流的API一般是第四个参数传0主码流、1子码流。function startPreview(channel) { WebVideoCtrl.N({ szIp: 192.168.1.64, szPort: 80, iChannelID: channel, iStreamType: 0, // 0主码流1子码流 iProtocolType: 0, // 0 TCP1 UDP success: function () { console.log(预览启动); }, error: function (err) { console.error(预览失败, err); } }); }N()是开始预览O()是停止预览具体方法名以你的SDK版本为准。停止预览后要释放资源否则短时间频繁切换通道会累积句柄最终导致插件崩溃。页面卸载时一定记得清理function logoutAndStop() { WebVideoCtrl.O(); // 停止所有预览 WebVideoCtrl.P(192.168.1.64, 80); // 登出设备 WebVideoCtrl.C(); // 释放插件资源 }前后的调用顺序不能乱先停止预览再登出最后释放插件。直接关页面而不调停止预览在部分版本里会导致后台进程残留下次打开页面时端口被占用初始化失败。5. 高频API组合多画面、云台、抓图、对讲5.1 多画面分屏切换监控大屏场景中多画面分屏是刚需。插件一般提供内置的分屏能力你可以设置iMaxSplit最大分屏数为4、9、16等然后通过设置当前窗口的分屏模式。我这里用伪API说明思路// 切换为2x2四画面 WebVideoCtrl.setSplit(4); // 在某个格子中播放指定通道 WebVideoCtrl.startPreviewByWindow(windowIndex, ip, port, channel, streamType);很多SDK内部叫法不同但都有类似机制。分屏模式下要注意主码流和子码流的选择要合理四个画面同时走主码流很容易让NVR解码能力吃紧导致画面卡顿。建议分屏超过4路时优先用子码流单路放大时再切换主码流。5.2 云台控制与预置位云台控制是监控系统里高频操作插件接口会提供方向控制、变倍、变焦、预置位设置、巡航等。方向控制一定要做“按下开始、松开停止”的逻辑如果只发一次转动指令设备会一直转到限位才停。正确流程是// 按下开始向上转动 WebVideoCtrl.ptzControl(ip, port, channel, up, 0, function () {}); // 松开停止 WebVideoCtrl.ptzControl(ip, port, channel, stop, 0, function () {});同时做防抖按下的时间间隔太短就忽略防止抖动导致控制指令积压。预置位调用一般先设置再巡航到目标逻辑上先调用“设置预置位”接口再调用“转到预置位”接口。需要注意不同设备支持的预置位号可能不同要先查设备能力。5.3 抓图、本地录像与倒带回放业务侧经常要为“证据留存”做抓图或录像。插件提供了本地抓图和本地录像的API底层是通过插件直接抓取解码后的画面图片格式一般是JPEG保存在本地磁盘。抓图逻辑WebVideoCtrl.capturePicture(ip, port, channel, { success: function (data) { console.log(抓图成功保存路径:, data); }, error: function (err) { console.error(抓图失败, err); } });本地录像则类似WebVideoCtrl.startRecord(ip, port, channel); WebVideoCtrl.stopRecord(ip, port, channel);要留意的是这里的“本地录像”存的路径在插件服务端机器上不是浏览器所在的机器。如果插件是本地服务模式保存路径通常是服务配置里指定的目录。实际项目中需要做服务端录像时优先通过后端调用设备SDK或ONVIF来做而不是依赖前端插件录像因为前端录像很容易被清理或中断。回放方面插件一般支持通过时间轴查询录像文件然后调用回放接口。回放接口和预览接口最大的区别是要多传一个时间段参数。实现回放时要注意时区问题设备自身时区和浏览器时区不一致会导致查不到录像。通常统一用设备本地时间查询前端展示时再用浏览器时区处理。6. 真实排错经历插件装好了就是不显示画面6.1 排查链路从页面报错到系统服务我在处理这类问题时习惯按链路排查页面JS是否加载 - 初始化是否成功 - 插件服务是否运行 - 网络是否通 - 设备账号是否有效 - 协议和码流参数是否匹配。任何一环断了现象都可能是同一个“画面不显示”。先打开浏览器开发者工具看Console有没有报错。最常见的报错是WebVideoCtrl is not defined这说明JS没引入或引入顺序有问题。其次是对象不支持此操作这说明JS引入了但插件对象创建失败多半是ActiveX控件或扩展没生效。这时候不要急着看网络先把本机环境和示例页面对照一遍。如果页面无报错但黑屏那么大概率是插件服务本身没起来。打开任务管理器搜索该厂商相关的进程名比如xxxService.exe或xxxPlugin.exe如果不存在就去Windows服务里手动启动。很多情况下插件安装后服务是“手动启动”类型只有页面调用时才会拉起但如果启动条件不满足就起不来。6.2 IE浏览器ActiveX被拦截的怪问题有次客户现场是Windows 7 IE11开发机一切正常客户机死活加载不出控件。我远程一看页面底部弹了个黄色提示条“已阻止此网站使用ActiveX控件”。这是IE安全等级过高导致的。解决方案是把设备页面地址加入受信任站点并把该站点区域的安全级别调低。但客户是内网管控不允许改IE设置最后只能让管理员下发策略把域名加到白名单里。还有一个坑IE的“启用内存保护帮助减少联机攻击”选项会影响ActiveX运行。如果勾选了“为增强保护模式启用64位进程”可能导致32位控件无法加载。解决办法是在“Internet选项-高级”中取消勾选增强保护模式或者使用32位IE。6.3 Chrome下插件白屏本地服务与混合内容排查新版Chrome下白屏先看浏览器右上角有没有插件扩展图标。如果没有说明扩展未安装或者被自动停用。去chrome://extensions检查扩展是否存在重新启用。如果扩展在但页面无法连接很可能是本地服务没监听在预期端口。用命令行验证netstat -ano | findstr 80808080换成实际端口。如果看不到本地监听说明服务没起来。如果监听正常但页面还是白屏那就要看是不是混合内容问题。部署页面是http://但是服务在https://或者反过来浏览器会拦截。最简单的方法是把服务地址改成http://127.0.0.1:端口并把页面部署成http://协议保持一致。如果是纯内网环境一般不会强制上HTTPS。6.4 网络与端口不通导致的预览失败插件初始化成功后调用播放接口提示“网络错误”或“连接超时”先别怀疑插件用命令行测一下设备IP和端口ping 192.168.1.64 telnet 192.168.1.64 8080是设备HTTP端口如果通了再测RTSP端口554。如果RTSP端口不通可能是网络策略限制也可能是设备启用了“流媒体加密”选项。有些设备默认只开放RTSP over TCP有些只开放UDP你需要和网络管理员确认。前端这边能做的就是尝试把传输协议改成TCP或UDP来回测通常iProtocolType参数从0改成1能解决一部分UDP不通的问题。如果多网卡环境插件拉流时可能走了错误的网卡导致视频断断续续或者连接失败。可以在初始化参数里指定绑定的本机IP或者在设备网络配置里设置多播/单播模式。这些都是从实际项目里试出来的官方文档不一定写。7. 插件方案不是终点现代H5播放的替代路线7.1 插件的天花板移动端和国产化环境做监控平台不可能只盯着Windows PC。很多用户现在拿着一台手机就想看实时画面插件方案在这个场景下直接失效。还有信创环境UOS、麒麟系统浏览器不允许装ActiveXChrome扩展也要看兼容性。我在一个项目里遇到过客户要求支持“国产浏览器环境且免插件”原来的ActiveX方案完全没有可行性必须换一套思路。所以如果你现在刚着手设计一个新项目我的建议是明确一条“双轨”思路。老设备、老系统保留插件通道作为兼容项新建设备和平台尽量走H5流媒体方案用一个转码网关把RTSP源统一转成浏览器能消费的WebRTC或HTTP-FLV流页面用支持WebRTC的播放器或者WASM解码器播放。7.2 免插件方案转码网关与WebRTC市面上主流的免插件方案是“端侧RTSP - 媒体网关 - 浏览器播放”。媒体网关要做三件事拉取设备RTSP流转码或封装成浏览器可播放的协议把流分发给浏览器端。WebRTC是延迟最低的基本能在500毫秒以内接近插件体验但需要网关支持并做好信令交互。HTTP-FLV延迟稍高但胜在兼容性可以用mpegts.js或flv.js播放。另一种方案是GB28181国标平台设备通过国标协议主动注册到平台平台输出RTSP或WebRTC给前端。这种方式适合大规模视频接入尤其是公安、园区类项目。缺点是需要维护一套国标网关部署成本高。小项目如果只有十几路摄像头直接部署一个转码服务就够了。前端部分我会用WebRTC播放器插件这里指纯JS库不是本地插件去接代码逻辑和插件完全不同。初始化的是RTCPeerConnection收到流后塞进video标签的srcObject。这要求后端信令服务打通前端才能拿到answer和候选地址。对不熟悉网络协议的前端来说这个学习曲线明显更陡。7.3 如果必须兼容我建议这样规划我的经验是做一个“环境检测能力降级”的入口页。页面加载后先检测当前浏览器和操作系统如果满足插件条件就加载插件播放器如果不满足就加载H5播放器。两种播放器的业务接口尽量封装成一致抽象层对外暴露play(streamParams)和stop()内部再根据环境路由。这样既保护了存量项目又给新环境留了活路。要注意的是两种播放器的事件体系不一样比如“断流重连”“码流切换”一定要在抽象层里做统一。不要写一堆if (isIE) { ... } else { ... }散落在各处否则三个月后你自己都不想维护。我个人做了几年安防平台越来越觉得技术选型不是越新越好而是要看设备的可交付性。插件方案再老只要现场是WindowsChrome它依然是最省事、延迟最低的选择。但如果你预见项目会扩展移动端或信创环境那从第一天起就要把H5播放器方案纳入规划哪怕先做成双轨。最后分享一个细节无论用哪种方案都要在页面里把“通道列表”和“设备登录状态”先拉出来用户看不到画面时优先排查设备侧不要一上来就怀疑播放器。前端只是管道源才是根本。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表