# 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
```