前言
這里主要是 來看一下 海康視頻 的一個九宮格播放的需求
然后 在實際使用的過程中產(chǎn)生了一些問題, 比如 增加一個視頻, 應(yīng)該只增量請求這一個視頻的服務(wù), 而一些實現(xiàn)下是全量請求了 整個視頻列表的服務(wù)
另外 就是全屏播放, 如果是 自己寫樣式來實現(xiàn) 全屏播放, 可能需要 重新創(chuàng)建 ??档膒layer, 進而 需要重新請求 ??档囊曨l服務(wù)
另外 還有 cpu, 內(nèi)存占用過高的情況, 然后 還有一些疑似 內(nèi)存泄露的情況
這里 調(diào)整一個版本 記錄一下
以下有一些版本, 一個是自定義實現(xiàn)九宮格, 這樣做的問題 還是挺多的, 以上的問題基本上都占了, 然后另外一個版本是 直接使用 ??底约禾峁┑?api 來實現(xiàn) 九宮格, 會稍微好一些
?文章來源地址http://www.zghlxwxcb.cn/news/detail-851660.html
?文章來源:http://www.zghlxwxcb.cn/news/detail-851660.html
整體來說, 一個比較良好的情況是, 否則的話 可能會出現(xiàn)一些 較高的資源占用的問題
- 新增一個視頻的時候, 僅僅增量請求這一個視頻的數(shù)據(jù), 增量的和??到⑦B接
- 全屏的時候 使用海康的 api, 它自己已經(jīng)實現(xiàn)了 自適應(yīng), 否則 自己處理的話 自適應(yīng)有可能需要重新和??到⑦B接, 重新渲染
- 盡量避免 并發(fā) 和請求??档慕涌? 經(jīng)常會崩潰, 盡量避免 頻繁的和??禂嚅_視頻連接, 重新創(chuàng)建視頻連接
?
?
自己自定義九宮格
這個就相當(dāng)于是 海康的視頻播放器只播放一個視頻
然后 這里是 循環(huán) codeUrlList, 一個視頻對應(yīng)于一個 player, 雖然同時 播放了多個 player 但是 實際上核心占用資源的貌似是其中一個
key 需要指定, 否則 在一些需要重新渲染 ??祊layer 的場景下面, 模型改變了 但是每一個 div 內(nèi)部的 player 的 dom 不會重新渲染, 可能會導(dǎo)致 視頻錯位等問題
這個 問題就是需要自己實現(xiàn)全屏的樣式, 以及全拼的時候需要全部重新渲染一次, 才能適應(yīng)全屏之后的窗口
其他的 增量的獲取海康服務(wù), 避免并發(fā)的請求??到涌?就需要自己處理了
以下的測試代碼 看 (!singlePlayer) 部分
?
業(yè)務(wù)組件如下
<template>
<div class="indexDiv">
<div v-if="!singlePlayer" v-for="item in codeUrlList" :key="item.code" style="width:400px; display: inline; float:left;">
<Player :palyer-code="item.code" :play-url="item.url"></Player>
</div>
<PlayerSplitByHk ref="playerHk" v-if="singlePlayer"></PlayerSplitByHk>
<button @click="handleFullScreen" >全屏</button>
</div>
</template>
<script>
import Player from "./Player.vue"
import PlayerSplitByHk from "./PlayerSplitByHk.vue"
export default {
name: "Index",
components: {
Player,
PlayerSplitByHk,
},
data() {
return {
singlePlayer: false,
codeUrlList: [{"code":"61092100561310001001","url":"ws://112.110.110.109/openUrl/KG6aIkE"},{"code":"61102600581328004001","url":"ws://112.110.110.109:559/openUrl/KHubaKc"},{"code":"61092200561310001001","url":"ws://112.110.110.109:559/openUrl/KIs4xbO"},{"code":"61092200561310001002","url":"ws://112.110.110.109:559/openUrl/KJcCKwo"},{"code":"61092200561310002701","url":"ws://112.110.110.109/openUrl/KK6g812"},{"code":"61092200561310001901","url":"ws://112.110.110.109:559/openUrl/KL11U1W"},{"code":"61092800561310002101","url":"ws://112.110.110.109:559/openUrl/KLJjkk0"},{"code":"61092800561310002402","url":"ws://112.110.110.109:559/openUrl/KMu98ME"},{"code":"61092800561310002901","url":"ws://112.110.110.109/openUrl/KNaIYik"}]
};
},
mounted() {
// test for hk sudoku
if(this.singlePlayer) {
this.$refs.playerHk.updateCodeUrlList(this.codeUrlList)
// call updateCodeUrlList if codeUrlList updated
let _this = this
setTimeout(function() {
let updatedCodeUrlList = []
_this.codeUrlList.map(ele => updatedCodeUrlList.push(ele))
updatedCodeUrlList.splice(5, 3)
_this.$refs.playerHk.updateCodeUrlList(updatedCodeUrlList)
console.log(" splice with idx 6, 7, 8 ")
console.log(" ----------------------------- ")
}, 5000)
setTimeout(function() {
let updatedCodeUrlList = []
_this.codeUrlList.map(ele => updatedCodeUrlList.push(ele))
updatedCodeUrlList.splice(5, 3)
updatedCodeUrlList.push({code: "code1", url: "url1"})
updatedCodeUrlList.push({code: "code2", url: "url2"})
_this.$refs.playerHk.updateCodeUrlList(updatedCodeUrlList)
console.log(" push url1, url2 ")
console.log(" ----------------------------- ")
}, 10000)
}
},
methods: {
handleFullScreen() {
// test for hk sudoku
if(this.singlePlayer) {
this.$refs.playerHk.handleFullScreen()
}
}
}
}
</script>
<style scoped>
</style>
?
視頻播放組件如下
<template>
<div clas="outerDiv" >
<div class="main" :id="'playerDiv' + this.palyerCode" ></div>
</div>
</template>
<script>
export default {
name: "Player",
props: {
palyerCode: {
type: String,
default: "",
},
playUrl: {
type: String,
default: "",
},
},
data() {
return {
player: null
};
},
mounted() {
this.createPlayer()
this.startPlay()
},
methods: {
createPlayer() {
this.player = new window.JSPlugin({
szId: 'playerDiv' + this.palyerCode,
szBasePath: "./",
iMaxSplit: 4,
iCurrentSplit: 1,
openDebug: true,
oStyle: {
borderSelect: '#000',
}
})
// 事件回調(diào)綁定
let _this = this
this.player.JS_SetWindowControlCallback({
windowEventSelect: function (iWndIndex) { //插件選中窗口回調(diào)
console.log('windowSelect callback: ', iWndIndex);
_this.player.JS_Stop(iWndIndex).then(
() => { console.log('stop play ' + iWndIndex + ' success') },
e => { console.error(e) }
)
},
pluginErrorHandler: function (iWndIndex, iErrorpalyerCode, oError) { //插件錯誤回調(diào)
console.log('pluginError callback: ', iWndIndex, iErrorpalyerCode, oError);
},
windowFullCcreenChange: function (bFull) { //全屏切換回調(diào)
console.log('fullScreen callback: ', bFull);
},
firstFrameDisplay: function (iWndIndex, iWidth, iHeight) { //首幀顯示回調(diào)
console.log('firstFrame loaded callback: ', iWndIndex, iWidth, iHeight);
},
performanceLack: function () { //性能不足回調(diào)
console.log('performanceLack callback: ');
}
});
},
startPlay() {
let playURL = this.playUrl
let model = 1
console.log(" start replay with url : " + playURL)
// this.player.JS_Play(playURL, { playURL, model }, 0).then(
// () => { console.log('realplay success') },
// e => { console.error(e) }
// )
}
}
}
</script>
<style scoped>
</style>
?
?
使用 hik 提供的 api 實現(xiàn)九宮格
這里的九宮格的實現(xiàn)就是直接基于 hk 的 api 了, 比如這里的 this.player.JS_ArrangeWindow, this.player.JS_Play?
然后 全屏基于 this.player.JS_FullScreenDisplay, 然后 全拼的狀態(tài)可以通過 windowFullCcreenChange 進行獲取
一些 常見的回調(diào)函數(shù), 也在 demo 中有體現(xiàn)
然后 降低客戶端和??捣?wù)器這邊的開銷的處理, 主要是如下的 更新前后的視頻列表, 如果目標索引的視頻變了, 才重新發(fā)起請求, 重新建立視頻連接
?
這樣的話 開始的時候點擊九個視頻, 資源占用大概是 cpu100%, 內(nèi)存差不多是 500M 左右, 然后 隨著時間的推移, 主項目的js引擎[不是海康player的js引擎] 占用內(nèi)存逐漸升高, 這個具體就得看這個 player 的問題了, 然后刷新 Index.vue 的頁面, 這個內(nèi)存占用 依然存在
這里 就不深究了
?
業(yè)務(wù)組件如下
<template>
<div class="indexDiv">
<div v-if="!singlePlayer" v-for="item in codeUrlList" :key="item.code" style="width:400px; display: inline; float:left;">
<Player :palyer-code="item.code" :play-url="item.url"></Player>
</div>
<PlayerSplitByHk ref="playerHk" v-if="singlePlayer"></PlayerSplitByHk>
<button @click="handleFullScreen" >全屏</button>
</div>
</template>
<script>
import Player from "./Player.vue"
import PlayerSplitByHk from "./PlayerSplitByHk.vue"
export default {
name: "Index",
components: {
Player,
PlayerSplitByHk,
},
data() {
return {
singlePlayer: false,
codeUrlList: [{"code":"61092100561310001001","url":"ws://112.110.110.109/openUrl/KG6aIkE"},{"code":"61102600581328004001","url":"ws://112.110.110.109:559/openUrl/KHubaKc"},{"code":"61092200561310001001","url":"ws://112.110.110.109:559/openUrl/KIs4xbO"},{"code":"61092200561310001002","url":"ws://112.110.110.109:559/openUrl/KJcCKwo"},{"code":"61092200561310002701","url":"ws://112.110.110.109/openUrl/KK6g812"},{"code":"61092200561310001901","url":"ws://112.110.110.109:559/openUrl/KL11U1W"},{"code":"61092800561310002101","url":"ws://112.110.110.109:559/openUrl/KLJjkk0"},{"code":"61092800561310002402","url":"ws://112.110.110.109:559/openUrl/KMu98ME"},{"code":"61092800561310002901","url":"ws://112.110.110.109/openUrl/KNaIYik"}]
};
},
mounted() {
// test for hk sudoku
if(this.singlePlayer) {
this.$refs.playerHk.updateCodeUrlList(this.codeUrlList)
// call updateCodeUrlList if codeUrlList updated
let _this = this
setTimeout(function() {
let updatedCodeUrlList = []
_this.codeUrlList.map(ele => updatedCodeUrlList.push(ele))
updatedCodeUrlList.splice(5, 3)
_this.$refs.playerHk.updateCodeUrlList(updatedCodeUrlList)
console.log(" splice with idx 6, 7, 8 ")
console.log(" ----------------------------- ")
}, 5000)
setTimeout(function() {
let updatedCodeUrlList = []
_this.codeUrlList.map(ele => updatedCodeUrlList.push(ele))
updatedCodeUrlList.splice(5, 3)
updatedCodeUrlList.push({code: "code1", url: "url1"})
updatedCodeUrlList.push({code: "code2", url: "url2"})
_this.$refs.playerHk.updateCodeUrlList(updatedCodeUrlList)
console.log(" push url1, url2 ")
console.log(" ----------------------------- ")
}, 10000)
}
},
methods: {
handleFullScreen() {
// test for hk sudoku
if(this.singlePlayer) {
this.$refs.playerHk.handleFullScreen()
}
}
}
}
</script>
<style scoped>
</style>
?
視頻播放組件如下
<template>
<div class="outerDiv" >
<div class="main" id="playerDiv" ></div>
</div>
</template>
<script>
export default {
name: "PlayerSplitByHk",
props: {
},
data() {
return {
player: null,
videoListMax: 0,
isFirstClick: false,
codeUrlList: null,
};
},
mounted() {
this.createPlayer()
},
methods: {
updateCodeUrlList(newCodeUrlList) {
let oldCodeUrlList = this.codeUrlList
this.codeUrlList = newCodeUrlList
this.videoListMax = Math.max(this.videoListMax, newCodeUrlList.length)
let matrixLen = newCodeUrlList.length > 4 ? 3 : (newCodeUrlList.length > 1 ? 2 : 1)
this.isFirstClick = true
this.player.JS_ArrangeWindow(matrixLen)
for(let i=newCodeUrlList.length; i<this.videoListMax; i++) {
console.log(" stop replay with idx : " + i)
this.player.JS_Stop(i);
}
for(let i=0; i<newCodeUrlList.length; i++) {
let newItem = newCodeUrlList[i]
let oldItem = oldCodeUrlList && oldCodeUrlList[i]
if((!oldItem) || (oldItem.code !== newItem.code)) {
this.startPlay(i)
}
}
},
handleFullScreen() {
this.player.JS_FullScreenDisplay(true).then(
() => { console.log(`wholeFullScreen success`) },
e => { console.error(e) }
)
},
createPlayer() {
this.player = new window.JSPlugin({
szId: 'playerDiv',
szBasePath: "/static",
iMaxSplit: 9,
iCurrentSplit: 1,
iWidth: 400,
iHeight: 300,
openDebug: true,
oStyle: {
// border: '#green',
// borderSelect: '#ffcc00',
}
})
// 事件回調(diào)綁定
let _this = this
this.player.JS_SetWindowControlCallback({
windowEventSelect: function (iWndIndex) { //插件選中窗口回調(diào)
if(_this.isFirstClick) {
_this.isFirstClick = false
return ;
}
console.log(" do what you want ")
},
pluginErrorHandler: function (iWndIndex, iErrorpalyerCode, oError) {
console.log('pluginError callback: ', iWndIndex, iErrorpalyerCode, oError);
},
windowFullCcreenChange: function (bFull) {
console.log('fullScreen callback: ', bFull);
},
firstFrameDisplay: function (iWndIndex, iWidth, iHeight) {
console.log('firstFrame loaded callback: ', iWndIndex, iWidth, iHeight);
},
performanceLack: function () {
console.log('performanceLack callback: ');
}
});
},
startPlay(idx) {
let playURL = this.codeUrlList[idx].url
let model = 1
console.log(" start replay with idx : " + idx)
// this.player.JS_Play(playURL, { playURL, model }, idx).then(
// () => { console.log('realplay success') },
// e => { console.error(e) }
// )
}
}
}
</script>
<style scoped>
</style>
?
?
完?
?
?
?
到了這里,關(guān)于45 對接??狄曨l九宮格的實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!