Code Monkey home page Code Monkey logo

wasmvideoplayer's Introduction

@[TOC](基于WASM的H265 Web播放器)

1 背景

目前这个时间点,原生支持H265(HEVC)播放的浏览器极少,可以说基本没有,主要原因一个是H265的解码有更高的性能要求,从而换取更高的压缩率,目前大多数机器CPU软解H265的超清视频还是有点吃力,硬解兼容性又不好,另外一个原因主要是H265的专利费问题。因此H265有被各大浏览器厂商放弃的趋势,转而去支持更加开放的AV1编码,但是AV1编码的商用和普及估计还有段时间。

H265与H264相比主要的好处在于相同分辨率下降低了几乎一倍的码率,对带宽压力比较大的网站来说,使用H265可以极大削减带宽消耗(尽管可能面临专利费麻烦),但是由于浏览器的支持问题,目前H265的播放主要在APP端实现,借助硬件解码,可以获得比较好的性能和体验。

本文相关的代码使用WASM、FFmpeg、WebGL、Web Audio等组件实现了一个简易的支持H265的Web播放器,作为探索、验证,just for fun。

2 代码

github地址: https://github.com/sonysuqin/WasmVideoPlayer.

3 依赖

3.1 WASM

WASM的介绍在这里,可以在浏览器里执行原生代码(例如C、C++),要开发可以在浏览器运行的原生代码,需要安装他的工具链,我使用的是目前最新的版本(1.39.5)。编译环境有Ubuntu、MacOS等,这里有介绍。

3.2 FFmpeg

主要使用FFmpeg来做解封装(demux)和解码(decoder),由于使用了FFmpeg(3.3),理论上可以播放绝大多数格式的视频,这里只针对H265编码、MP4封装,在编译时可以只按需编译最少的模块,从而得到比较小的库。

使用Emscripten编译FFmpeg主要参考下面这个网页,做了一些修改: https://blog.csdn.net/Jacob_job/article/details/79434207

3.3 WebGL

H5使用Canvas来绘图,但是默认的2d模式只能绘制RGB格式,使用FFmpeg解码出来的视频数据是YUV格式,想要渲染出来需要进行颜色空间转换,可以使用FFmpeg的libswscale模块进行转换,为了提升性能,这里使用了WebGL来硬件加速,主要参考了这个项目,做了一些修改: https://github.com/p4prasoon/YUV-Webgl-Video-Player

3.4 Web Audio

FFmpeg解码出来的音频数据是PCM格式,可以使用H5的Web Audio Api来播放,主要参考了这个项目,做了一些修改: https://github.com/samirkumardas/pcm-player

4 播放器实现

这里只是简单实现了播放器的部分功能,包括下载、解封装、解码、渲染、音视频同步等基本功能,每个环节还有很多细节可以优化。目前可以支持FFmpeg的各种内置codec,如H264/H265等,默认支持MP4/FLV文件播放、HTTP-FLV流的播放。

4.1 模块结构

在这里插入图片描述

4.2 线程模型

理论上来说,播放器应该使用这样的线程模型,各个模块在各自线程各司其职: 在这里插入图片描述 但是WASM目前对多线程(pthread)的支持不够好,各个浏览器的WASM多线程支持还处于试验阶段,因此现在最好不要在原生代码里编写pthread的代码。这里使用了Web Worker,把下载和对FFmpeg的调用放到单独的线程中去。

主要有三个线程:

  • 主线程(Player):界面控制、播放控制、下载控制、音视频渲染、音视频同步;
  • 解码线程(Decoder Worker):音视频数据的解封装、解码;
  • 下载线程(Downloader Worker):下载某个chunk。 线程之间通过postMessage进行异步通信,在需要传输大量数据(例如视频帧)的地方,需要使用Transferable接口来传输,避免大数据的拷贝损耗性能。

4.3 Player

4.3.1 接口

  • play:开始播放;
  • pause:暂停播放;
  • resume:恢复播放;
  • stop:停止播放;
  • fullscreen:全屏播放;
  • seek:seek播放未实现。

4.3.2 下载控制

为防止播放器无限制地下载文件,在下载操作中占用过多的CPU,浪费过多带宽,这里在获取到文件码率之后,以码率一定倍数的速率下载文件。

4.3.3 缓冲控制

