Git Product home page Git Product logo

goldvideo / h265player Goto Github PK

View Code? Open in Web Editor NEW
1.5K 33.0 295.0 145.64 MB

一套完整的Web版H.265播放器解决方案,非常适合学习交流和实际应用。基于JS码流解封装、WebAssembly(FFmpeg)视频解码,利用Canvas画布投影、AudioContext播放音频。

Home Page: https://goldvideo.github.io/h265player/

JavaScript 98.94% CSS 1.06%
h265-payer h265-hevc webassembly yuv-canvas webplayer ffmpeg-player

h265player's Introduction

English英文版

简介

随着视频编码技术的发展,相比H.264, H.265同等画质体积仅为一半、带宽占用省一半、画质更细腻等诸多优势。 但Web浏览器还不支持H.265的解码播放,因此基于Web Assembly(封装FFmpeg)、JS解封装、Canvas投影以及AudioContext实现Web端的H265播放。

支持主要浏览器及其版本如下:
Chrome(>57) Safari (>11) Firefox (>52)

本项目是一个公开的基础可用版本,并不含有具体的业务代码。业务可基于此项目进行具体业务实现。

安装与测试

下载源码

# 创建根目录
* mkdir goldvideo
* cd goldvideo
# 下载h265player源码, 创建h265player目录
* git clone https://github.com/goldvideo/h265player.git
* cd h265player
# 安装依赖
* npm install

工程打包

# 以下打包命令任选一
* npm run dev    # 运行开发环境
* npm run test   # 运行测试环境
* npm run build  # 打包正式环境
* rollup -c      # 打包csj与esm版本

Nginx配置(或者其他Server)

server {
    listen       8000;
    location / {
        root   <path of goldvideo>/goldvideo;
        index  index.html index.htm;
        autoindex on;
    }
}

测试页面

重启nginx并访问demo地址,就能看到播放器画面,如果可以能正常播放视频时就表示成功了。 http://localhost:8000/h265player/demo/demo.html

如果遇到错误,请通过检查路径配置以及资源是否加载完成等。您也可以给我们留言反馈问题,我们将尽快回复。

以上就完成了基本安装,想了解更多详情,可以接着往下看。

安装NPM包,参照example快速运行例子[可选]

npm version Downloads

# 可以直接npm安装构建后的文件,快速运行DEMO
* npm i goldvideo-player

具体参见 goldvideo example

源码安装解封装库demuxer[可选]

