# h265web.js **Repository Path**: linshl/h265web.js ## Basic Information - **Project Name**: h265web.js - **Description**: No description available - **Primary Language**: Unknown - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-01-19 - **Last Updated**: 2021-07-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: 流媒体 ## README # h265web.js 中文 | English 一个可支持HEVC/H.265编码播放360P、480P、540P、720P、1080P的播放器 h265web.js | h265web.js | mpeg.js `(解析ts)` | h265web.js 底层265解码器SDK | | ---- | ---- | ---- | | [h265web.js](https://github.com/numberwolf/h265web.js) | [MPEG-Demuxer.js](https://github.com/numberwolf/MPEG-Demuxer.js) | [h265web.js-wasm-decoder](https://github.com/numberwolf/h265web.js-wasm-decoder) | License GPL-3.0 https://www.gnu.org/licenses/gpl-3.0.md # Remind! 因为使用软解码能力(浏览器上无法做硬解码加速 与 汇编优化),故设备电脑配置性能 会 影响播放器性能! 请注意: * 视频帧率最好 <= 30fps * 建议:24fps * 视频码率最好 <= 1.5Mb * 建议:300~600kbps (HEVC/H.265可提供较高的压缩率) ## 目录 - [0、说明](#0说明) - [更新日志](#更新日志) - [当前能力](#当前能力) - [当前版本token](#当前版本的token) - [联系我](#联系我) - [线上demo](#线上demo) - [效果预览](#效果预览) - [1、快捷方式使用](#1快捷方式使用) - [2、播放器SDK使用文档](#2播放器sdk使用文档) - [安装](#安装) - [播放器配置](#播放器配置) - [初始化播放器](#初始化播放器) - [播放器相关事件绑定](#播放器相关事件绑定) - [播放器API能力](#播放器api能力) - [3、其它](#3其它) - [捐赠 - 让作者更加拼命 - 捐赠的同学我会全部罗列出来](#捐赠) - [FFmpeg转码265编码的视频](#ffmpeg转码265编码的视频)
### 0、说明 ### #### 更新日志 #### | 更新日志 | 内容 | | ---- | ---- | | 时间 | 2021/07/04 | | - | 0.修复 `ISSUE#58` (默认内核缓存状态下的暂停问题) | | 时间 | 2021/07/01 | | - | 0.增加示例 与 编译所需 | | 时间 | 2021/06/27 | | - | 0.开源! | | - | 1.支持了FLV视频播放Seek能力 | | - | 2.解决了新播放内核的SEEK问题 | | - | 3.FLV播放新类型支持, 以及不需要设置播放内核 | | 时间 | 2021/05/30 | | - | 1.解决了一些Seek和播放的bug(比较重要的升级) | | - | 2.播放器封面图加载完成 事件通知 | | 时间 | 2021/05/24 | | - | 1.FLV点播支持(在备用播放内核模式下可用) | | 时间 | 2021/05/21 | | - | 1.HLS(无声直播)性能优化 | | 时间 | 2021/05/18 | | - | 1.HLS(直播)性能优化、增加声音Case | | 时间 | 2021/05/16 | | - | 1.MP4点播兼容BD265产出部分特殊box case | | 时间 | 2021/05/15 | | - | 1.修复HLS直播的部分问题 以及嵌套型的HLS | | 时间 | 2021/04/27 | | - | 1.修复部分视频播放中马赛克问题 | | - | 2.修复部分视频第一个GOP马赛克问题 | | 时间 | 2021/04/22 | | - | 1.备用播放内核模式 增加Seek功能 | | - | 2.备用播放内核模式 兼容yuvj420p | | - | 3.一些其他细节的完善 | | 时间 | 2021/04/12 | | - | 1.修复了默认内核播放 hev错误的问题 | | - | 2.修复了默认内核播放 部分nalu错误的问题 | | - | 3.修复了默认内核播放 部分花屏问题 | | 时间 | 2021/04/07 | | - | 1.时长错误问题 | | 时间 | 2021/03/28 | | - | 1.增加缓冲进度条 | | - | 2.解决了一些Bug,优化了一些性能 | | - | 3.移出HLS播放的无用日志 | | - | 4.增加去音频播放选项(新内核) | | 时间 | 2021/03/14 | | - | 1.备用播放内核模式 | | 时间 | 2021/03/12 | | - | 1.很抱歉,这几天事情交织在一起,有些累,因为我的个人疏忽,导致HLS/M3u8能力不可用,今天已紧急修复. ~_~! 谢谢所有支持h265web的工程师朋友们! | | 时间 | 2021/03/06 | | - | 1.备用播放内核模式,解决多路窗口播放加载失败问题 | | 时间 | 2021/02/28 | | - | 1.开放给H.265解码器喂完整的265nalu帧函数 `append265NaluFrame(nalBuf);` | | - | 2.开放新库,解析h265流为帧数据的工具 [raw-parser.js](./dist/raw-parser.js) | | 时间 | 2021/02/21 | | - | 1.更新底层265解码器SDK项目 - [https://github.com/numberwolf/h265web.js-wasm-decoder](https://github.com/numberwolf/h265web.js-wasm-decoder) | | 时间 | 2021/02/18 | | - | 1.备用播放内核模式,增加音频播放能力 | | 时间 | 2021/02/08 | | - | 1.增加播放内核类型:备用播放内核模式,可兼容多种解码Badcase(测试阶段, 输入媒资Mp4Box需要前置Moov,当前还不支持音频、Seek) | | 时间 | 2021/01/04 | | - | 1.支持H.265的流式接入,可直接以265的URI进行播放、也可以流式字节填充播放(可应用于直播) | | - | 2.取消了播放器自带的播放view蒙板(用于点击播放画面触发暂停/播放能力),开放给用户自行实现 | | - | 3.支持 如果播放器配置的长宽与视频纵横比不匹配,自动裁剪黑边区域 | | - | 4.增加`onPlayFinish` 事件回调,播放结束调用 | | @TODO | 内容 | | ---- | ---- | | 1 | 增加http-flv直播能力 | | 2 | Vue Demo | | 3 | React Demo |
#### 当前能力 #### * 协议 | 协议 | 模式 | 是否支持 | 说明 | | ---- | ---- | ---- | ---- | | mp4 | 点播 | 是 | ---- | | mpeg-ts | 点播 | 是 | ---- | | m3u8 | 点播 | 是 | ---- | | hls | 直播 | 是 | ---- | | H.265 | 点播 | 是 | ---- | | H.265 | 直播 | 是 | ---- | | http-flv | 直播 | 否 | 待支持 | | flv | 点播 | 是 | 备用播放内核模式,不需要填写 | * 能力 | 能力 | 是否支持 | 其他 | | ---- | ---- | ---- | | 直播 | 是 | ---- | ---- | | 点播 | 是 | ---- | ---- | | Seek跳转 | 是 | ---- | ---- | | 精准Seek | 是 | ---- | ---- | | 封面图 | 是 | ---- | ---- | | 边下边播 | 是 | ---- | ---- | | 音量调节 | 是 | ---- | ---- | | 播放 | 是 | ---- | ---- | | 暂停 | 是 | ---- | ---- | | 重新播放 | 是 | ---- | ---- | | 暂停截图 | 是 | ---- | ---- | | 1080p播放 | 是 | ---- | ---- | | 720p播放 | 是 | ---- | ---- | | 多路播放 | 是 | ---- | ---- | | 去音频播放 | 是 | ---- | ---- | | 缓冲进度 | 是 | ---- | ---- |
#### 当前版本的token #### ```javascript token = "base64:QXV0aG9yOmNoYW5neWFubG9uZ3xudW1iZXJ3b2xmLEdpdGh1YjpodHRwczovL2dpdGh1Yi5jb20vbnVtYmVyd29sZixFbWFpbDpwb3JzY2hlZ3QyM0Bmb3htYWlsLmNvbSxRUTo1MzEzNjU4NzIsSG9tZVBhZ2U6aHR0cDovL3h2aWRlby52aWRlbyxEaXNjb3JkOm51bWJlcndvbGYjODY5NCx3ZWNoYXI6bnVtYmVyd29sZjExLEJlaWppbmcsV29ya0luOkJhaWR1"; ```
#### 联系我 #### * Github: https://github.com/numberwolf/h265web.js * Email(porschegt23@foxmail.com) * QQ: 531365872 * QQ技术支持群: 925466059 * Discord:numberwolf#8694 * 微信:numberwolf11
#### 线上demo #### https://www.zzsin.com/h265webjs.html
#### 效果预览 #### | 类型 | 点播 | 直播 | | ---- | ---- | ---- | | 点击
放大 | | |
## 1、快捷方式使用 ## * 使用流程也可以直接看 `play.js`和`index.html`的Demo使用 * 本项目可以直接放在你的`web服务器`目录下访问`index.html`
## 2、播放器SDK使用文档 ## ———————— __API以及事件能力__ #### 如果想使用底层的265解码器能力 可以看 [h265web.js-wasm-decoder](https://github.com/numberwolf/h265web.js-wasm-decoder) ### 安装 ### #### 1)引入包 * 方式1.1:引入Github的本地文件 `require`形式 ```javascript // 引入Github的本地文件 require('./dist/h265webjs'); ``` * 方式1.2:引入Github的本地文件 `import xxx from xxx`形式 (推荐) ```javascript // 引入Github的本地文件 import H265webjsModule from './dist/index'; ```
#### 2)安装Wasm * 从Github下载dist。
#### 3)引入h265web.js到你的项目 * 本地引入(从Github h265web.js) * 1)require形式 ```javascript require('./dist/h265webjs'); ``` * 2)`import xxx from xxx`形式 (推荐) ```javascript // 引入Github的本地文件 import H265webjsModule from './dist/index'; ```
### 播放器配置 ### * 创建代码如下 ```javascript const PLAYER_CORE_TYPE_DEFAULT = 0; // 默认播放器内核 const PLAYER_CORE_TYPE_CNATIVE = 1; // 实验播放器内核 var config = { type: "mp4", player: "glplayer", width: 960, height: 540, accurateSeek : true, token : token, extInfo : { moovStartFlag : true, readyShow : true, rawFps : 30, autoCrop : false, core : PLAYER_CORE_TYPE_DEFAULT } }; ``` * 配置详解 | 配置项 | 类型 | 可选值 | 必填 | 说明 | | ---- | ---- | ---- | ---- | ---- | | type | String | mp4/hls/ts/raw265/flv | 是 | 播放文件的类型 | | player | String | - | 是 | 播放窗口的dom的id值 | | width | Int | - | 是 | 播放窗口的宽度 | | height | Int | - | 是 | 播放窗口的高度 | | accurateSeek | Bool | true/false | 是 | 精准Seek(暂时固定为true) | | token | String | - | 是 | 播放器token值 | | extInfo | Object | - | 否 | 播放器额外配置 | | \+ moovStartFlag | Bool | true/false | 否:默认false | Mp4的moov box是否前置 关联到动态加载 | | \+ readyShow | Bool | true/false | 否:默认false | 是否需要封面图展示 | | \+ rawFps | Float32 | 例如:30 | 否:默认24 | HEVC/AVC裸流播放时候的帧率设定 | | \+ autoCrop | Bool | - | 否:默认false | 如果播放器配置的长宽与视频纵横比不匹配,自动裁剪黑边区域 | | \+ core | Int | - | 否:默认0 | 0:默认播放内核
1:备用播放内核 | | \+ coreProbePart | Float32 | - | 否:默认1.0 | 探测Mp4媒体的属性,百分比 `0.0~1.0`,正常moov前置的文件都用0.1(10%)可以(只适用于备用播放内核) | | \+ ignoreAudio | Int | - | 否:默认0 | 0:带音频播放
1:忽略音频播放 |
### 初始化播放器 ### * 务必注意!!! 请将你整体项目最终编译出来的`JS目标文件` 与 `wasm文件`放置于`同一级目录` * 例如 ```c ./dist/你最终编译产出.js ./dist/missile.wasm ./index.html ``` * 创建方法(全局方法) > new265webjs(`播放地址`, `播放器配置`) | 参数 | 类型 | 默认值 | 必填 | 说明 | | ---- | ---- | ---- | ---- | ---- | | 播放地址 | String | - | 是 | 播放视频地址 | | 播放器配置 | Object | - | 是 | 播放器配置信息 | * 创建示例Demo * 1)路径 + 配置 * 例子1 创建 `mp4/hls/ts`类型播放器 ```javascript let videoURL = "h265_test.mp4"; let config = { type: "mp4", player: "glplayer", width: 960, height: 540, accurateSeek : true, token : token, extInfo : { moovStartFlag : true, readyShow : true } }; ```` * 例子2 创建`raw265`类型 播放h265裸流 播放器(包括直播) ```javascript let config = { type: "raw265", player: "glplayer", width: 960, height: 540, accurateSeek : true, token : token, extInfo : { readyShow : true, rawFps : 30 // 播放帧率 } }; * 例子3 创建`FLV`点播播放器 ```javascript const PLAYER_CORE_TYPE_DEFAULT = 0; // 默认播放器 const PLAYER_CORE_TYPE_CNATIVE = 1; // 备用播放内核 let config = { type: "flv", player: "glplayer", width: 960, height: 540, accurateSeek : true, token : token, extInfo : { moovStartFlag : true, readyShow : true, autoCrop : false, coreProbePart : 0.1, ignoreAudio : 0 } }; ```` * 2)创建播放器 * 1. 以`require('./src/h265webjs');`引入为前提 示例: ```javascript let player = new265webjs(videoURL, config); // 全局方法 ``` * 2. 以`import H265webjsModule from './dist/index';`引入为前提 (推荐) 示例: ```javascript let player = H265webjsModule.createPlayer(videoURL, config); ``` * 3. 如果创建的是`raw265`类型的裸流数据播放 请注意 > 这部分fetch请求网络数据以及异步喂数据的过程 请自行改写,下面给出的仅仅是一个demo,网络IO和解析265流为帧数据会非常耗时。 > > 如果你可以通过websocket直接一帧一帧传输的话,那么只需要调用喂265数据的函数即可。 * `raw265`类型下,喂一帧一帧H.265播放 调用函数 | 函数 | 返回 | 说明 | | ---- | ---- | ---- | | append265NaluFrame | NULL | 喂一帧265数据 | 参数 | 参数 | 类型 | 默认值 | 必填 | 说明 | | ---- | ---- | ---- | ---- | ---- | | frame | Uint8Array | - | 是 | 一帧265数据 | 例子 - 这里直接将265文件通过网络串流传输 ```javascript // // fetch 265 // you can use your code to fetch vod stream // only need `h265webjs.append265NaluFrame(nalBuf);` to append 265 frame // let rawParser = new RawParserModule(); let fetchFinished = false; let startFetch = false; let networkInterval = window.setInterval(() => { if (!startFetch) { startFetch = true; fetch(url265).then(function(response) { let pump = function(reader) { return reader.read().then(function(result) { if (result.done) { // console.log("========== RESULT DONE ==========="); fetchFinished = true; window.clearInterval(networkInterval); networkInterval = null; return; } let chunk = result.value; rawParser.appendStreamRet(chunk); return pump(reader); }); } return pump(response.body.getReader()); }) .catch(function(error) { console.log(error); }); } }, 1); // fps>=30 play else cache let naluParseInterval = window.setInterval(() => { if (nalBuf != false) { // require h265webjs.append265NaluFrame(nalBuf); } else if (fetchFinished) { window.clearInterval(naluParseInterval); naluParseInterval = null; } }, 1); ```
### 播放器相关事件绑定 ### #### 1)Seek完成 > 主要用于SEEK完成做一些操作 * 示例 ```javascript player.onSeekFinish = () => { // todo }; ```
#### 2)YUV帧数据渲染 | 回调参数 | 类型 | 默认值 | 必填 | 说明 | | ---- | ---- | ---- | ---- | ---- | | width | int | - | - | YUV宽度 | | height | int | - | - | YUV高度 | | imageBufferY | Uint8Array | - | - | Y分量 | | imageBufferB | Uint8Array | - | - | ChromaB分量 | | imageBufferR | Uint8Array | - | - | ChromaR分量 | > 可以利用事件回调的YUV做全屏播放 > 需要调用 `setRenderScreen` 函数开启才可以收到事件回调数据, 下方`1.5 API`会说明 * 示例 ```javascript player.onRender = (width, height, imageBufferY, imageBufferB, imageBufferR) => { // todo }; ```
#### 3)媒体文件加载完成事件 > 媒体文件当前加载成功,可以进行播放 * 示例 ```javascript player.onLoadFinish = () => { // todo }; ```
#### 4)播放器当前播放PTS(时刻)更新 | 回调参数 | 类型 | 默认值 | 必填 | 说明 | | ---- | ---- | ---- | ---- | ---- | | videoPTS | float64 | - | - | 当前播放时间 | * 示例 ```javascript player.onPlayTime = (videoPTS) => { // todo console.log(videoPTS) }; ``` #### 5)播放器媒体播放结束事件 * 示例 ```javascript player.onPlayFinish = () => { // finished }; ``` #### 6)播放器缓冲进度回调 | 回调参数 | 类型 | 默认值 | 必填 | 说明 | | ---- | ---- | ---- | ---- | ---- | | cPts | float64 | - | - | 当前缓冲进度时间 | * 示例 ```javascript player.onCacheProcess = (cPts) => { // console.log("onCacheProcess => ", cPts); }; ``` #### 7)播放器封面图加载完成 * 示例 ```javascript player.onReadyShowDone = () => { // console.log("onReadyShowDone"); // to play 封面图加载完成了 }; ```
### 播放器API能力 ### #### 1)加载播放器 > 一般在配置完成【播放器配置】和【事件】之后进行播放器加载 * 示例 ```javascript player.do(); ```
#### 2)获取当前播放状态 | 调用函数 | 返回 | 说明 | | ---- | ---- | ---- | | isPlaying() | bool | 是否正在播放中 | * 示例 ```javascript if (player.isPlaying()) { // 正在播放中 } else { // 当前是暂停状态 } ```
#### 3)开始播放 | 调用函数 | 返回 | 说明 | | ---- | ---- | ---- | | play() | - | 开始播放 | * 示例 ```javascript player.play(); ```
#### 4)暂停播放 | 调用函数 | 返回 | 说明 | | ---- | ---- | ---- | | pause() | - | 暂停播放 | * 示例 ```javascript player.pause(); ```
#### 5)开启/关闭渲染过程中 回调YUV帧数据 > 开启之后,`onRender`事件才可以收到数据 | 调用函数 | 返回 | 说明 | | ---- | ---- | ---- | | setRenderScreen(`{param1}`) | - | 开启/关闭渲染过程中 回调YUV帧数据 | * 参数 | 参数 | 类型 | 默认值 | 说明 | | ---- | ---- | ---- | ---- | | param1 | bool | false | 开启/关闭渲染过程中 回调YUV帧数据 | * 示例 ```javascript // 开启 player.setRenderScreen(true); // 关闭 player.setRenderScreen(false); ```
#### 6)Seek: 跳转到某个时刻 | 调用函数 | 返回 | 说明 | | ---- | ---- | ---- | | seek(`{pts}`) | - | Seek到某一个时刻 | * 参数 | 参数 | 类型 | 默认值 | 说明 | | ---- | ---- | ---- | ---- | | pts | float64 | - | Seek到某一个时刻的时间点 | * 示例 ```javascript // Seek到10.01秒 player.seek(10.01); ```
#### 7)调整音量 > 调整视频的播放音量 | 调用函数 | 返回 | 说明 | | ---- | ---- | ---- | | setVoice(`{volume}`) | - | 调整音量 | * 参数 | 参数 | 类型 | 默认值 | 说明 | | ---- | ---- | ---- | ---- | | volume | float64 | - | 范围区间是`[0, 1.0]`, 0为mute,1.0为全开音量 | * 示例 ```javascript // 音量开启一半 player.setVoice(0.5); ```
#### 8)获取媒资数据 > 获取当前播放的视频文件的信息数据 | 调用函数 | 返回 | 说明 | | ---- | ---- | ---- | | mediaInfo() | Object | 媒资详情 | * 返回值示例 ```json meta: audioNone: false // 是否不包含音频轨 durationMs: 600000 // 时长 毫秒级 fps: 25 // 帧率 sampleRate: 44100 // 音频采样率 size: // 视频分辨率 height: 720 width: 1280 videoCodec: 0 videoType: "vod" // 点播vod 直播live ``` * 示例 ```javascript let mediaInfo = player.mediaInfo(); ```
## 3、其它 ## ### 捐赠 ### | 微信 | 支付宝 | PayPal | | ---- | ---- | ---- | | | | TODO |
### FFmpeg转码265编码的视频 ### * mp4 ```bash ffmpeg -i input.mp4 \ -vcodec libx265 -pix_fmt \ -acodec aac -ac 2 -ar 44100 \ -preset medium -maxrate 1000k -bufsize 1000k \ -vtag hev1 \ -movflags faststart \ -y video.mp4 ``` * hls/m3u8 录屏 ```bash ffmpeg -f avfoundation -i 1:0 \ -q 4 -r 10 \ -filter_complex "scale=1280:720" \ -pix_fmt yuv420p \ -vcodec libx265 \ -ar 22050 -ab 64k -ac 1 -acodec aac \ -threads 4 \ -preset veryfast \ -f segment \ -segment_list test.m3u8 \ -segment_time 5 \ -y /Users/numberwolf/Documents/webroot/VideoMissile/VideoMissilePlayer/res/hls1/v-%03d.ts ``` * mpeg-ts ```bash ffmpeg -ss 20 -t 10 -i ./res/xinxiaomen.mp4 \ -vcodec libx265 -x265-params "bframes=0:keyint=10" -r 24 -filter_complex "scale=720:1280" -preset fast -maxrate 800k -bufsize 800k \ -acodec aac -ar 22050 -ac 1 \ -pix_fmt yuv420p \ -f mpegts -y ./res/veilside2.ts ```