UNPKG

@jxstjh/jhvideo

Version:

HTML5 jhvideo base on MPEG2-TS Stream Player

204 lines (188 loc) 6.74 kB
import { EventEmitter } from 'events' const playType = { REALPLAY: 'realplay', PLAYBACK: 'playback', TALK: 'talk' } class StreamWebsocket { private _ws:any = null private _headBuffer:any = null private _lastCmd:any = null private _receivedSteamHead:boolean = false _requestData={ playUrl:'', playType:'playback', startTime:0, endTime:0, } emitter: any constructor(url:string, playType = 'playback' ) { this.emitter = new EventEmitter() this._requestData.playUrl = url this._requestData.playType = playType } on(event:any, listener:any) { this.emitter.addListener(event, listener); } off(event:any, listener:any) { this.emitter.removeListener(event, listener); } sendArrayBuffer(arrBuf:any) { this._ws.send(arrBuf) } open(url?:string) { return new Promise((resolve, reject) => { this.emitter.on(`cmd.${this._requestData.playType}`, (code:any, mediaInfo:any) => { if (code === 0) { resolve({ code, mediaInfo, playType: this._requestData.playType, head: this._headBuffer }) } else { // resolve({}) reject(code) } }) const _url = url || this._requestData.playUrl this._ws = new WebSocket(_url) this._ws.binaryType = 'arraybuffer' this._ws.onopen = (val:any) => { // console.log('onopen',val) } this._ws.onerror = (err:any) => { // console.log('onerror',err) // this._bError = true } this._ws.onclose = () => { // console.log('close') // if (this._receivedSteamHead) { // this.emitter.emit('stream.interrupt', 'codes.ERR_INTERRUPT') // } this.emitter.emit(`cmd.${this._requestData.playType}`, '0x-000000') } this._ws.onmessage = (msg:any) => { let { data } = msg if (data instanceof ArrayBuffer) { this._handleStream(data) } else if (typeof data === 'string') { this._handleInteract(data) } } }) } /** * 码流处理 * @param {*} bufData * @returns */ _handleStream(bufData:any) { if (!this._receivedSteamHead) { this._headBuffer = bufData this._receivedSteamHead = true let isHead = true if (this.emitter.eventNames().includes(`cmd.${this._requestData.playType}`)) { this.emitter.emit(`cmd.${this._requestData.playType}`, 0) } this.emitter.emit('stream.input', bufData, isHead) } else { this.emitter.emit('stream.input', bufData) } } /** * 交互信息处理 * @param {*} strData */ _handleInteract(strData:any) { let jsonData = JSON.parse(strData) if (!this._lastCmd) { // 开流 let { errorCode, errorMsg } = jsonData if (parseInt(errorCode) === 0) { // 安全认证成功,与服务端建立连接 if (this._requestData.playType === playType.TALK) { this.emitter.emit(`cmd.${this._requestData.playType}`, errorCode, jsonData.audioInfo) } else { this.emitter.emit(`cmd.${this._requestData.playType}`, errorCode) } } else { let errorCodeHex = '0x0' + errorCode.toString(16) this.emitter.emit(`cmd.${this._requestData.playType}`, errorCodeHex, errorMsg) } return } if (jsonData.hasOwnProperty('errorCode')) { // 交互消息 let { errorCode, errorMsg } = jsonData if (parseInt(errorCode) === 0) { this.emitter.emit(`cmd.${this._lastCmd.cmd}`, parseInt(errorCode)) } else { let errorCodeHex = '0x0' + errorCode.toString(16) this.emitter.emit(`cmd.${this._lastCmd.cmd}`, errorCodeHex, errorMsg) } } else { // 服务端主动消息 if (!jsonData.hasOwnProperty('cmd')) { let extra:any = { url: this._requestData.playUrl } let cmd = this._requestData.playType if (this._requestData.playType === playType.PLAYBACK) { extra.startTime = this._requestData.startTime extra.endTime = this._requestData.endTime } this.sendCmd(cmd, extra).catch((err) => { console.error(err) }) } else { let { cmd } = jsonData if (cmd === 'end') { this.emitter.emit('stream.end') this.close() } else if (cmd === 'newStreamFlag') {} } } } sendCmd(cmd, extra = {}) { return new Promise((resolve, reject) => { if (!this._ws && this._ws.readyState !== WebSocket.OPEN) { return reject('意外的状态') } // 设置消息发送监听 this.emitter.once(`cmd.${cmd}`, (code) => { if (code === 0) { resolve('codes.OK') } else { reject(code) } }) // 发送消息 let cmdBody = { cmd, ...extra, sequence: !this._lastCmd ? 0 : this._lastCmd.sequence + 1, } this._ws.send(JSON.stringify(cmdBody)) this._lastCmd = cmdBody }) } destroy() { this.close() if(this.emitter){ this.emitter.removeAllListeners() this.emitter = null; } } close() { if (!this._ws) return let ws = this._ws ws.close(1000) ws.onmessage = null ws.onclose = null ws.onerror = null ws.onopen = null this._ws = null this._receivedSteamHead = false this._lastCmd = null } } export default StreamWebsocket