缓存控制对这个播放器的意义重大,在这个时间点,WASM还无法使用多线程以及多线程的同步,FFmpeg的同步读数据接口必须保证返回数据。所以这里有两个措施,1:在未获取到文件元信息之前的数据缓存;2:解码帧缓存。必须控制好这两个缓存,才能保证任何时候FFmpeg需要读取数据时都能够返回数据,在数据不足时停止解码,进入Buffer状态,数据足够时继续解码播放,返回Play状态,保证FFmpeg不会报错退出播放。

4.3.4 音视频同步

音频数据直接喂给Web Audio,通过Web Audio的Api可以获得当前播放的音频的时间戳,以该时间戳为时间基准来同步视频帧,如果当前视频帧的时间已经落后则立刻渲染,如果比较早,则需要delay。 在H5里delay可以通过setTimeout实现(还未找到更好的方式),上面做缓冲控制的另外一个意义在于控制视频的渲染频率,如果调用setTimeout的视频帧太多,内存会暴涨。

4.3.5 渲染

简单地将PCM数据交给PCM Player,YUV数据交给WebGL Player。

4.4 Downloader

这个模块很简单,只是单纯为了不在主线程做太多事情而分离,功能主要有:

  • 通过Content-Length字段获取文件的长度;
  • 通过Range字段下载一个chunk。

如上面提到的,Player会进行速率控制,因此需要把文件分成chunk,按照chunk方式进行下载。下载的数据先发给Player,由Player转交给Decoder(理论上应该直接交给Decoder,但是Downloader无法直接与Decoder通信)。 对流式的数据,则使用Fetch

4.5 Decoder

这个模块需要加载原生代码生成的胶水代码(glue code),胶水代码会加载wasm。

self.importScripts("libffmpeg.js");

4.5.1 接口

  • initDecoder:初始化解码器,开辟文件缓存;
  • uninitDecoder:反初始化解码器;
  • openDecoder:打开解码器,获取文件信息;
  • closeDecoder:关闭解码器;
  • startDecoding:开始解码;
  • pauseDecoding:暂停解码。

这些方法都由Player模块通过postMessage异步调用。

4.5.2 缓存

这里简单使用了WASM的MEMFS文件接口(WASM的文件系统参考),使用方式就是直接调用stdio的方法,然后在emcc的编译命令中加入编译选项:

-s FORCE_FILESYSTEM=1 

MEMFS会在内存中虚拟一个文件系统,Decoder收到Player发过来的文件数据直接写入缓存,由解码任务读取缓存。 对流式的数据,则使用FFmpeg的环形缓存FIFO。

4.5.3 解码

  • 播放开始后不能立刻打开解码器,因为FFmpeg探测数据格式需要一定的数据长度(例如MP4头的长度);
  • 缓存的数据足够后Player打开解码器,会得到音频的参数(通道数、采样率、采样大小、数据格式),视频的参数(分辨率,duration、颜色空间),以这些参数来初始化渲染器、界面;
  • Player调用startDecoding会启动一个定时器执行解码任务,以一定的速率开始解码;
  • Player缓存满后会调用pauseDecoding暂停解码器。

4.5.4 数据交互

解码后的数据直接通过Transferable Objects postMessage给Player,这样传递的是引用,不需要拷贝数据,提高了性能。

Javascript与C的数据交互:

发送:
……
this.cacheBuffer = Module._malloc(chunkSize);
……
Decoder.prototype.sendData = function (data) {
    var typedArray = new Uint8Array(data);
    Module.HEAPU8.set(typedArray, this.cacheBuffer); //拷贝
    Module._sendData(this.cacheBuffer, typedArray.length); //传递
};

接收:
this.videoCallback = Module.addFunction(function (buff, size, timestamp) {
    var outArray = Module.HEAPU8.subarray(buff, buff + size); //拷贝
    var data = new Uint8Array(outArray);
    var objData = {
        t: kVideoFrame,
        s: timestamp,
        d: data
    };
    self.postMessage(objData, [objData.d.buffer]); //发送给Player
});
需要把回调通过openDecoder方法传入C层,在C层调用。

5 编译

5.1 安装Emscripten

参考其官方文档

5.2 下载FFmpeg

git clone https://git.ffmpeg.org/ffmpeg.git

这里切到了3.3分支。

5.3 下载本文的代码

保证FFmpeg目录和代码目录平级。

git clone https://github.com/sonysuqin/WasmVideoPlayer.git

5.4 编译

进入代码目录,执行:

./build_decoder.sh

6 测试

可以使用任意的Http Server(Apache、Nginx等),例如: 如果安装了node/npm/http-server,则在代码目录下执行:

