vc-player
v0.5.0
Published
vc-player 是一款面向 web 的流媒体软解播放器,基于流媒体技术和 web 技术开发,采用 ffmpeg+webassembly 的方式,对视频/音频进行解码并播放。目前可支持 url 网络流,本地上传文件流和切片流三种方式,前两种适用于点播,后者适用于直播。
Downloads
2
Readme
vc-player
vc-player 是一款面向 web 的流媒体软解播放器,基于流媒体技术和 web 技术开发,采用 ffmpeg+webassembly 的方式,对视频/音频进行解码并播放。目前可支持 url 网络流,本地上传文件流和切片流三种方式,前两种适用于点播,后者适用于直播。
更新日志:
2021-09-15 增加了回调(hooks)和插槽(slots),详见下文
系统需求
建议最低运行环境 cpu 为 4x Intel(R) Core(TM) i5-7500 @ 3.4GHZ
使用方式
import("vc-player")
.then(({ default: vcPlayer }) => new vcPlayer(YOUR_CANVAS_DOM))
.then((player) => {
// 状态初始化
// 直连http,取流
player.openUrlDecoder(MEDIA_URL);
// OR
// 直连文件流
let reader = new FileReader();
reader.onload = function () {
player.openFileDecoder(this.result);
};
reader.readAsArrayBuffer(fileInput.files[0]);
// OR
// 初始化流片段
player.openIoDecoder(this.result);
// 提供流片段
player.supplyFragment(this.result);
})
- new vcPlayer(YOUR*CANVAS_DOM, option),第二个参数为配置项,有几个参数是可配置的:
- defaultBufferingTime: 3000, // 初始缓存时间,默认 3 秒钟,如果缓存时间少于改值则等待解码器回传更多数据
- defaultTickTime: 100, // 默认时间轴跳跃间隔,每次跳跃都会进行音视频同步,跳跃越频繁,cpu 压力越大,效果越好
- preparedBufferSize: 256 * 1024 _ 1024, // 默认缓存库大小,这里是直播专用,一般不用设置,除非直播数据非常大
- cacheThresholdMax: 512 _ 1024 _ 1024, // 最大主线程缓存大小,如果解码器工作速度超过播放速度,解码帧会堆积起来,为了不给计算机内存造成巨大压力,这里设置解码帧缓存上限,超过该值则解码器暂停工作
- cacheThresholdMin: 256 _ 1024 _ 1024, // 最小主进程缓存大小,如果缓存帧大小小于该值,则会重新唤起解码器工作
- hideTimer: false, // 是否隐藏时间
- hideSound: false, // 是否隐藏调音器
- hideFullScreen: false, // 是否隐藏全屏按钮
- hideBar: false, // 是否隐藏操作栏
- vcPlayer 所有时间的计量单位都是毫秒 ms,所有大小计量单位都为字节 byte
- isLight: false, // 是否使用轻量模式,使用轻量模式可以支持视频墙等同页面多播放器的场景
- 直播时,不管是通过 websocket 还是 m3u8 的 ts 列表,前端需将 fmp4 格式的文件流切片或者 ts 格式的流切片通过调用 sdk 的方式喂到当前 player 的 file buffer 中,解码器会自动整合,没有时间戳解码器会自行添加,用户需自行保证流切片的完整性和合法性,否则可能出现解码器错误等问题
- 当前版本播放器为单例模式,一个页面只能有一个 vc-player 播放器
- 播放任务为串行模式,也就是说前一个播放任务必须结束(点击停止)后才能播放另一个任务
- 目前可支持 h264/h265,pcm 格式的文件,如需要可加入新的解码器重新编译
软件结构
结构一览如下图
注意事项
- 为了提高软解性能,目前编译的版本为 x64 版,在 32 位机上执行可能有问题,开发者可自行使用项目中已经编译好的 x86 版本 ffmpeg 进行 32 位机版本的编译
- 当前 build 中,解码器运行时初始内存为 100M,最大内存为 2G,由于文件会被缓存在内存中,所以如果播放器所在宿主机内存有限,请不要播放超过 2G 的视频文件,如有特殊需要,请修改参数重新编译新版 wasm(解码器)
- 当前测试结果,双核 intel i5 下,h264 bitrate < 20000 kbps 时,流畅, hevc bitrate < 2000 kbps 时,流畅,由于该播放器是软解播放器,请用户根据自己的机器 cpu 能力,自行选择待播放的视频,以避免出现卡帧现象
- 关于 Shared ArrayBuffer, 近期部分浏览器如 Chrome 增加了同源且必须 https 部署的安全策略,可能需要一个 nginx 上做反代以适配
- 目前暂定只有两个声道,多声道会被忽略
- 目前暂不支持 ps 流直接播放
vcPlayer 成员数据和方法
数据类
vcPlayer.prototype.doms
- dom: //dom 容器元素,
- canvas: //播放器视频部 dom 元素
- bgBar: //进度条背景,
- playBar: //播放进度条,
- bufferBar: //缓冲进度条,
- timer: //时间进度,
- volume: //声音控制器,
- startBtn: //开始按钮,
- pauseBtn: //暂停按钮,
- stopBtn: //停止按钮,
- fullScreenBtn: //全屏按钮,
- timeTooltip: //时间进度悬浮框,
vcPlayer.prototype.queues
- yuv: //解码出来的 yuv 数据队列,
- pcm: //解码出来的 pcm 数据队列
vcPlayer.prototype.statistic
- nbSamplePlaying: //当前播放的 pcm 整合数据包数量,
- decodedFrameNum: //解码出来的视频帧总数(从上一次开始或者 seek 算起)
- renderedFrameNum: //播放过的视频帧总数(从上一次开始或者 seek 算起)
- decodedSampleNum: //解码出来的 pcm 包总数(从上一次开始或者 seek 算起)
- playedSampleNum: //播放过的 pcm 包总数(从上一次开始或者 seek 算起)
- frameAdjusted: //音视频同步导致帧时长调整的统计
vcPlayer.prototype.ticker
- currentPts: //当前时间点(毫秒),
- nextPts: //下一个 tick 播放的时间点(毫秒),
- currentTime: //当前系统时刻,
- ptsChecker: //时间同步器,用于同步音视频,
- playChecker: //播放状态核对器,用于检查播放状态,以便判断是否要阻塞/解除阻塞
- ptsDiff: // 播放器平均音视频时间差,用于同步时作为参数
- lastFrameTime: // 最后一次播放视频帧的系统时刻
- lastFramePauseTime: // 最后一次播放视频帧之后用户暂停的系统时刻
- lastFramePauseElipsed: // 最后一次播放视频帧之后用户暂停后经过的时间(毫秒)
- lastFramePts: // 最后一次播放视频帧的时间点
- lastFrameDuration: // 最后一次播放视频帧的时长
- lastPcmTime: // 最后一次播放音频整合包的系统时刻
- lastPcmPauseTime: // 最后一次播放音频整合包之后用户暂停的系统时刻
- lastPcmPauseElipsed: // 最后一次播放音频整合包之后用户暂停后经过的时间(毫秒)
- lastPcmPts: // 最后一次播放音频整合包的时间点
- lastPcmDuration: // 最后一次播放音频整合包的时长
- lastFramePlan: // playChecker 检查后创建的下一帧播放策略,
- lastPcmPlan: // playChecker 检查后创建的下段音频的播放策略,
- pcmSourceNode: // Web Audio Context 的 Source Buffer Node, 不解释,
vcPlayer.prototype.info
- codecs: //解码器(含音频,没有字幕),
- fps: //视频流帧率,
- width: //视频流宽,
- height: //视频流高,
- defaultBufferingTime: //播放前缓冲的最小时间,
- defaultTickTime: //音视频同步的校验周期,
- channels: //音视通道数,
- sampleRate: //音视采样率,
- isPlanar: // 是否为二维数组,
- duration: // 视频流时长(如有音频为音频时长),
- preparedBufferSize: // 直播缓存区大小,直播会开辟堆缓存区,大小为此数值,用于暂时存放直播拉下来的数据流,但如果解码器播放码率效率比直播拉流码率低,则此缓存区会堆积起来,直到堆满后清空,用户会看到视频跳跃现象
- cacheThresholdMax: // 缓存区可播极高值,如果解码出来的数据超过此数值则 playChecker 会指令解码器暂停解码
- cacheThresholdMin: // 缓存区可播极低值,如果解码出来的数据低于此数值则 playChecker 会指令解码器解码
- streamReaderBufferSize: // 直播初始化最小读入数据量,值越大视频同步效果越好,反之会保证播放实时性,牺牲质量,如果想秒开则需调低此数值
- codecStatus: // 解码器状态 0: ready, 1: running, 2: pause until memory reduce to threshold, 3: seek start 4: seeking -1: ended
- playStatus: // 播放器状态 0: ready, 1: running, 2: pause -1: ended
- audioCtx: // Web Audio Context 不解释,
- audioGainNode: // Web Audio Gain Node 不解释,
- isLive: // 是否为直播,直播不可 seek,
- render: // webgl 渲染器,
window.vcPlayerDecoderBridge = vcPlayer
挂在 window 上的桥对象,用于 wasm 和 js 同步交互
方法类
以下方法须初始化播放器后方能使用,即
import("vc-player")
.then(({ default: vcPlayer }) => new vcPlayer(YOUR_CANVAS_DOM))
.then(()=>{
// use them here
})
vcPlayer.prototype.openUrlDecoder
- 参数:url, 类型:string
- 返回:无
- 效果:解码器开始从该地址上拉流,缓存到本地内存上后开始解码,解码到 playChecker 认为可以播放的条件后开始播放
vcPlayer.prototype.openFileDecoder
- 参数:buffer, 类型:ArrayBuffer
- 返回:无
- 效果:播放器将该数据压入解码队列后开始解码,解码到 playChecker 认为可以播放的条件后开始播放(可以用 FileReader 将用户上传的文件解析成 ArrayBuffer 形式数据)
vcPlayer.prototype.openIoDecoder
- 参数:buffer, 类型:ArrayBuffer
- 返回:无
- 效果:播放器将该数据压入解码队列并异步开始解码,解码到 playChecker 认为可以播放的条件后开始播放(可以用 FileReader 将用户上传的文件解析成 ArrayBuffer 形式数据)
vcPlayer.prototype.supplyFragment
- 参数:buffer, 类型:ArrayBuffer
- 返回:无
- 效果:播放器将数据压入解码队列
vcPlayer.prototype.startPlay
- 参数:无
- 返回:无
- 效果:启动播放流程
vcPlayer.prototype.toggleStart
- 参数:无
- 返回:无
- 效果:不断检查是否符合条件,符合后马上启动播放流程
vcPlayer.prototype.toggleStop
- 参数:无
- 返回:无
- 效果:无条件终止播放,由于解码器和播放器是异步处理,解码器会在最多 100 毫秒内完全关闭,故这里返回的是一个延时 100ms 的 promise,期待使用者 100ms 后再启动新的实例
vcPlayer.prototype.togglePause
- 参数:无
- 返回:无
- 效果:暂停/解除暂停,由于音频使用的是 audio context,故根据其本身特性,挂起时(suspend)是一个延时函数,反之亦同
vcPlayer.prototype.toggleFullscreen
- 参数:无
- 返回:无
- 效果:全屏/退出全屏,不解释
vcPlayer.prototype.toggleSeek
- 参数:无
- 返回:无
- 效果:用户 Seek 时执行的函数,解码器重新定位数据游标,播放器重新计算播放状态
vcPlayer.prototype.toggleVolume
- 参数:e, 类型:Event
- 返回:无
- 效果:audio context 的调音函数
以下是回调函数,初始化时跟随 option(new vcPlayer(YOUR_CANVAS_DOM, {info: {...}, ...}))作为参数加入,位置位于 vcPlayer.info
- onLoading 加载中,播放器已启动但数据尚未回传时触发
- onLoaded 加载完毕,有且有足够的数据,即将开始播放
- onPause 用户暂停时触发
- onResume 用户解除暂停时触发
- onSeeking 跳转时间,且尚无反应时触发
- onSeeked 跳转且已寻址完毕时触发
- onCacheThresholdReached 音视频数据阈值打到上限时触发
- onFullScreen 全屏时触发
- onExitFullScreen 退出全屏时触发
- onTick 每次检查点任务执行时触发
- onStop 停止当前视频时触发
- onDestroy 销毁播放器时触发
以下是插槽函数,初始化时跟随 option(new vcPlayer(YOUR_CANVAS_DOM, {slots: {...}, ...}))作为参数加入,位置位于 vcPlayer.info
- customRender 自定义绘制图像函数,如果用户提供该方法则默认画布不会初始化,用户可根据 yuv 数据自行绘制,
- 参数 { stride_y, stride_u, stride_v, width, height, buf_y, buf_u, buf_v, pts, duration,}
以下是内部函数
vcPlayer.prototype.cacheChecker
- 参数:无
- 返回:无
- 效果:解码数据缓存检查器
vcPlayer.prototype.createRenderTask
- 参数:无
- 返回:无
- 效果:创建下一帧的渲染任务
vcPlayer.prototype.createSoundTask
- 参数:无
- 返回:无
- 效果:创建下一个 pcm 包的播放任务
vcPlayer.prototype.drawFrame
- 参数:yuv_obj,
- 类型: { stride_y, // y 步长 stride_u, // u 步长 stride_v, // v 步长 width, // 帧宽度 height, // 帧高度 buf_y: // y 向数据 buf_u: // u 向数据 buf_v: // v 向数据 pts, // 帧时间点 duration, // 帧播放时长 pkt_pos, // 解码位置(适用于 b 帧) }
- 返回:无
- 效果:绘制该 yuv 数据
vcPlayer.prototype.format_seconds
- 参数:pts,类型: 毫秒
- 返回:无
- 效果:转成 hh:mm:ss 结构的时分秒字符串
vcPlayer.prototype.postPause
- 参数:无
- 返回:无
- 效果:用户暂停时负责记录当时的播放状态
vcPlayer.prototype.postResume
- 参数:无
- 返回:无
- 效果:用户解除暂停时负责调取暂停时的播放状态和当前时刻,刷新参数,以便下一个 ticker 重新规划播放任务
vcPlayer.prototype.ptsCheckerRunner
- 参数:无
- 返回:无
- 效果:负责发起同步校验任务
vcPlayer.prototype.shadowCodecStatus
- 参数:status, 类型:number
- 返回:无
- 效果:解码器状态回调函数
vcPlayer.prototype.toggleTooltipSeek
- 参数:event, 类型:Event
- 返回:无
- 效果:用户鼠标悬浮在进度条上显示时间
vcPlayer.prototype.toggleTooltipSeekEnd
- 参数:event, 类型:Event
- 返回:无
- 效果:用户鼠标离开进度条上隐藏时间框
vcPlayer.prototype.mediaProber
参数:width, 类型:number
参数:height, 类型:number
参数:fps, 类型:number
参数:channels, 类型:number
参数:sample_rate, 类型:number
参数:is_planar, 类型:number
参数:duration, 类型:number
参数:video_codec, 类型:number
参数:video_codec_length, 类型:number
参数:audio_codec, 类型:number
参数:audio_codec_length, 类型:number
返回:无
效果:解码器在解析该视频流后,解码前,会将该视频的各种信息返回,方便前端进行记录和其他初始化工作
vcPlayer.prototype.frameSupplier
- 参数:addr_y, 类型:number
- 参数:addr_u, 类型:number
- 参数:addr_v, 类型:number
- 参数:stride_y, 类型:number
- 参数:stride_u, 类型:number
- 参数:stride_v, 类型:number
- 参数:width, 类型:number
- 参数:height, 类型:number
- 参数:pts, 类型:number
- 参数:duration, 类型:number
- 参数:bitrate, 类型:number
- 参数:pkt_pos, 类型:number
- 返回:无
- 效果:解码后的帧数据回传函数
vcPlayer.prototype.sampleSupplier
- 参数:addr_ch_0, 类型:number
- 参数:addr_ch_1, 类型:number
- 参数:linesize, 类型:number
- 参数:channels, 类型:number
- 参数:sample_rate, 类型:number
- 参数:pts, 类型:number
- 参数:duration, 类型:number
- 参数:nb_samples, 类型:number
- 返回:无
- 效果:解码后的 pcm 数据回传函数
支持视频格式
D = Demuxing supported
D 4xm 4X Technologies
D aac raw ADTS AAC (Advanced Audio Coding)
D ac3 raw AC-3
D act ACT Voice file format
D adf Artworx Data Format
D adx CRI ADX
D aea MD STUDIO audio
D afc AFC
D aiff Audio IFF
D alaw PCM A-law
D amr 3GPP AMR
D anm Deluxe Paint Animation
D apc CRYO APC
D ape Monkey‘s Audio
D aqtitle AQTitle subtitles
D asf ASF (Advanced / Active Streaming Format)
D ass SSA (SubStation Alpha) subtitle
D ast AST (Audio Stream)
D au Sun AU
D avi AVI (Audio Video Interleaved)
D avr AVR (Audio Visual Research)
D avs AVISynth
D bethsoftvid Bethesda Softworks VID
D bfi Brute Force & Ignorance
D bin Binary text
D bink Bink
D bit G.729 BIT file format
D bmv Discworld II BMV
D brstm BRSTM (Binary Revolution Stream)
D c93 Interplay C93
D caf Apple CAF (Core Audio Format)
D cavsvideo raw Chinese AVS (Audio Video Standard) video
D cdg CD Graphics
D cdxl Commodore CDXL video
D concat Virtual concatenation script
D daud D-Cinema audio
D dfa Chronomaster DFA
D dirac raw Dirac
D dnxhd raw DNxHD (SMPTD dshow DirectShow capture
D dsicin Delphine Software International CIN
D dts raw DTS
D dtshd raw DTS-HD
D dv DV (Digital Video)
D dxa DXA
D ea Electronic Arts Multimedia
D ea_cdata Electronic Arts cdata
D eac3 raw E-AC-3
D epaf Ensoniq Paris Audio File
D f32be PCM 32-bit floating-point big-endian
D f32le PCM 32-bit floating-point little-endian
D f64be PCM 64-bit floating-point big-endian
D f64le PCM 64-bit floating-point little-endian
D ffm FFM (FFserver live feed)
D ffmetadata FFmpeg metadata in text
D film_cpk Sega FILM / CPK
D filmstrip Adobe Filmstrip
D flac raw FLAC
D flic FLI/FLC/FLX animation
D flv FLV (Flash Video)
D frm Megalux Frame
D g722 raw G.722
D g723_1 raw G.723.1
D g729 G.729 raw format demuxer
D gif GIF Animation
D gsm raw GSM
D gxf GXF (General eXchange Format)
D h261 raw H.261
D h263 raw H.263
D h264 raw H.264 video
D hls,applehttp Apple HTTP Live Streaming
D ico Microsoft Windows ICO
D idcin id Cinematic
D idf iCD iff IFF (Interchange File Format)
D ilbc iLBC storage
D image2 image2 sequence
D image2pipe piped image2 sequence
D ingenient raw Ingenient MJPEG
D ipmovie Interplay MVE
D ircam Berkeley/IRCAM/CARL Sound Format
D iss Funcom ISS
D iv8 IndigoVision 8000 video
D ivf On2 IVF
D jacosub JACOsub subtitle format
D jv Bitmap Brothers JV
D latm LOAS/LATM
D lavfi Libavfilter virtual input device
D lmlm4 raw lmlm4
D loas LOAS AudioSyncStream
D lvf LVF
D lxf VR native stream (LXF)
D m4v raw MPEG-4 video
D matroska,webm Matroska / WebM
D mgsts Metal Gear Solid: The Twin Snakes
D microdvd MicroDVD subtitle format
D mjpeg raw MJPEG video
D mlp raw MLP
D mm American Laser Games MM
D mmf Yamaha SMAF
D mov,mp4,m4a,3gp,3g2,mj2 QuickTime / MOV
D mp3 MP3 (MPEG audio layer 3)
D mpc Musepack
D mpc8 Musepack SV8
D mpeg MPEG-1 Systems / MPEG program stream
D mpegts MPEG-TS (MPEG-2 Transport Stream)
D mpegtsraw raw MPEG-TS (MPEG-2 Transport Stream)
D mpegvideo raw MPEG video
D mpl2 MPL2 subtitles
D mpsub MPlayer subtitles
D msnwctcp MSN TCP Webcam stream
D mtv MTV
D mulaw PCM mu-law
D mv Silicon Graphics Movie
D mvi Motion Pixels MVI
D mxf MXF (Material eXchange Format)
D mxg MxPEG clip
D nc NC camera feed
D nistsphere NIST SPeech HEader REsources
D nsv Nullsoft Streaming Video
D nut NUT
D nuv NuppelVideo
D ogg Ogg
D oma Sony OpenMG audio
D paf Amazing Studio Packed Animation File
D pjs PJS (Phoenix Japanimation Society) subtitles
D pmp Playstation Portable PMP
D psxstr Sony Playstation STR
D pva TechnoTrend PVA
D pvf PVF (Portable Voice Format)
D qcp QCP
D r3d REDCOD R3D
D rawvideo raw video
D realtext RealText subtitle format
D rl2 RL2
D rm RealMedia
D roq raw id RoQ
D rpl RPL / ARMovie
D rso Lego Mindstorms RSO
D rtp RTP output
D rtsp RTSP output
D s16be PCM signed 16-bit big-endian
D s16le PCM signed 16-bit little-endian
D s24be PCM signed 24-bit big-endian
D s24le PCM signed 24-bit little-endian
D s32be PCM signed 32-bit big-endian
D s32le PCM signed 32-bit little-endian
D s8 PCM signed 8-bit
D sami SAMI subtitle format
D sap SAP output
D sbg SBaGen binaural beats script
D sdp SDP
D shn raw Shorten
D siff Beam Software SIFF
D smjpeg Loki SDL MJPEG
D smk Smacker
D smush LucasArts Smush
D sol Sierra SOL
D sox SoX native
D spdif IEC 61937 (used on S/PDIF - IEC958)
D srt SubRip subtitle
D subviewer SubViewer subtitle format
D subviewer1 SubViewer v1 subtitle format
D swf SWF (ShockWave Flash)
D tak raw TAK
D tedcaptions TED Talks captions
D thp THP
D tiertexseq Tiertex Limited SEQ
D tmv 8088flex TMV
D truehd raw TrueHD
D tta TTA (True Audio)
D tty Tele-typewriter
D txd Renderware TeXture Dictionary
D u16be PCM unsigned 16-bit big-endian
D u16le PCM unsigned 16-bit little-endian
D u24be PCM unsigned 24-bit big-endian
D u24le PCM unsigned 24-bit little-endian
D u32be PCM unsigned 32-bit big-endian
D u32le PCM unsigned 32-bit little-endian
D u8 PCM unsigned 8-bit
D vc1 raw VC-1
D vc1test VC-1 test bitstream
D vfwcap VfW video capture
D vivo Vivo
D vmd Sierra VMD
D vobsub VobSub subtitle format
D voc Creative Voice
D vplayer VPlayer subtitles
D vqf Nippon Telegraph and Telephone Corporation (NTT) TwinVQ
D w64 Sony Wave64
D wav WAV / WAVE (Waveform Audio)
D wc3movie Wing Commander III movie
D webvtt WebVTT subtitle
D wsaud Westwood Studios audio
D wsvqa Westwood Studios VQA
D wtv Windows Television (WTV)
D wv WavPack
D xa Maxis XA
D xbin eXtended BINary text (XBIN)
D xmv Microsoft XMV
D xwma Microsoft xWMA
D yop Psygnosis YOP
D yuv4mpegpipe YUV4MPEG pipe
开发者常用
使用 emscripten 进行 ffmpeg 的静态包编译脚本为
emconfigure ../configure --cc=emcc --cxx=em++ --ar=emar --ranlib=emranlib --disable-ffplay --disable-ffprobe --enable-cross-compile --target-os=none --arch=x86_32 --cpu=generic --prefix=$project/ffmpegx64 --disable-stripping --disable-asm --disable-doc --disable-devices --disable-network --enable-gpl --disable-avdevice --disable-hwaccels --enable-demuxer=hevc --enable-decoder=hevc --enable-parser=hevc --enable-decoder=h264 --enable-parser=h264 --disable-debug --disable-protocols --disable-indevs --disable-outdevs --disable-programs --disable-logging
使用 emscripten 进行 vc-player 解码器的编译脚本为
emcc -o decoder.js ./lib/open_stream_emcc.c -L./ffmpeg_x64/lib -I./ffmpeg_x64/include -I$emsdk/upstream/emscripten/system/include -lavutil -lavformat -lavcodec -lswresample -msimd128 -msse -msse2 -msse3 -msse4.2 -s FETCH=1 -s EXPORTED_RUNTIME_METHODS='["cwrap","allocate","intArrayFromString", "addFunction","UTF8ToString"]' -s EXPORTED_FUNCTIONS='["_open_url_decoder", "_open_io_decoder", "_open_file_decoder","_set_status", "_set_buffer", "_seek_time"]' -s INITIAL_MEMORY=100MB -s ALLOW_MEMORY_GROWTH=1 -s RESERVED_FUNCTION_POINTERS=10 -s WASM_MEM_MAX=2048MB -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=8 -s MODULARIZE=1 -s EXPORT_NAME=vcPlayerModule -s EXPORT_ES6=1 -s USE_ES6_IMPORT_META=0 -s ENVIRONMENT='web,worker'
emcc -o ./src/decoder/decoder.js ./lib/open_stream_emcc.c -L./ffmpeg_x64/lib -I./ffmpeg_x64/include -I$emsdk/upstream/emscripten/system/include -lavutil -lavformat -lavcodec -lswresample -msimd128 -msse -msse2 -msse3 -msse4.2 -s FETCH=1 -s EXPORTED_RUNTIME_METHODS='["cwrap","allocate","intArrayFromString", "addFunction","UTF8ToString"]' -s EXPORTED_FUNCTIONS='["_open_url_decoder", "_open_io_decoder", "_open_file_decoder","_set_status", "_set_buffer", "_seek_time", "_destroy"]' -s INITIAL_MEMORY=100MB -s ALLOW_MEMORY_GROWTH=1 -s RESERVED_FUNCTION_POINTERS=10 -s WASM_MEM_MAX=2048MB -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=8 -s MODULARIZE=1 -s EXPORT_NAME=vcPlayerModule -s EXIT_RUNTIME=1 -s EXPORT_ES6=1 -s USE_ES6_IMPORT_META=0 -s ENVIRONMENT='web,worker' -Oz