海康威視web控件開發的(de)正确姿勢
發表時(shí)間:2018-7-18
發布人(rén):融晨科技
浏覽次數:290
最近一個(gè)vue的(de)項目裏面需要(yào / yāo)呈現某現場的(de)實時(shí)視頻,組裏購買了(le/liǎo)一組海康威視的(de)網絡攝像頭,是(shì)那種帶CS端管理程序的(de),通過ip,port,用戶名,密碼登錄攝像頭,但是(shì)不(bù)知道(dào)如何應用到(dào)web項目中。查找資料後,我在(zài)網上(shàng)找到(dào)一個(gè)web控件開發包,于(yú)是(shì)在(zài)此基礎上(shàng)進行開發,實現vue項目需要(yào / yāo)的(de)功能。
熟悉demo程序
打開這(zhè)個(gè)web控件開發包的(de)文檔,可以(yǐ)看到(dào),這(zhè)個(gè)控件是(shì)利用ActiveX控件和(hé / huò)NPAPI實現的(de)。IE上(shàng)用ActiveX控件,Chrome基于(yú)NPAPI實現,并且需要(yào / yāo)安裝codebase目錄下的(de)WebComponentsKit.exe插件。這(zhè)裏我們可以(yǐ)了(le/liǎo)解到(dào),該控件不(bù)适用于(yú)高版本Chrome浏覽器,這(zhè)是(shì)一個(gè)很不(bù)爽的(de)地(dì / de)方。不(bù)過目前還沒有找到(dào)其他(tā)合适的(de)方案,也(yě)隻能試試這(zhè)個(gè)方案了(le/liǎo)。
打開demo目錄下的(de)index.html,我們可以(yǐ)看到(dào)它支持的(de)功能還是(shì)很多的(de)。
而(ér)我并不(bù)需要(yào / yāo)這(zhè)麽多功能,隻需要(yào / yāo)能把網絡攝像頭的(de)畫面呈現在(zài)項目頁面上(shàng)就(jiù)好了(le/liǎo)。
定制開發
遇到(dào)的(de)問題: 一開始也(yě)沒有熟讀這(zhè)個(gè)控件的(de)demo源碼,就(jiù)想着把從初始化到(dào)登錄,再到(dào)預覽這(zhè)部分功能截取出(chū)來(lái)移植到(dào)Vue項目裏就(jiù)好。然而(ér)在(zài)裁剪代碼的(de)過程出(chū)現了(le/liǎo)各種報錯,嘗試定位錯誤的(de)過程浪費了(le/liǎo)不(bù)少時(shí)間。
解決方法: 之(zhī)後想到(dào)的(de)方法是(shì),把demo中的(de)多餘的(de)功能一個(gè)一個(gè)去掉,在(zài)此過程中要(yào / yāo)觀察demo是(shì)否可以(yǐ)正常登錄和(hé / huò)預覽畫面。最後的(de)demo中我隻保留了(le/liǎo)從初始化到(dào)登錄以(yǐ)及預覽這(zhè)部分的(de)代碼。這(zhè)個(gè)過程下來(lái),我對這(zhè)部分的(de)js邏輯也(yě)是(shì)比較清楚了(le/liǎo),最終也(yě)是(shì)順利地(dì / de)移植到(dào)Vue項目中。
代碼分享
移植的(de)這(zhè)部分代碼我封裝成了(le/liǎo)一個(gè)webVideo,js文件,供頁面調用。
而(ér)在(zài)頁面中,首先需要(yào / yāo)引入該js文件
import { WebVideo } from '@/assets/js/webVideo.js'
然後需要(yào / yāo)在(zài)mounted方法中進行初始化對象
this.webVideo = new WebVideo()
最後在(zài)打開dialog顯示視頻的(de)位置調用init方法和(hé / huò)clickLogin方法(我在(zài)clickLogin方法的(de)成功回調函數中調用獲取頻道(dào)信息和(hé / huò)設備端口的(de)方法,并在(zài)這(zhè)之(zhī)後調用了(le/liǎo)預覽方法)。
// 顯示視頻dialog
this.videoBoxVisible = true
// nextTick回調中調用init和(hé / huò)clickLogin
this.$nextTick(() => {
this.webVideo.init()
this.webVideo.clickLogin()
})
最終可以(yǐ)看到(dào)攝像頭畫面啦,算是(shì)有了(le/liǎo)成果!
有朋友留言說(shuō)想看一下這(zhè)個(gè)js文件的(de)寫法,這(zhè)裏分享一下。有時(shí)候不(bù)能及時(shí)看到(dào)評論,見諒
// 初始化插件
export function WebVideo() {
this.g_iWndIndex = 0
this.szDeviceIdentify = ''
this.deviceport = ''
this.deviceport = ''
this.channels = []
this.ip = '172.29.3.101'
this.port = '80'
this.username = 'admin'
this.password = '123456'
this.init = function() {
var self = this
// 檢查插件是(shì)否已經安裝過
var iRet = WebVideoCtrl.I_CheckPluginInstall();
if (-1 == iRet) {
alert("您還未安裝過插件,雙擊開發包目錄裏的(de)WebComponentsKit.exe安裝!");
return;
}
// 初始化插件參數及插入插件
WebVideoCtrl.I_InitPlugin('100%', '100%', {
bWndFull: true,
iPackageType: 2,
iWndowType: 1,
cbInitPluginComplete: function () {
WebVideoCtrl.I_InsertOBJECTPlugin("divPlugin");
}
});
}
// 登錄
this.clickLogin = function () {
var self = this
if ("" == self.ip || "" == self.port) {
return;
}
self.szDeviceIdentify = self.ip + "_" + self.port;
WebVideoCtrl.I_Login(self.ip, 1, self.port, self.username, self.password, {
success: function (xmlDoc) {
setTimeout(function () {
self.getChannelInfo();
self.getDevicePort();
}, 10);
setTimeout(function() {
self.clickStartRealPlay()
}, 500)
},
error: function (status, xmlDoc) {
}
});
}
// 退出(chū)
this.clickLogout = function() {
var self = this
if (null == self.szDeviceIdentify) {
return;
}
var iRet = WebVideoCtrl.I_Logout(self.szDeviceIdentify);
if (0 == iRet) {
self.getChannelInfo();
self.getDevicePort();
}
}
// 獲取通道(dào)
this.getChannelInfo = function() {
var self = this
self.channels = []
if (null == self.szDeviceIdentify) {
return;
}
// 模拟通道(dào)
WebVideoCtrl.I_GetAnalogChannelInfo(self.szDeviceIdentify, {
async: false,
success: function (xmlDoc) {
var oChannels = $(xmlDoc).find("VideoInputChannel");
$.each(oChannels, function (i) {
var id = $(this).find("id").eq(0).text(),
name = $(this).find("name").eq(0).text();
if ("" == name) {
name = "Camera " + (i < 9 ? "0" + (i + 1) : (i + 1));
}
self.channels.push({
id: id,
name: name
})
});
},
error: function (status, xmlDoc) {
}
});
}
// 獲取端口
this.getDevicePort = function() {
var self = this
if (null == self.szDeviceIdentify) {
return;
}
var oPort = WebVideoCtrl.I_GetDevicePort(self.szDeviceIdentify);
if (oPort != null) {
self.deviceport = oPort.iDevicePort;
self.deviceport = oPort.iRtspPort;
}
}
// 開始預覽
this.clickStartRealPlay = function() {
var self = this
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(self.g_iWndIndex),
iChannelID = self.channels[0].value
if (null == self.szDeviceIdentify) {
return;
}
var startRealPlay = function () {
WebVideoCtrl.I_StartRealPlay(self.szDeviceIdentify, {
iRtspPort: self.deviceport,
iStreamType: '1',
iChannelID: iChannelID,
bZeroChannel: false,
success: function () {
},
error: function (status, xmlDoc) {
if (403 === status) {
} else {
}
}
});
};
if (oWndInfo != null) {// 已經在(zài)播放了(le/liǎo),先停止
WebVideoCtrl.I_Stop({
success: function () {
startRealPlay();
}
});
} else {
startRealPlay();
}
}
// 停止預覽
this.clickStopRealPlay = function() {
var self = this
var oWndInfo = WebVideoCtrl.I_GetWindowStatus(self.g_iWndIndex)
if (oWndInfo != null) {
WebVideoCtrl.I_Stop({
success: function () {
},
error: function () {
}
});
}
}
}
2018年12月1日補充
很多人(rén)都有報錯的(de)情況,請檢查下是(shì)否在(zài)index.html中引用了(le/liǎo)這(zhè)個(gè)js,這(zhè)個(gè)js來(lái)源于(yú)Web控件開發包。
<script type="text/javascript" id="videonode" src="static/webVideoCtrl.js"></script>
對了(le/liǎo),還有一個(gè)jsPlugin-1.0.0.min.js也(yě)需要(yào / yāo)放在(zài)static目錄下,但是(shì)不(bù)需要(yào / yāo)在(zài)index.html引用,因爲(wéi / wèi)webVideoCtrl.js會主動去調用同目錄下的(de)jsPlugin-1.0.0.min.js。
我能補充的(de)坑大(dà)概就(jiù)這(zhè)些了(le/liǎo)吧,因爲(wéi / wèi)這(zhè)個(gè)項目也(yě)過去很久了(le/liǎo),我用到(dào)的(de)功能也(yě)真的(de)少,對于(yú)不(bù)能答複大(dà)家太多深入的(de)問題,我感到(dào)抱歉。
開發包64位下載地(dì / de)址
鏈接:https://pan.baidu.com/s/19uCuu838TwP-OBqWqo-MPw
提取碼:futg
開發包32位下載地(dì / de)址
鏈接:https://pan.baidu.com/s/1byAij-cStvoYhS9SlV5dDw
提取碼:f24r