http-server -p 8080 .

在浏览器输入即可:

http://127.0.0.1:8080

Demo地址:播放

7 浏览器支持

目前(20190207)没有做太多严格的浏览器兼容性测试,主要在Chrome上开发,以下浏览器比较新的版本都可以运行:

  • Chrome(360浏览器、搜狗浏览器等webkit内核也支持);
  • Firefox;
  • Edge。

8 主要问题

  • 解码、播放H265的CPU占用相对来说较高;
  • 如果不及时传递音频数据,AudioContext的currentTime不做控制可能会导致音视频不同步。

wasmvideoplayer's People

Contributors

snadn avatar sonysuqin 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wasmvideoplayer's Issues

decoder.js中的openDecoder参数问题

moov atom not found问题导致了openDecoder函数返回了8。我对视频方面的知识了解的不是很多,我想问一下Decoder.openDecoder中的paramCount和paramSize是什么意思?这两个参数一定要写死吗?

How to process HEVC data received from camera's RTSP stream

I am trying to send HEVC data received from camera to decoder using sendData API. But, avformat_open_input API failed with error code 8 i.e. "No error information".
Following are the logs printed on console,

Wasm loaded.
libffmpeg.js:1 decoder->isStream 1.
libffmpeg.js:1 Decoder initialized 0.
libffmpeg.js:90 initDecoder return 0.
libffmpeg.js:1 Opening decoder.
libffmpeg.js:1 avformat_open_input failed 8 No error information.
libffmpeg.js:105 openDecoder return 8

为什么使用 canvas 进行渲染

请教一下,为什么项目中视频画面的绘制是通过 canvas 来做,而不是将数据转换成浏览器支持的格式(如 H.264),然后喂给 <video> 进行播放?

视频音频播放不同步如何调整?

播放过程中 音频会滞后视频,看到文章里提到过是因为内存过高导致,请问如何有办法调整同步吗?如果有的话,如何调整?

How to build h264

Hi @sonysuqin, Thanks for the wonderful repo

Here in this repo you builded the hevc type of video decoder.js. The same i need to build h264 codec support decoder.js. That is very useful for my project.

