UNPKG

@jxstjh/jhvideo

Version:

HTML5 jhvideo base on MPEG2-TS Stream Player

695 lines (601 loc) 26.8 kB
import EventEmitter from 'events'; // ------------------------ common player ----------------// const EventInfo = { ERROR: 'error', STREAMPAUSE: 'streampause', FIRST_CANPLAY: 'first_canplay', PLAYTIME: 'playtime', VIDEOSEEK: 'videoseek' } //Player request. const kPlayVideoReq = 0; const kPauseVideoReq = 1; const kStopVideoReq = 2; //Player response. const kPlayVideoRsp = 0; const kAudioInfo = 1; const kVideoInfo = 2; const kAudioData = 3; const kVideoData = 4; //Downloader request. const kGetFileInfoReq = 0; const kDownloadFileReq = 1; const kCloseDownloaderReq = 2; //Downloader response. const kGetFileInfoRsp = 0; const kFileData = 1; //Downloader Protocol. const kProtoHttp = 0; const kProtoWebsocket = 1; const kInitDecoderReq = "InitDecoderReq"; const kUninitDecoderReq = "UninitDecoderReq"; const kOpenDecoderReq = "OpenDecoderReq"; const kCloseDecoderReq = "CloseDecoderReq"; const kFeedDataReq = "FeedDataReq"; const kDecodeOnePacketReq = "kDecodeOnePacketReq"; const kStartDecodeReq = "StartDecodeReq"; const kStopDecodeReq = "StopDecodeReq"; const kCreateDecoderReq = "CreateDecoderReq"; const kCreateDecoderRsp = "CreateDecoderRsp"; const kDestroyDecoderReq = "DestroyDecoderReq"; const kDestroyDecoderRsp = "DestroyDecoderRsp"; //Decoder response. const kInitDecoderRsp = "InitDecoderRsp"; const kUninitDecoderRsp = "UninitDecoderRsp"; const kOpenDecoderRsp = "OpenDecoderRsp"; const kCloseDecoderRsp = "CloseDecoderRsp"; const kVideoFrame = "VideoFrame"; const kAudioFrame = "AudioFrame"; const kStartDecodeRsp = "StartDecodeRsp"; const kStopDecodeRsp = "StopDecodeRsp"; const kDecodeFinishedEvt = "DecodeFinishedEvt"; const kRequestDataEvt = "RequestDataEvt"; const kDecodeOnePacketRsp = "kDecodeOnePacketRsp"; const REQUEST_DECODE_OPEN = "REQUEST_DECODE_OPEN";//请求启动解码 const REQUEST_DECODE_CLOSE = "REQUEST_DECODE_CLOSE";//请求关闭解码 const REQUEST_DECODE_RELEASE = "REQUEST_DECODE_RELEASE";//请求释放解码器 const RESPOND_DECODE_OPEN = "RESPOND_DECODE_OPEN";//请求启动解码的响应 const RESPOND_DECODE_CLOSE = "RESPOND_DECODE_CLOSE";//请求关闭解码的响应 const RESPOND_DECODE_RELEASE = "RESPOND_DECODE_RELEASE";//请求释放解码器的响应 const EVENT_DECODE_ERROR = "EVENT_DECODE_ERROR";//错误信息回调 const EVENT_DECODE_NOTIFY = "EVENT_DECODE_NOTIFY";//信息回调 function Logger(module) { this.module = module; } Logger.prototype.log = function (line) { console.log("[" + this.currentTimeStr() + "][" + this.module + "]" + line); } Logger.prototype.logError = function (line) { console.log("[" + this.currentTimeStr() + "][" + this.module + "][error] " + line); } Logger.prototype.logInfo = function (line) { console.log("[" + this.currentTimeStr() + "][" + this.module + "][info] " + line); } Logger.prototype.logDebug = function (line) { console.log("[" + this.currentTimeStr() + "][" + this.module + "][debug] " + line); } Logger.prototype.currentTimeStr = function () { var now = new Date(Date.now()); var year = now.getFullYear(); var month = now.getMonth() + 1; var day = now.getDate(); var hour = now.getHours(); var min = now.getMinutes(); var sec = now.getSeconds(); var ms = now.getMilliseconds(); return year + "-" + month + "-" + day + " " + hour + ":" + min + ":" + sec + ":" + ms; } // ------------------------ webgl player ----------------// function Texture(gl) { this.gl = gl; this.texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); } Texture.prototype.bind = function (n, program, name) { var gl = this.gl; gl.activeTexture([gl.TEXTURE0, gl.TEXTURE1, gl.TEXTURE2][n]); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.uniform1i(gl.getUniformLocation(program, name), n); }; Texture.prototype.fill = function (width, height, data) { var gl = this.gl; gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width, height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data); }; function WebGLPlayer(canvas, options) { this.canvas = canvas; this.gl = canvas.getContext("webgl", { preserveDrawingBuffer: true }) || canvas.getContext("experimental-webgl", { preserveDrawingBuffer: true }); this.initGL(options); } WebGLPlayer.prototype.destroy = function () { var e = this.gl; e && (e.viewport(0, 0, e.canvas.width, e.canvas.height), e.clearColor(0, 0, 0, 0), e.clear(e.COLOR_BUFFER_BIT)) } WebGLPlayer.prototype.initGL = function (e) { if (this.gl) { var t = this.gl; t.pixelStorei(t.UNPACK_ALIGNMENT, 1); var i = t.createProgram(), r = ["attribute highp vec4 aVertexPosition;", "attribute vec2 aTextureCoord;", "varying highp vec2 vTextureCoord;", "void main(void) {", " gl_Position = aVertexPosition;", " vTextureCoord = aTextureCoord;", "}"].join("\n"), n = t.createShader(t.VERTEX_SHADER); t.shaderSource(n, r), t.compileShader(n); var a = ["precision highp float;", "varying lowp vec2 vTextureCoord;", "uniform sampler2D YTexture;", "uniform sampler2D UTexture;", "uniform sampler2D VTexture;", "const mat4 YUV2RGB = mat4", "(", " 1.1643828125, 0, 1.59602734375, -.87078515625,", " 1.1643828125, -.39176171875, -.81296875, .52959375,", " 1.1643828125, 2.017234375, 0, -1.081390625,", " 0, 0, 0, 1", ");", "void main(void) {", " gl_FragColor = vec4( texture2D(YTexture, vTextureCoord).x, texture2D(UTexture, vTextureCoord).x, texture2D(VTexture, vTextureCoord).x, 1) * YUV2RGB;", "}"].join("\n"), s = t.createShader(t.FRAGMENT_SHADER); t.shaderSource(s, a), t.compileShader(s), t.attachShader(i, n), t.attachShader(i, s), t.linkProgram(i), t.useProgram(i), t.getProgramParameter(i, t.LINK_STATUS) || console.log("[ER] Shader link failed."); var o = t.getAttribLocation(i, "aVertexPosition"); t.enableVertexAttribArray(o); var l = t.getAttribLocation(i, "aTextureCoord"); t.enableVertexAttribArray(l); var u = t.createBuffer(); t.bindBuffer(t.ARRAY_BUFFER, u), t.bufferData(t.ARRAY_BUFFER, new Float32Array([1, 1, 0, -1, 1, 0, 1, -1, 0, -1, -1, 0]), t.STATIC_DRAW), t.vertexAttribPointer(o, 3, t.FLOAT, !1, 0, 0); var c = t.createBuffer(); t.bindBuffer(t.ARRAY_BUFFER, c), t.bufferData(t.ARRAY_BUFFER, new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]), t.STATIC_DRAW), t.vertexAttribPointer(l, 2, t.FLOAT, !1, 0, 0), t.y = new Texture(t), t.u = new Texture(t), t.v = new Texture(t), t.y.bind(0, i, "YTexture"), t.u.bind(1, i, "UTexture"), t.v.bind(2, i, "VTexture") } else console.log("[ER] WebGL not supported.") } WebGLPlayer.prototype.renderFrame = function (e, t, i, r, n, a, s) { if (this.gl) { var o = this.gl; o.viewport(0, 0, o.canvas.width, o.canvas.height), o.clearColor(0, 0, 0, 0), o.clear(o.COLOR_BUFFER_BIT), o.y.fill(r, n, e), o.u.fill(r >> 1, n >> 1, t), o.v.fill(r >> 1, n >> 1, i), o.drawArrays(o.TRIANGLE_STRIP, 0, 4) } else console.log("[ER] Render frame failed due to WebGL not supported.") } // ------------------ wasm player ---------------// function Player(cvsEel, isLive, codecId, duration, workerPath = '') { this.workerPath = workerPath this._pcmPlayer = null; this.canvas = cvsEel; this.webglPlayer = null; this._duration = 0; this.pixFmt = 0; this.videoWidth = 0; this.videoHeight = 0; this.yLength = 0; this.uvLength = 0; this.audioTimeOffset = 0; this.decoderState = 0; this.playerState = 0; this.decoding = false; this.displaying = false; this.decodeInterval = 1; this.audioQueue = []; this.videoQueue = []; this.decodeWorker = null; this._frameCount = 0; this.decoderCount = 0; this.ID = Math.floor(1e4 * Math.random() + 500); this._codecId = codecId || 0; duration && (this._duration = (duration - 0) / 1e3); this._currentPts = 0; this._firstPts = 0; this._endPts = this._firstPts + 1e3 * this._duration; this._playbackOffset = 0; this._currentTime = 0; this._bufferedPts = 0; this._seekPts = -1; this._seekPtsPre = 0; this._seekIFrame = false; this._streamPaused = false; this._shootingInfo = null; this._shooting = false; this._islive = isLive; this._onstreamPuase = null; this._speed = 1; this._playbackMode = 1; this._displayTimer = null; this._emitter = new EventEmitter(); } //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>对外接口>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // 喂数据 Player.prototype.inputData = function (e, t) { if (0 != this.playerState) { if (this._seekIFrame) { if (1 != t.frameType) return; if (t.pts > this._bufferedPts && t.pts - this._bufferedPts < 300) return; this._seekIFrame = false } this._playbackMode < 0 && !this._pauseByBegintime && (t.pts < this._firstPts || 0 < this._endPts && t.pts > this._endPts && t.pts > d) && (this._pauseByBegintime = true, this._OnPauseFeeding()), this._bufferedPts = t.pts; var i = { t: 4, s: t.pts, k: t.frameType, d: t.data }; this.decodeWorker.postMessage(i, [i.d.buffer]) } } Player.prototype.catchPicture = function (e, t, i, r) { t = t || "jpeg"; var n = this.videoWidth, a = this.videoHeight, s = parseInt(i || -1), o = parseInt(r || -1); n < s && (s = n), a < o && (o = a), 0 < s && o <= 0 ? o = Math.ceil(s * a / n) : 0 < o && s <= 0 ? s = Math.ceil(n * o / a) : s <= 0 && o <= 0 && (s = n, o = a), e.width = s, e.height = o, 2 == this.playerState || this.playerStateStepPlaying, e.getContext("2d").drawImage(this.canvas, 0, 0, n, a, 0, 0, s, o); try { return e.toDataURL("image/" + t) } catch (e) { return console.log(" wasmPlayer catchPicture " + e.name + " " + e.code + " " + e.message), "" } } Player.prototype.continuousShooting = function (e, t, i, r, n, a) { if (0 == this._shooting && 0 <= i) { t = t || "jpeg"; var s = this.videoWidth, o = this.videoHeight, l = parseInt(n || -1), u = parseInt(a || -1); s < l && (l = s), o < u && (u = o), 0 < l && u <= 0 ? u = Math.ceil(l * o / s) : 0 < u && l <= 0 ? l = Math.ceil(s * u / o) : l <= 0 && u <= 0 && (l = s, u = o), e.width = l, e.height = u, e.getContext("2d").drawImage(this.canvas, 0, 0, s, o, 0, 0, l, u); try { r(0, e.toDataURL("image/" + t)) } catch (e) { return r(-1, "continuousShooting " + e.name + " " + e.code + " " + e.message), false } return 1 < i && (this._shooting = true, this._shootingInfo = { cvs: e, count: i, index: 1, callback: r, type: t }), true } return false } Player.prototype.play = function () { var e = { e: 0, m: "Success" }; do { if (2 == this.playerState || 3 == this.playerState) { e = this.resume(); break } if (1 == this.playerState) break; if (!this.decodeWorker) { e = { e: -4, m: "Decoder not initialized" }; break } this.playerState = 1; this.webglPlayer = new WebGLPlayer(this.canvas, { preserveDrawingBuffer: false }); this.decodeWorker.postMessage({ t: 0, c: 65536 }); this.decodeWorker.postMessage({ t: 2, cd: this._codecId, l: this._islive }) } while (0); return e } Player.prototype.pause = function () { return 1 != this.playerState ? { e: -1, m: "Not playing" } : (this.playerState = 2, this._pcmPlayer && this._pcmPlayer.pause(), this._pauseDecoding(), { e: 0, m: "Success" }) } Player.prototype.singleFramePlay = function () { 1 == this.playerState ? (this.pause(), this.playerState = 3) : 2 != this.playerState && 3 != this.playerState || (this.playerState = 3, this._displayNextVideoFrame()) } Player.prototype.resume = function () { if (2 != this.playerState && 3 != this.playerState) return { e: -1, m: "Not pausing" }; if (this._pcmPlayer) for (this._pcmPlayer.resume(); 0 < this.audioQueue.length;) { var e = this.audioQueue.shift(); this._pcmPlayer.play(e) } return this.playerState = 1, this.displaying = true, this._displayNextVideoFrame(), this._startDecoding(), { e: 0, m: "Success" } } Player.prototype.destroy = function () { if (0 != this.playerState) return this._displayTimer && (clearInterval(this._displayTimer), this._displayTimer = null), this.webglPlayer && (this.webglPlayer.destroy(), this.webglPlayer = null), this.canvas = null, this._duration = 0, this.pixFmt = 0, this.videoWidth = 0, this.videoHeight = 0, this.yLength = 0, this.uvLength = 0, this.audioTimeOffset = 0, this.decoderState = 0, this.playerState = 0, this.decoding = false, this.displaying = false, this.audioQueue = [], this.videoQueue = [], this._pcmPlayer && (this._pcmPlayer.destroy(), this._pcmPlayer = null), this.decodeWorker.postMessage({ t: 3 }), this.decodeWorker.postMessage({ t: 1 }), this.decodeWorker.terminate(), this.decodeWorker = null, e; var e = { e: -1, m: "Not playing" }; return e } Player.prototype.setPlaybackMode = function (e, t) { (e < 0 && 0 < this._playbackMode || 0 < e && this._playbackMode < 0) && (this.videoQueue = [], this._startDecoding(true), this._playbackMode = e, this._seekPtsPre = 0, this._seekPts = 1e3 * t + this._firstPts, this._streamPaused = false, this._pauseByBegintime = false) } Player.prototype.setPlaybackOffset = function (e) { this._playbackOffset = e } Player.prototype.setDidirectPlayTime = function (e) { if (!this.decodeWorker) return false; var t = this._pauseByBegintime = false, i = 1e3 * e + this._firstPts; if (0 < this._playbackMode && this._currentPts <= i && this._bufferedPts > i) { var r = this.videoQueue.length; 0 < r && this.videoQueue[r - 1].s >= i ? t = true : this.decodeWorker.postMessage({ t: 7, s: i }), this._emitter.emit(EventInfo.VIDEOSEEK, e), t = true } else if (this._playbackMode < 0 && this._currentPts >= i && this._bufferedPts < i) t = true; else { this._seekPts = i, 14 != this._codecId && (this._seekIFrame = true), this._seekPtsPre = this._currentPts, this.videoQueue = [], this._startDecoding(true), t = false, this._currentTime = e; var n = this; this._seekTimer = setTimeout(function () { -1 != n._seekPts && (n._seekPts = -1) }, 5e3) } return (this.resume(), this._streamPaused = false, t) } Player.prototype.on = function (e, t) { this._emitter.addListener(e, t) } Player.prototype.off = function (e, t) { this._emitter.removeListener(e, t) } Player.prototype.initDecodeWorker = function () { var i = this; const path = (this.workerPath || '/') + 'decoder.worker.js' try { var e = this.decodeWorker = new Worker(path); e.onerror = function (e) { console.log(e) }; e.onmessage = function (e) { var t = e.data; // console.log('t:',t) switch (t.t) { case 0: i._onInitDecoder(t); break; case 2: i._onOpenDecoder(t); break; case 4: i._onVideoFrame(t); break; case 5: i._onAudioFrame(t); break; case 8: i._onDecodeFinished(t); break; case 9: i._OnStartFeeding(); break; case 10: i._OnPauseFeeding(); break; case 11: case 12: i._OnDecoderError(t.t) } } } catch (e) { this._emitter.emit(EventInfo.ERROR, 'wasmPlayer init error') } } Player.prototype._onInitDecoder = function (e) { 0 != e.e && this._emitter.emit(EventInfo.ERROR, 'WASM_INIT_ERROR') } Player.prototype._onOpenDecoder = function (e) { 0 != this.playerState && (0 == e.e ? (this.decoderState = 2, this._startDecoding()) : this._emitter.emit(EventInfo.ERROR, 'WASM_INIT_ERROR')) } Player.prototype._onAudioParam = function (e) { if (0 != this.playerState) { var t = e.f, i = e.c, r = e.r, n = "16bitInt"; switch (t) { case 0: n = "8bitInt"; break; case 1: n = "16bitInt"; break; case 2: n = "32bitInt"; break; case 3: n = "32bitFloat" } this._pcmPlayer = new PCMPlayer({ encoding: n, channels: i, sampleRate: r, flushingTime: 5e3 }), this.audioTimeOffset = this._pcmPlayer.getTimestamp() } } Player.prototype._onAudioFrame = function (e) { switch (this.playerState) { case 1: this._pcmPlayer.play(e.d); break; case 2: case 3: this.audioQueue.push(e.d) } } Player.prototype._onDecodeFinished = function (e) { } Player.prototype._OnStartFeeding = function () { this._pauseByBegintime ? console.log("_OnStartFeeding _pauseByBegintime") : (this._onstreamPuase && this._onstreamPuase(false), this._emitter.emit(EventInfo.STREAMPAUSE, false)) } Player.prototype._OnPauseFeeding = function () { this._onstreamPuase && this._onstreamPuase(true), this._emitter.emit(EventInfo.STREAMPAUSE, true) } Player.prototype._OnDecoderError = function (e) { 11 == e ? this._emitter.emit(EventInfo.ERROR, 'WASM_DECODER_ERROR') : 12 == e && this._emitter.emit(EventInfo.ERROR, 'WASM_LOAD_ERROR') } Player.prototype._onVideoFrame = function (e) { if (0 != this.playerState) { if (this.decoderCount++, this.videoWidth == e.w && this.videoHeight == e.h || (this.videoWidth = e.w, this.videoHeight = e.h, this.yLength = this.videoWidth * this.videoHeight, this.uvLength = this.videoWidth / 2 * (this.videoHeight / 2)), 0 < this._playbackMode) this.displaying || 1 != this.playerState ? (this.videoQueue.push(e), 16 <= this.videoQueue.length && this.decoding && this._pauseDecoding()) : (this.displaying = true, this._renderVideoFrame(e)); else { var t = this.videoQueue, i = t[t.length - 1]; if (i || (i = [], t.push(i)), 0 < i.length) { var r = i[i.length - 1].s - e.s; if (0 < r || r < -2e3) { if (-1 != this._seekPts && i.length <= 2) return void t.pop(); i.reverse(); var n = []; n.push(e), t.push(n) } else i.push(e) } else i.push(e); !this.displaying && 1 < t.length && 1 == this.playerState && this._displayNextVideoFrame(), 4 <= this.videoQueue.length && this.decoding && this._pauseDecoding() } 1 == this.decoderCount && this._emitter.emit(EventInfo.FIRST_CANPLAY, e) } } Player.prototype._displayNextVideoFrame = function () { var i = this; this._displayTimer || (this._displayTimer = setInterval(function () { if (0 < i._playbackMode) { if (0 == i.videoQueue.length) i.displaying = false, i._displayTimer && clearInterval(i._displayTimer), i._displayTimer = null; else { var e = i.videoQueue.shift(); i._renderVideoFrame(e) } !i.decoding && i.videoQueue.length < 8 && i._startDecoding() } else { if (i.videoQueue.length <= 1) i.displaying = false, i._displayTimer && clearInterval(i._displayTimer), i._displayTimer = null; else { var t = i.videoQueue[0]; e = t.shift(), i._renderVideoFrame(e), 0 == t.length && i.videoQueue.shift() } i._currentTime < 0 ? 0 == i._streamPaused && (i._OnPauseFeeding(), i._pauseDecoding(), i._streamPaused = true, i.displaying = false, i._displayTimer && clearInterval(i._displayTimer), i._displayTimer = null, i.videoQueue = []) : !i.decoding && i.videoQueue.length <= 2 && i._startDecoding() } if (1 != i.playerState) return i._displayTimer && clearInterval(i._displayTimer), void (i._displayTimer = null) }, this._islive ? 0 : 40 / this._speed)) } Player.prototype._displayNextVideoFrame_bak = function () { var i = this; setTimeout(function () { if (1 == i.playerState || 3 == i.playerState) if (0 < i._playbackMode) { if (0 == i.videoQueue.length) i.displaying = false; else { var e = i.videoQueue.shift(); i._renderVideoFrame(e) } !i.decoding && i.videoQueue.length < 8 && i._startDecoding() } else if (i.videoQueue.length <= 1) i.displaying = false; else { var t = i.videoQueue[0]; e = t.shift(), i._renderVideoFrame(e), 0 == t.length && i.videoQueue.shift() } }, this._islive ? 0 : 40 / this._speed) } Player.prototype._renderVideoFrame = function (e) { if (this._currentPts = e.s, this._frameCount++, this.webglPlayer.renderFrame(e.y, e.u, e.v, e.ly, this.videoHeight, this.yLength, this.uvLength), -1 == this._seekPts ? (this._currentTime = (e.s - this._firstPts) / 1e3, this._pauseByBegintime && this._currentTime > d && (this._currentTime = 0), this._emitter.emit(EventInfo.PLAYTIME, 0 < this._currentTime ? this._currentTime : 0)) : (0 < this._playbackMode ? (this._seekPtsPre >= this._seekPts && e.s < this._seekPtsPre || this._seekPtsPre <= this._seekPts && -1e3 < this._seekPts - e.s && this._seekPts - e.s < 3e3) && (this._seekPts = -1) : this._seekPts = -1, -1 == this._seekPts && (this._currentTime = (e.s - this._firstPts) / 1e3, this._emitter.emit(EventInfo.PLAYTIME, 0 < this._currentTime ? this._currentTime : 0), this._emitter.emit(EventInfo.VIDEOSEEK, this._currentTime))), this._shooting && this._shootingInfo) { var t = this._shootingInfo; t.cvs.getContext("2d").drawImage(this.canvas, 0, 0, e.w, e.h, 0, 0, t.cvs.width, t.cvs.height); try { t.callback(t.index, t.cvs.toDataURL("image/" + t.type)) } catch (e) { t.callback(-1, "continuousShooting " + e.name + " " + e.code + " " + e.message) } t.index++, t.index == t.count && (this._shooting = false, this._shootingInfo = null) } 0 == this.videoQueue.length || 1 != this.playerState ? this.displaying = false : this._displayNextVideoFrame() } Player.prototype._startDecoding = function (e) { if (this.decodeWorker) { var t = { t: 5, i: this._speed, d: e || false }; this.decodeWorker.postMessage(t), this.decoding = true } } Player.prototype._pauseDecoding = function () { var e = { t: 6 }; this.decodeWorker.postMessage(e), this.decoding = false } Player.prototype._reportPlayError = function (e, t, i) { } Object.defineProperty(Player.prototype, 'codecId', { get: function () { return this._codecId } }) Object.defineProperty(Player.prototype, 'codec', { get: function () { return 7 == this._codecId ? "H264-WASM" : 9 == this._codecId ? "MPEG4" : 12 == this._codecId ? "H265" : 13 == this._codecId ? "SVAC" : 14 == this._codecId ? "MJPEG" : 15 == this._codecId ? "MJPEGB" : void 0 } }) Object.defineProperty(Player.prototype, 'playbackRate', { get: function () { return this._speed }, set: function (e) { 0 != (e -= "0") && (this._speed != e && (this._speed = e, this._displayTimer && (clearInterval(this._displayTimer), this._displayTimer = null), this._displayNextVideoFrame()), this.decodeWorker && this._startDecoding()) } }) Object.defineProperty(Player.prototype, 'playbackMode', { get: function () { return this._playbackMode } }) Object.defineProperty(Player.prototype, 'onstreamPuase', { get: function () { return this._onstreamPuase }, set: function (e) { this._onstreamPuase = e } }) Object.defineProperty(Player.prototype, 'currentTime', { get: function () { return this._currentTime < 0 ? 0 : this._currentTime } }) Object.defineProperty(Player.prototype, 'duration', { get: function () { return this._duration }, set: function (e) { this._duration = (e - "0") / 1e3, this._endPts = this._firstPts + 1e3 * this._duration } }) Object.defineProperty(Player.prototype, 'paused', { get: function () { return 2 == this.playerState || 3 == this.playerState } }) Object.defineProperty(Player.prototype, 'decodedFrames', { get: function () { return this._frameCount } }) Object.defineProperty(Player.prototype, 'mediaInfo', { get: function () { return { duration: this._duration, videoWidth: this.videoWidth, videoHeight: this.videoHeight, width: this.videoWidth, height: this.videoHeight, } } }) export { Player, EventInfo }