下载 demuxer 库源码 或者 从 npm 安装 (https://www.npmjs.com/package/demuxer)

* cd goldvideo
* git clone https://github.com/goldvideo/demuxer.git
* cd demuxer
* npm install
# 打包模块,详情请查看demuxer项目里面的package.json文件
* npm install --global rollup
# 构建demuxer模块
* rollup -c ./rollup.config.js --environment BUILD_MODE:production
* cd h265player
# 从本地安装demuxer,调用本地构建的库
* npm install ../demuxer

源码编译WASM解码库[可选]

decoder_wasm库之前已经编译并复制到 h265player/dist/lib/目录下。你也可以自己编译并替换libffmpeg.js与libffmpeg.wasm文件。

# 如果想看源码和编译过程,可以查看decoder_wasm模块源码。
* cd goldvideo
* git clone http://github.com/goldvideo/decoder_wasm.git
* cd decoder_wasm

wasm安装略微复杂,详细查看README文件

主要模块结构

源码目录结构

├─goldvideo
│  ├─demuxer
│  ├─h265player
│  ├─decoder_wasm
│  ├─example

整体架构图

播放器主要分为UI、Loader、数据处理、数据渲染四个部分和3个线程。一个是主线程,包括界面控制、下载控制、数据流控制、音视频控制等功能;数据加载线程,完成元数据和数据片段的请求;数据处理线程,完成数据解封装和解码。

  • UI:播放器显示成,包括screen和controlbar两部分,screen包括视频图像展示、弹窗、海报图等。controlbar包括进度条、播放按钮、音量控制等组件。
  • Loader:负责媒体数据的加载和解析,目前仅支持HLS协议。通过worker实现数据的请求,加载完成后,根据设置缓存大小,存储请求的ts数据,当达到缓存上限后停止加载。解码器从ts数据队列获取ts后,Hls Loader会把请求过的ts释放,继续加载下一个ts,达到最大缓存限制后停止加载
  • 数据处理:主要包括数据解封装和H265解码,解封装通过demuxe.js这个类库实现,H265解码通过ffmpeg打包生成的wasm软解来实现,cpu使用率较高。
  • 数据渲染:包括视屏渲染和音频渲染,视频渲染通过ImagePlayer把解码后的yuv数据直接渲染到canvas,音频通过AudioPlayer把AAC数据解码后进行音频播放,最后通过pts实现音视频的同步。同步策略是以音频为参考,判断当前视频pts与获取到的音频pts的差值来调整视频显示时间来达到音视频同步。

流程图

播放器主要流程如下图所示:

具体流程如下:

解封装器

通过JS实现了视频数据的解封装,从而获取到独立的视频(H265)数据和音频(AAC)数据。详细信息请参考demuxer模块:https://github.com/goldvideo/demuxer

解码器

通过ffmpeg实现H265数据的软解码,如果要在浏览器中调用ffmpeg,需要把ffmpeg编译成wasm进行调用,具体ffmpeg编译成wasm过程,可参考decoder_wasm

ImagePlayer

通过yuv-canvas实现YUV数据渲染,ImagePlayer中会有一个队列存储YUV数据,并计算当前yuv数据的时间长度,大于等于readybufferLength的值时,会触发ImagePlayerReady事件。当音视频播放器都处于ready状态时,H265播放器触发dataReady事件,开始调用play方法进行视频播放。

AudioPlayer

Audio Player 

Web Audio API

Audio Player的实现基于Web Audio API, 包括AAC音频流的解码与PCM数据的播放。  

  • 解码:Audio Player模块接收解封装模块发过来的AAC数据流,通过AudioContext的decodeAudioData API,解码为待后续播放的PCM数据。
  • 音频节点:音频节点(AudioNode)是Web Audio API中的音频数据"处理器",Web Audio API通过不同“处理器”对音频数据做串行处理,最终通过扬声器(audioContext.destination)播放。
    • ScriptProcessorNode:音频源节点。Web Audio API提供多种音频源节点以提供音频数据,如AudioBufferSourceNode, MediaElementAudioSourceNode等。考虑到倍速播放的需求,我们用的是ScriptProcessorNode, 通过onaudioprocess回调函数请求音频数据。
    • GainNode:音量控制节点。

倍速播放

Audio Context的部分音频节点提供了playbackRate属性以实现倍速播放的功能,但是音频在倍速播放的同时,音频的音调(pitch)也同步地升高/降低。
为实现变速不变调,项目中,我们使用了一个音频数据处理库SoundTouchJS,将处理过的变速不变调的音频数据提供给ScriptProcessorNode。

快速开始

在head标签中添加如下代码

<link rel="stylesheet" href="../dist/goldplay-h265.css">
<script src="../dist/goldplay-h265-sdk.js"></script>
<style>
    .play-container {
        width: 800px;
        height: 500px;
    }
</style>

创建一个div,作为播放器的容器

<div class="play-container"></div>

新建一个GoldPlay实例对象,传入相应参数,就可以实现视频的播放

//播放器容器
let el = doc.querySelector('.play-container')
//播放器参数
let options = {
    // 视频播放地址
    sourceURL: 'http://localhost:8000/h265player/data/video2/playlist.m3u8',
    type: 'HLS'
    // wasm库地址
    libPath: 'http://localhost:8000/h265player/dist/lib',
}
let player = new GoldPlay(el, options}

在线demo

https://omc3i.codesandbox.io/

组件扩展

如何扩展UI组件请参考文档 组件添加componentadd

API

https://goldvideo.github.io/h265player/API/index.html

开发与维护

h265player's People

Contributors

ashleyshar avatar jarry avatar snxly avatar yiwen03 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

h265player's Issues

GOLDPLAY ERROR:default-1001

ThrowError.js?80b6:64 Error: [GOLDPLAY ERROR:default-1001
1605768774842
]0
at ThrowError.throws (ThrowError.js?80b6:61)
at HLSLoader.eval (Player.js?66d6:305)
at eval (Events.js?a0fd:81)
at Array.forEach ()
at Events.emit (Events.js?a0fd:80)
at HLSLoader.parsePlaylist (HLSLoader.js?816b:75)
at Worker.httpWorker.onmessage (HLSLoader.js?816b:64) "[message]:" "0" "[args]:" (3) ["Parse playlist error.", "data:", M3U8Parser]

And m3u8 Return

#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=10119000
https://play.dtpcshow.com/live/8k.m3u8?wsSession=3b4060b548867528148ded20-160576873898472&wsIPSercert=3a6bf241b77ab87173cfbcc003bd3b3e&wsMonitor=0

可以支持rtmp流吗?

博主你好,想问下该播放器可以支持rtmp流吗,支持h.265/h.264编码
推流端:走的rtmp协议,推送h.264/h.265裸流到 srs/nginx-rtmp-server 服务器
拉流端:用你的播放器可以支持rtmp流吗?
小白刚入行

时序问题导致视频卡顿

// src/ImageData.js
isBuffered(time) {
  return time >= this.start && time < this.end
}

请问有时候time < this.end为false,导致find函数找不到image,最后结果是视频卡顿,是因为最后几帧丢失了吗?请问怎么解决,谢谢~
image

npm run dev 出错

请问下最新的node版本install,会不会有问题,我用的windows环境node12.18.3的版本,intall没有报错,但是npm run dev后出现下面的情况:
Error: No files matching the pattern "D:\work\h265player-master\src\themes***.css" were found.
at D:\work\h265player-master\node_modules\stylelint\lib\standalone.js:214:12
at processTicksAndRejections (internal/process/task_queues.js:97:5)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] dev: webpack --config build/webpack.dev.conf.js --watch --display-error-details
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] dev script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\lty\AppData\Roaming\npm-cache_logs\2020-09-12T09_31_46_411Z-debug.log