I tried to build the h264 codec support on edit the file (https://github.com/sonysuqin/WasmVideoPlayer/blob/master/build_decoder.sh) with --enable-demuxer = mov,mp4. But that will be not working for me.

So kindly let know me how to build the h264 decoder.js with latest ffmpeg version.

Thanks in advance...

播放flv直播流遇到的问题

你好,我使用ffmpeg命令将视频流推到rtmp服务器上,推流命令如下:
ffmpeg -stream_loop -1 -re -i xxx.flv -c copy -f flv rtmp://xxx/live/12345
然后讲rtmp转成了http-flv转发出去,直播地址为:https://xxxx.com/live/12345
因为直接用xhr播放直播流会有跨域问题,下载这一部分我改了一下,并且申请的cacheBuffer也根据下载到的文件块的大小进行了适配,改了以后播放本地文件是没问题的。
但是播放直播流的时候出现了点问题,我在尝试播放直播流的时候,虽然openDecoder返回了0,但是chrome的控制台提示了“libffmpeg.js:1 [flv @ 0x627f70] Could not find codec parameters for stream 0 (Video: h264, none): unspecified size” 和“libffmpeg.js:1 Consider increasing the value for the 'analyzeduration' and 'probesize' options”的提示,截图如下:
image
image

并且返回的媒体元信息的7个参数也不太正常,截图如下:
image

可能是因为返回7个媒体元数据参数的不正常,导致了后面在解码的时候提示“[flv @ 0x627f70] Packet mismatch -1665408982 11 84234”
image

如何播放裸流 (H265)?

目前测试可以通过 ffmpeg -i video.265 -vcodec copy -f mp4 output.mp4 转换成mp4并通过VLC播放。但生成的 output.mp4 以及 video.265 我未找到方法播放

video.zip

使用这个项目"sh ./build_decoder_wasm.sh"遇到一个 tools.shared.Py2CalledProcessError 的异常

有朋友遇到,或了解怎么解决吗?

异常信息如下:

Running Emscripten...
cache:INFO: generating system asset: is_vanilla.txt... (this will be cached in "/Users/myname/.emscripten_cache/is_vanilla.txt" for subsequent builds)
cache:INFO: - ok
decoder.c:635:24: warning: 'avpicture_get_size' is deprecated [-Wdeprecated-declarations]
decoder->videoSize = avpicture_get_size(
^
dist/include/libavcodec/avcodec.h:5560:1: note: 'avpicture_get_size' has been explicitly marked deprecated here
attribute_deprecated
^
dist/include/libavutil/attributes.h:94:49: note: expanded from macro 'attribute_deprecated'
define attribute_deprecated attribute((deprecated))
^
1 warning generated.
cache:INFO: generating system library: libc.bc... (this will be cached in "/Users/myname/.emscripten_cache/asmjs/libc.bc" for subsequent builds)
cache:INFO: - ok
cache:INFO: generating system library: libcompiler_rt.bc... (this will be cached in "/Users/myname/.emscripten_cache/asmjs/libcompiler_rt.bc" for subsequent builds)
cache:INFO: - ok
cache:INFO: generating system library: libc-wasm.bc... (this will be cached in "/Users/myname/.emscripten_cache/asmjs/libc-wasm.bc" for subsequent builds)
cache:INFO: - ok
cache:INFO: generating system library: libc-extras.bc... (this will be cached in "/Users/myname/.emscripten_cache/asmjs/libc-extras.bc" for subsequent builds)
cache:INFO: - ok
cache:INFO: generating system library: libdlmalloc.bc... (this will be cached in "/Users/myname/.emscripten_cache/asmjs/libdlmalloc.bc" for subsequent builds)
cache:INFO: - ok
cache:INFO: generating system library: libpthreads_stub.bc... (this will be cached in "/Users/myname/.emscripten_cache/asmjs/libpthreads_stub.bc" for subsequent builds)
cache:INFO: - ok
Traceback (most recent call last):
File "/Users/myname/work/emsdk/fastcomp/emscripten/emcc.py", line 3440, in
sys.exit(run(sys.argv))
File "/Users/myname/work/emsdk/fastcomp/emscripten/emcc.py", line 1929, in run
final = shared.Building.link(linker_inputs, DEFAULT_FINAL, force_archive_contents=force_archive_contents, just_calculate=just_calculate)
File "/Users/myname/work/emsdk/fastcomp/emscripten/tools/shared.py", line 1978, in link
Building.read_link_inputs([x for x in files if not x.startswith('-')])
File "/Users/myname/work/emsdk/fastcomp/emscripten/tools/shared.py", line 1757, in read_link_inputs
object_names_in_archives = pool.map(extract_archive_contents, archive_names)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 251, in map
return self.map_async(func, iterable, chunksize).get()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 567, in get
raise self._value
tools.shared.Py2CalledProcessError: Command '['/Users/myname/work/emsdk/fastcomp/fastcomp/bin/llvm-ar', 'xo', '/Users/myname/work/WasmVideoPlayer-master/dist/lib/libavformat.a']' returned non-zero exit status -9
Finished Build

手机 ios13 safari浏览器http-flv 播放不出来

手机 ios13 safari 浏览器http-flv 播放不出来,控制台日志并没有错误。请问有什么解决办法?
电脑chrome下播放没问题
日志如下:

[Log] [2020-3-18 21:35:44:730][Decoder][IF] Wasm loaded. (common.js, line 62)
[Log] [2020-3-18 21:35:58:223][Player][IF] Play http://1011.hlsplay.aodianyun.com/demo/game.flv (common.js, line 62)
[Log] [2020-3-18 21:35:58:277][Player][IF] Got file size rsp:200 size:-1 byte. (common.js, line 62)
[Log] [2020-3-18 21:35:58:277][Player][IF] Initializing decoder. (common.js, line 62)
[Log] [2020-3-18 21:35:58.278][Core][DT] Decoder initialized 0. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:35:58:284][Decoder][IF] initDecoder return 0. (common.js, line 62)
[Log] [2020-3-18 21:35:58:295][Player][IF] Init decoder response 0. (common.js, line 62)
[Log] [2020-3-18 21:36:5:349][Player][IF] Opening decoder. (common.js, line 62)
[Log] [2020-3-18 21:36:5.350][Core][DT] Opening decoder. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:36:5.357][Core][DT] avformat_open_input success. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:36:5.424][Core][DT] avformat_find_stream_info success. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:36:5.425][Core][DT] Open video codec context success, video stream index 1 dca180. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:36:5.425][Core][DT] Video stream index:1 pix_fmt:0 resolution:1280720. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:36:5.426][Core][DT] Open audio codec context success, audio stream index 0 a42c90. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:36:5.436][Core][DT] Audio stream index:0 sample_fmt:8 channel:2, sample rate:44100. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:36:5.438][Core][DT] Decoder opened, duration 5s, picture size 1382400. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:36:5:439][Decoder][IF] openDecoder return 0 (common.js, line 62)
[Log] [2020-3-18 21:36:5:440][Player][IF] Open decoder response 0. (common.js, line 62)
[Log] [2020-3-18 21:36:5:441][Player][IF] Video param duation:5 pixFmt:0 width:1280 height:720. (common.js, line 62)
[Log] [2020-3-18 21:36:5:441][Player][IF] Seek wait len -400 (common.js, line 62)
[Log] [2020-3-18 21:36:5:441][Player][IF] Byte rate:-200 target speed:-400 chunk interval:-163840. (common.js, line 62)
[Log] [2020-3-18 21:36:5:441][Player][IF] Audio param sampleFmt:3 channels:2 sampleRate:44100. (common.js, line 62)
[Log] [2020-3-18 21:36:5:441][Player][IF] Audio encoding 32bitFloat. (common.js, line 62)
[Log] [2020-3-18 21:36:5:542][Player][IF] Decoder ready now. (common.js, line 62)
[Log] [2020-3-18 21:36:5.551][Core][DT] Initial PCM buffer size 131072. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:36:14.649][Core][DT] Fifo size growed to 2097152. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:36:26.191][Core][DT] Fifo size growed to 4194304. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:36:50.112][Core][DT] Fifo size growed to 8388608. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:37:37.56][Core][DT] Fifo size growed to 16777216. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:37:37.57][Core][DT] [Warn] Fifo size larger than 16777216. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:38:49:79][Player][IF] Stop in stream pause. (common.js, line 62)
[Log] [2020-3-18 21:38:54:659][Player][IF] Stop. (common.js, line 62)
[Log] [2020-3-18 21:38:54:660][Player][IF] Pcm player released. (common.js, line 62)
[Log] [2020-3-18 21:38:54:661][Player][IF] Closing decoder. (common.js, line 62)
[Log] [2020-3-18 21:38:54:661][Player][IF] Uniniting decoder. (common.js, line 62)
[Log] [2020-3-18 21:38:54:663][Decoder][IF] closeDecoder. (common.js, line 62)
[Log] [2020-3-18 21:38:54.665][Core][DT] Video codec context closed. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:38:54.665][Core][DT] Audio codec context closed. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:38:54.667][Core][DT] IO context released. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:38:54.669][Core][DT] Input closed. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:38:54.669][Core][DT] All buffer released. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:38:54:692][Decoder][IF] Close ffmpeg decoder return 0. (common.js, line 62)
[Log] [2020-3-18 21:38:54.693][Core][DT] Decoder uninitialized. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:38:54:693][Decoder][IF] Uninit ffmpeg decoder return 0. (common.js, line 62)
[Log] [2020-3-18 21:38:54:774][Player][IF] Play in stream resume. (common.js, line 62)
[Log] [2020-3-18 21:38:54:774][Player][IF] Play http://183.47.13.164:1971/live/test.flv. (common.js, line 62)
[Log] [2020-3-18 21:38:54:783][Player][IF] Got file size rsp:200 size:-1 byte. (common.js, line 62)
[Log] [2020-3-18 21:38:54:783][Player][IF] Initializing decoder. (common.js, line 62)
[Log] [2020-3-18 21:38:54.783][Core][DT] Decoder initialized 0. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:38:54:784][Decoder][IF] initDecoder return 0. (common.js, line 62)
[Log] [2020-3-18 21:38:54:799][Player][IF] Init decoder response 0. (common.js, line 62)
[Log] [2020-3-18 21:39:1:432][Player][IF] Opening decoder. (common.js, line 62)
[Log] [2020-3-18 21:39:1.433][Core][DT] Opening decoder. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:1.437][Core][DT] avformat_open_input success. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:1.502][Core][DT] avformat_find_stream_info success. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:1.503][Core][DT] Open video codec context success, video stream index 1 dd0e60. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:1.503][Core][DT] Video stream index:1 pix_fmt:0 resolution:1280
720. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:1.503][Core][DT] Open audio codec context success, audio stream index 0 9fe6e0. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:1.504][Core][DT] Audio stream index:0 sample_fmt:8 channel:2, sample rate:44100. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:1.506][Core][DT] Decoder opened, duration 5s, picture size 1382400. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:1:507][Decoder][IF] openDecoder return 0 (common.js, line 62)
[Log] [2020-3-18 21:39:1:508][Player][IF] Open decoder response 0. (common.js, line 62)
[Log] [2020-3-18 21:39:1:508][Player][IF] Video param duation:5 pixFmt:0 width:1280 height:720. (common.js, line 62)
[Log] [2020-3-18 21:39:1:508][Player][IF] Seek wait len -400 (common.js, line 62)
[Log] [2020-3-18 21:39:1:508][Player][IF] Byte rate:-200 target speed:-400 chunk interval:-163840. (common.js, line 62)
[Log] [2020-3-18 21:39:1:508][Player][IF] Audio param sampleFmt:3 channels:2 sampleRate:44100. (common.js, line 62)
[Log] [2020-3-18 21:39:1:508][Player][IF] Audio encoding 32bitFloat. (common.js, line 62)
[Log] [2020-3-18 21:39:1:533][Player][IF] Decoder ready now. (common.js, line 62)
[Log] [2020-3-18 21:39:1.541][Core][DT] Initial PCM buffer size 131072. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:4:241][Player][IF] Stop in stream pause. (common.js, line 62)
[Log] [2020-3-18 21:39:4:241][Player][IF] Stop. (common.js, line 62)
[Log] [2020-3-18 21:39:4:242][Player][IF] Pcm player released. (common.js, line 62)
[Log] [2020-3-18 21:39:4:243][Player][IF] Closing decoder. (common.js, line 62)
[Log] [2020-3-18 21:39:4:243][Player][IF] Uniniting decoder. (common.js, line 62)
[Log] [2020-3-18 21:39:4:243][Decoder][IF] closeDecoder. (common.js, line 62)
[Log] [2020-3-18 21:39:4.245][Core][DT] Video codec context closed. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:4.245][Core][DT] Audio codec context closed. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:4.245][Core][DT] IO context released. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:4.247][Core][DT] Input closed. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:4.247][Core][DT] All buffer released. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:4:247][Decoder][IF] Close ffmpeg decoder return 0. (common.js, line 62)
[Log] [2020-3-18 21:39:4.248][Core][DT] Decoder uninitialized. (libffmpeg.js, line 1)
[Log] [2020-3-18 21:39:4:251][Decoder][IF] Uninit ffmpeg decoder return 0. (common.js, line 62)

