一、項目說明
1. H265web.js 簡介
H265web.js 是一個用於在 Web 瀏覽器中播放 H.265 視頻的 JavaScript 播放器。它支持在瀏覽器中直接解碼 H.265 編碼的視頻流,提供了高效的視頻播放體驗。在 Element UI 項目中集成 H265web.js 可以讓我們輕松實現 H.265 視頻的播放功能。
H265web.js 開源地址:
https://github.com/numberwolf/h265web.js
文檔地址:
https://github.com/numberwolf/h265web.js?tab=readme-ov-file
目前vue裡集成H265web.js 還有一定的復雜度,本文作以詳細介紹。
2. 準備環境
- 一個 準備好的 element-ui 項目和開發環境
- 本文基於VUE2.0
二、項目配置
1. 下載 H265web.js
我們采用直接下載 dist 的方式,而不是使用 npm 安裝,據說npm對wasm不太友好(我沒有實證)。
到官網找到最新版本的 releasae或者接下載整個項目:
![](https://news.xinpengboligang.com/upload/keji/c392ae185d457ec3b0edef5d7f30338d.jpeg)
後面需要使用的是 dist/ 目錄的內容。
本文參考了官方目錄 example_vue2/ 裡的實現代碼,主要加入了對 npm 自動化構建的支持。
2. 在vue項目裡引入 H265web
首先在 vue 項目裡新建一個 template 目錄,按如下方式組織文件:
![](https://news.xinpengboligang.com/upload/keji/a070b71d9477fb880720aa8ab14aaefb.jpeg)
即把 H265web.js 的dist目錄,拷到 template/libs/h265web下。
index.html 是構建vue項目時使用的模板文件,內容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Your App Title</title>
<script type="text/javascript" src="static/js/missile.js"></script>
<script src="static/js/h265webjs-v20221106.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
使用npm命令構建時,默認情況會在目錄的 public/ 目錄自動生成 index.html 文件。但是我們需要在 index.html 裡引入 h265web.js 的文件,構建後再去添加引用就有些繁瑣,所以自定義了此模板頁方便構建。
3. 設置 vue.config.js
本步驟的目的是在 npm 構建時,自動將 h265 的庫文件拷貝到構建的目標目錄 。
這裡重點是使用了 copy-webpack-plugin 和 html-webpack-plugin 兩個構建的插件。
vue.config.js 設置
// 這一句定義在 module.exports 之前
const CopyWebpackPlugin = require('copy-webpack-plugin')
// 定義模板頁位置
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 在 module.exports ,加入
module.exports = {
configureWebpack: {
// provide the app's title in webpack's name field, so that
// it can be accessed in index.html to inject the correct title.
name: name,
resolve: {
alias: {
'@': resolve('src')
}
},
plugins: [
new HtmlWebpackPlugin({
template: 'template/index.html'
}),
new CopyWebpackPlugin([
{
from: 'template/libs/h265web',
to: './static/js/'
}
])
]
}
}
這樣在執行 npm run dev 或 npm run build:prod時, h265web的庫文件會拷到目標的 static/js 目錄下。
執行構建命令的效果如下:
![](https://news.xinpengboligang.com/upload/keji/ee2a1b9bd6810d245b4c59d1475d8d1e.jpeg)
三、代碼引用
1. 參照官方demo , 創建 executor.js
路徑可按自己需要放置,我這裡放到了src/utils下:
![](https://news.xinpengboligang.com/upload/keji/c547aa46e339c18919c90392e1da2e8e.jpeg)
內容:
const PRESET_CONFIG = {
player: 'glplayer',
width: 960,
height: 540,
token: 'base64:QXV0aG9yOmNoYW5neWFubG9uZ3xudW1iZXJ3b2xmLEdpdGh1YjpodHRwczovL2dpdGh1Yi5jb20vbnVtYmVyd29sZixFbWFpbDpwb3JzY2hlZ3QyM0Bmb3htYWlsLmNvbSxRUTo1MzEzNjU4NzIsSG9tZVBhZ2U6aHR0cDovL3h2aWRlby52aWRlbyxEaXNjb3JkOm51bWJlcndvbGYjODY5NCx3ZWNoYXI6bnVtYmVyd29sZjExLEJlaWppbmcsV29ya0luOkJhaWR1',
extInfo: {
moovStartFlag: true,
coreProbePart: 0.1,
ignoreAudio: 0,
autoPlay: true,
core: 1
}
}
// FYI. the Player class is a wrapper container provide the init and destory methods.
// you should destory the player instance at the page unshift time.
// By the way if you want to impl a progress bar you should view the normal_example.
// It's a full example. This demo only provide a minimalist case.
// Why use class? Convenient der is enough :)
// Should I registry the instnace at a microTask? Of course.
// Pay attention to index.html. vite boy. Don't forget import the static source code :)
export class Player {
#config = {};
instance;
constructor(opt = {}) {
const { presetConfig = PRESET_CONFIG } = opt
if (presetConfig) Object.assign(this.#config, presetConfig)
}
init(url) {
this.instance = window.new265webjs(url, this.#config)
}
}
2. 在 vue 頁面裡引用
html 模板
<!-- video player content -->
<div class="player-container">
<div id="glplayer" class="glplayer"></div>
</div>
js
這裡是用在 dialog 裡的, 在watch 的 $nextTick() 中來創建播放器, 可視需要在其它事件中使用。
import { Player } from '@/utils/executor'
watch: {
show() {
const that = this
this.mrl = this.mediaObject.flv
if (that.visible) {
this.$nextTick(() => {
console.info(TAG, '初始化播放器', this.show)
const player = new Player()
player.init(this.mrl)
that.instance = player.instance
player.instance.onLoadFinish = () => {
const mediaInfo = player.instance.mediaInfo()
console.log(TAG, 'onLoadFinish', mediaInfo)
}
player.instance.onPlayFinish = () => {
console.log(TAG, 'onPlayFinish')
}
player.instance.do()
})
}
}
},
其它地方使用,調用 player.instance 相關的方法即可。
運行效果:
![](https://news.xinpengboligang.com/upload/keji/a2d41d8077efc59df0a4aff42019a563.jpeg)