不知道什么原因造成的,好像还是少了什么依赖

Unable to play H265 video without audio

I am unable to play HEVC files (HLS) without audio track. Player doesnt load - timeline shows proper duration.
If i add a AAC track to same video without reeencoding - it will play well.
Also - 4K HEVC files are not playable - i dont care about smooth playback.

直播视频卡顿

第一个m3u8的ts切片播放完,播第二个m3u8的ts切片时候会开始卡顿。看log好像是没播放完就开始加载下一个ts,正常是3s加载一次,为什么现在是1s加载一次?是这个原因导致卡顿吗?请教一下,非常感谢!
image

m3u8重复加载

Hi yanlong,
如何达到重复加载m3u8,获取最新的ts,已达到播放实时视频流嘛
尝试在 Events.DecodeFlushEnd 中调用 LoaderController 中的 loadPlaylist 方法,但效果不太理想~

你好,运行时出错,提示Error: No files matching the pattern "E:\goldvideo\h265player\src\themes\**\*.css" were found. at E:\goldvideo\h265player\node_modules\stylelint\lib\standalone.js:212:12 at processTicksAndRejections (internal/process/task_queues.js:93:5)

image
Error: No files matching the pattern "E:\goldvideo\h265player\src\themes***.css" were found.
at E:\goldvideo\h265player\node_modules\stylelint\lib\standalone.js:212:12
at processTicksAndRejections (internal/process/task_queues.js:93:5)

npm run test出错

npm ERR! path /web/goldvideo/h265player
npm ERR! command failed
npm ERR! command sh -c webpack --config build/webpack.test.conf.js

播放暂停的时候,httpworker 有没有办法停止,播放的时候重新请求url。