关于播放flv视频的问题

我用脚本重新编译了ffmpeg,添加了解码器flv,然后播放的时候,发现解码器能生成,数据无法解析,报Invalid NAL unit size (15205 > 9622)。 是跟decoder.c写的有关系吗,我用vlc能播放这个文件

无法播放hevc+aac (LC)的mp4视频

为什么无法播放这个h265的mp4文件?浏览器控制台信息如下:

libffmpeg.js:1 wasm streaming compile failed: TypeError: Failed to execute 'compile' on 'WebAssembly': Incorrect response MIME type. Expected 'application/wasm'.
(anonymous) @ libffmpeg.js:1
libffmpeg.js:1 falling back to ArrayBuffer instantiation
(anonymous) @ libffmpeg.js:1
common.js:58 [2019-10-25 11:44:59:888][Decoder][IF] Wasm loaded.
common.js:58 [2019-10-25 11:45:0:806][Player][IF] Play video/VID_20191025_110711.mp4.
common.js:58 [2019-10-25 11:45:0:845][Downloader][IF] Getting file size video/VID_20191025_110711.mp4.
common.js:58 [2019-10-25 11:45:0:853][Player][IF] Got file size rsp:200 size:39933168 byte.
common.js:58 [2019-10-25 11:45:0:853][Player][IF] Initializing decoder.
common.js:58 [2019-10-25 11:45:0:855][Decoder][IF] initDecoder return 0.
common.js:58 [2019-10-25 11:45:0:855][Player][IF] Init decoder response 0.
common.js:58 [2019-10-25 11:45:0:882][Player][IF] Opening decoder.
libffmpeg.js:1 18
libffmpeg.js:1 18
abort @ libffmpeg.js:1
libffmpeg.js:1 Uncaught abort(18). Build with -s ASSERTIONS=1 for more info.
common.js:54 [2019-10-25 11:45:3:41][Player][ER] Reach file end.

视频文件信息如下:

  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf58.20.100
  Duration: 00:00:42.07, start: 0.000000, bitrate: 11897 kb/s
    Stream #0:0(eng): Video: hevc (Main) (hev1 / 0x31766568), yuv420p(tv, progressive), 3840x2160 [SAR 1:1 DAR 16:9], 11792 kb/s, 29.97 fps, 29.97 tbr, 11988 tbn, 29.97 tbc (default)
    Metadata:
      handler_name    : Mainconcept MP4 Video Media Handler
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 112 kb/s (default)
    Metadata:
      handler_name    : Mainconcept MP4 Sound Media Handler

可以直接使用ffmpeg的io吗?

有几点疑问:
1.不太确定是否可以直接使用ffmpeg的io?
2.当mp4 moov box较大时需要增大waitHeaderLength要设置很大,这个阈值不太好确定。
3.sendData和decoder可以放到不同woker中吗?类似ffplay的逻辑,read/decoder video/audio放在不同线程中。

用脚本编译时候出现问题

1 warning generated.
wasm-ld: error: 'atomics' feature is used by allformats_ea044c9d.o, so --shared-memory must be used

请问之前编译有碰到过这个问题吗

编译代码的时候报错

我下载了ffmpeg3.3,并且和目录同级。
在windows环境下,我使用git bash来运行编译脚本。
报如下错误,:
image