我在做hls方案的时候:需要这样的功能:播放暂停的时候,想让:httpworker 停止,播放的时候重新请求url。
内存溢出复现:暂停后,httpworker 还在不停的请求数据。。。
看遍全代码,没有 stop这个功能。 pause:暂停只是相对于点播是没问题的。
如果hls直播的话,重新链接播放,stop就直接关闭下载了。
同类播放器:easyplayer.js这个东西就是这么干的。
我现在困扰的东西就是这个 httpwork 。。。
image

怎么运行

我下载了源码,要怎么运行才能看到效果呢。
我执行 npm run test和npm run dev都没看到效果。

版主您好:请问支持HLS 直播需要从哪个模块进行修改呢?

我看了下issues, 其中很多人和我一样,都有hls hevc 直播的需求。请问要修改哪些地方才能实现此功能呢?

hls.js 中是将ts 转mp4进行播放,在goldvideo 应该不需要此步骤了吧

是否只需要添加 playlist,loader 呢?等等,如果版主有设计好的框架么,剩下的交给大家来做

请问怎么调用播放器的 destroy 方法?

按 demo 中的 new 了 GoldPlay 实例后,调用 destroy 方法会报错

Uncaught TypeError: Cannot read property 'destroy' of undefined

代码:

let el = document.querySelector(".play-container");
let options = {
  sourceURL: "https://omc3i.codesandbox.io/ts/playlist.m3u8",
  libPath: "https://omc3i.codesandbox.io/ts/playlist.m3u8"
};
let player = new GoldPlay(el, options);

player.destroy()

是我调用的方法不对吗?

goldplay-h265-sdk.js Uncaught TypeError: this.segmentPool.addAll is not a function

goldplay-h265-sdk js
when into onmessage, this.segmentPool got changed from t[ ] to [ ], which cause an obvious error when SegmentPool's member function addAll is called. Anybody can tell why? Is this a bug?

source code is around src/loader/HLSLoader.js L44~L67, as follow:

  loadPlaylist(callback) {
    this.httpWorker.postMessage({
      type: 'invoke',
      fileType: 'm3u8',
      method: 'get',
      name: 'playlist',
      url: this.sourceURL
    })
    this.httpWorker.onmessage = (event) => {
      const data = event.data
      const body = event.data.data
      if (!body) {
        const content = `Get the ${data.fileType} file error. URL: ${data.url}`
        this.events.emit(Events.PlayerAlert, content)
        this.events.emit(Events.LoaderError, content, data)
        const errors = [this.state, 'request playlist error.', 'data:', data, content]
        this.events.emit(Events.PlayerThrowError, errors)
        return
      }
      if (data.name == 'playlist') {
        this.parsePlaylist(body, callback)
      }
    }
  }

The scene of error being caught is around src/loader/HLSLoader.js L69~L87, as follow:

parsePlaylist(source, callback) {
    const data = new M3U8Parser(source)
    if (!data.segments || !data.segments.length) {
      this.events.emit(Events.LoaderError, data)
      this.events.emit(Events.PlayerAlert, 'Parse playlist file error.')
      const errors = [this.state, 'Parse playlist error.', 'data:', data]
      this.events.emit(Events.PlayerThrowError, errors)
      return
    }
    let segments = data.segments
    segments.forEach(item => {
      item.start = Utils.msec2sec(item.start)
      item.end = Utils.msec2sec(item.end)
      item.duration = Utils.msec2sec(item.duration)
    })
    this.setSourceData(Object.freeze(data))
    this.segmentPool.addAll(data.segments)
    callback.call(this, data)
  }

作者 你好 请问一下 我看到别的类似的wasm 播放器 都是把比如flv,MP4相关的解码全部放到ffmpeg层编译成二进制字节码。但是你这个项目是把ts用js解析到h264才塞给ffmpeg。这样做有什么好处吗?

作者 你好 请问一下 我看到别的类似的wasm 播放器 都是把比如flv,MP4相关的解码全部放到ffmpeg层编译成二进制字节码。但是你这个项目是把ts用js解析到h264才塞给ffmpeg。这样做有什么好处吗?

H264、H265

后续是否支持H265、H265的文件点播呢?MP4格式的

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.