image
在Ubuntu环境下编译时,报如下错误,有一方面的原因可能是emsdk版本的原因(找不到emsdk/fastcomp/fastcomp/bin/lli),我下的是最新版
image
image

可以播放 hls/flv 直播流吗?

Flash被废除就在眼前,急需一个纯网页播放直播流的替代方案。尝试过flv.js、hls.js来播放直播流(hls或flv)都有很多问题(延时大、卡停、黑屏……),不知道您这个是否可应用于稳定播放 hls/flv 直播流的场景呢

如果想解码flv视频要从哪里下手?

感谢作者抽空对我之前提问的回答,对您的代码有了更深刻的了解,通过您的代码也对ffmpeg的解码流程有了更清晰的认识 : )
我想问一下,如果要解码flv视频的话,要从哪里下手?应该要改造一下decoder
.c里的openDecoder函数吗?
还有一个问题就是,不论什么格式的视频,解码这一块都不用改了?都是不断的通过XMLHttpRequest获取文件片段然后发送给C端解码就行了?
谢谢。

关于moov atom not found 问题

up主好,通过mp4info工具我发现大部分mp4视频的moov信息在最后,所以在decoder在执行openDecoder函数的时候返回的ret是8,本人对c和视频不太熟悉,可否告知如何让moov在末尾的情况下,让ret返回的是0。谢谢

关于参数的一些疑问

你好,我想问一下,里面的一些参数值是怎么考虑的?
1、发送解码命令的周期为什么设为5ms?(按照帧率设置解码周期的话,如30帧设为30ms时会特别卡)
2、每次downlad的数据大小为什么是65536?
3、decoder.c中的kCustomIoBufferSize为什么是32X1024?(设为64X1024也可以正常播放,16没试过)

ffmpeg执行 ./configure时报错,shared:ERROR: dist/lib/libavformat.a: No such file or directory ("dist/lib/libavformat.a" was expected to be an input file, based on the commandline arguments provided),

再执行下面的sh build_decoder_wasm.sh就会有问题,root@DESKTOP-7ME2BST:/home/blue/data/WasmVideoPlayer# sh build_decoder_wasm.sh
Running Emscripten...
shared:ERROR: dist/lib/libavformat.a: No such file or directory ("dist/lib/libavformat.a" was expected to be an input file, based on the commandline arguments provided)
Finished Build

建议作者写一个flv2canvas的项目,现在国内video劫持太严重

如果想要在移动端浏览器上如直播将视频置于底层就需要对video进行处理,而腾讯UC这些基本都是各种不要脸的对起劫持搞起所谓同层播放器或插播广告.
将视频流解析到canvas播放,目前我看过jsmepg还可以,但是mpeg1-ts来解码实在是效率欠佳,若能将flv或hls解码到canvas播放,这类项目估计会非常火.

很多h265视频无法播放是怎么回事?

之前发现hev1的h265视频无法播放,现在发现hvc1的h265视频也有无法播放的,这是什么情况?应该如何debug调查?
报错如下:

libffmpeg.js:1 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x647710] error reading header
[2019-11-4 14:28:35:73][Decoder][IF] openDecoder return 8
[2019-11-4 14:28:35:73][Player][IF] Open decoder response 8.
play error 8 status 0.

视频媒体信息如下:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'h265.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf58.29.100
  Duration: 01:09:37.08, start: 0.000000, bitrate: 327 kb/s
    Stream #0:0(eng): Video: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv, progressive), 720x480 [SAR 32:27 DAR 16:9], 196 kb/s, 25 fps, 25 tbr, 12800 tbn, 25 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 125 kb/s (default)
    Metadata:
      handler_name    : SoundHandler

seek bar点击报错

播放视频的时候,点击seek bar,有时候会出现以下错误,视频就无法播放了。

libffmpeg.js:1 [hevc @ 0x64c9a0] Invalid NAL unit size (137165 > 52089).
libffmpeg.js:1 [hevc @ 0x64c9a0] Error splitting the input into NAL units.
libffmpeg.js:1 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x647710] stream 1, offset 0x3ff6c5: partial file
libffmpeg.js:1 [aac @ 0x677d70] Sample rate index in program config element does not match the sample rate index configured by the container.
libffmpeg.js:1 [aac @ 0x677d70] Inconsistent channel configuration.
libffmpeg.js:1 [aac @ 0x677d70] get_buffer() failed
libffmpeg.js:1 [hevc @ 0x64c9a0] Invalid NAL unit size (705012347 > 42820).
libffmpeg.js:1 [hevc @ 0x64c9a0] Error splitting the input into NAL units.
libffmpeg.js:1 [aac @ 0x677d70] channel element 3.5 is not allocated
libffmpeg.js:1 [aac @ 0x677d70] channel element 2.11 is not allocated
。。。

关于解码格式

如果是h265(hvc1)的就可以但是如果是h265(hev1)就不行,这个能解决一下么?

Compile issue with libx264

Hi @sonysuqin i faced an issue when am run the build_decoder_wasm.sh. Kindly help me for this issue to resolve.

error: asm2wasm seeing an invalid argument type at index 1 (this will not validate) in call from $_file_seek to fined behaviour in C, like defining a function one way and calling it in another, which is important to fix)

Fatal: error in validating output
shared:ERROR: '/home/user/emsdk/fastcomp/bin/asm2wasm libffmpeg.temp.asm.js --total-memory=1073741824 --trap-mode=allow -O3 --mem-init=libffmpeg.js.mem --mem-base=1024 --table-max=-1 --wasm-only -o libffmpeg.wasm --mvp-features' failed (1)

audioCtx.currentTime不太稳定的同步

依赖于audioCtx.currentTime的同步方案 在测试过程中感觉不太靠谱,例如chrome最小化后,音频停止播放了但是currentTime会继续流逝,还有例如网络卡顿。
使用pts是否是更好的方案呢:)

支持 http-flv 直播

请问如何改成支持直播呢,看到有说改成 环形缓冲区的,前端开发,没有学过 C 研究了两个周末也没研究出来。

其实我觉得可以 通过是否传入 videocallback 和 audiocallback 函数来决定是否是否解码 音/视频,某些场景可能只需要单独一个,比如我。哈哈哈哈哈哈

h265文件视频无法播放 function signature mismatch

ffprobe 分析出来的 mp4视频格式:
Metadata:
major_brand : qt
minor_version : 512
compatible_brands: qt
encoder : Lavf55.33.100
Duration: 00:00:54.68, start: 0.000000, bitrate: 2056 kb/s
Stream #0:0(eng): Video: hevc (Main) (hev1 / 0x31766568), yuv420p(tv), 640x480 [SAR 1:1 DAR 4:3], 1933 kb/s, 30 fps, 30 tbr, 90k tbn, 30 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 127 kb/s (default)
Metadata:
handler_name : SoundHandler
但是无法播放
wasm-010e596e-924:1 Uncaught RuntimeError: function signature mismatch
at wasm-function[924]:0xb94d4
at wasm-function[57]:0x4d49
at wasm-function[70]:0x6722
at wasm-function[174]:0x1aa40
at wasm-function[2374]:0x1c7184
at wasm-function[1437]:0x11eaaa
at wasm-function[2289]:0x1b5a37
at Object.Module._openDecoder (http://127.0.0.1:8081/libffmpeg.js:1:92204)
at Decoder.openDecoder (http://127.0.0.1:8081/decoder.js:48:22)
at Decoder.processReq (http://127.0.0.1:8081/decoder.js:165:18)

openDecoder return 8

您好,我发现我很多视频 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.