UNPKG

trtc-electron-sdk

Version:

trtc electron sdk

668 lines (667 loc) 27.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.V2LivePusher = void 0; const events_1 = require("events"); const live_define_1 = require("../live_define"); const trtc_define_1 = require("../../trtc_define"); const video_render_1 = require("../video-render"); const converter_1 = require("../converter"); const logger_1 = require("../../logger"); const NodeTRTCEngine = require('../../../build/Release/trtc_electron_sdk.node'); /** * 腾讯云直播推流器 * * @example * * // 创建/销毁 V2LivePusher 对象,以及回调事件监听。 * * import { V2LivePusher } from 'trtc-electron-sdk'; * const livePusher = V2LivePusher.createV2LivePusher(V2LiveMode.V2LiveModeRTMP); * * subscribeEvents = (livePusher) => { * livePusher.on('onError', (errcode, errmsg) => { * console.info('livePusher_demo: onError :' + errcode + " msg" + errmsg); * }); * }; * * V2LivePusher.releaseV2LivePusher(livePusher); * */ class V2LivePusher { constructor(mode) { this.livePusher = new NodeTRTCEngine.NodeV2LivePusher(mode); this.initObserver(); this.deviceManager = this.livePusher.getDeviceManager(); this.pusherVideoRender = null; this.cameraTestVideoRender = null; this.pixelFormat = live_define_1.V2LivePixelFormat.V2LivePixelFormatI420; this.eventEmitter = new events_1.EventEmitter(); this.logger = new logger_1.Logger(`V2LivePusher`); this._pusherVideoRenderCallback = this._pusherVideoRenderCallback.bind(this); this._cameraTestVideoRenderCallback = this._cameraTestVideoRenderCallback.bind(this); this._createPusherRender(); } /** * 创建 V2LivePusher 实例 * * @param {V2LiveMode} mode - 推流模式,参考 V2LiveMode 的定义。 * @return {V2LivePusher} - 推流器实例 */ static createV2LivePusher(mode) { return new V2LivePusher(mode); } /** * 析构 V2LivePusher 对象 * * @param {V2LivePusher} v2livepusher - 推流器实例 */ static releaseV2LivePusher(livePusher) { livePusher.destroy(); } destroy() { this._destroyPusherRender(); this._destroyCameraTestRender(); this.livePusher.destroy(); this.livePusher = null; this.deviceManager = null; } /** * 监听 LivePusher 对象事件。 * * @param {V2LivePusherEvent} event - 事件名称。 * @param {Function} listener - 事件回调函数。 */ on(event, listener) { this.eventEmitter.on(event, listener); } /** * 取消监听 LivePusher 对象事件。 * * @param {V2LivePusherEvent} event - 事件名称。 * @param {Function} listener - 事件回调函数。 */ off(event, listener) { this.eventEmitter.off(event, listener); } ///////////////////////////////////////////////////////////////////////////////// // // (一)LivePusher相关接口函数 // ///////////////////////////////////////////////////////////////////////////////// /** * 设置本地摄像头预览 View, 本地摄像头采集到的画面,最终会显示到传入的 View 上。 * * @param {HTMLElement | null} view - 本地摄像头预览 View。 */ setRenderView(view) { var _a; this.logger.debug(`setRenderView view:${view}`); (_a = this.pusherVideoRender) === null || _a === void 0 ? void 0 : _a.setRenderView(view); } /** * 设置本地摄像头预览镜像 * @param {V2LiveMirrorType} mirrorType - 摄像头镜像类型, 默认值为 V2LiveMirrorTypeAuto。 * V2LiveMirrorTypeEnable 前置摄像头 和 后置摄像头,都切换为镜像模式。 * V2LiveMirrorTypeDisable 前置摄像头 和 后置摄像头,都切换为非镜像模式。 * * @return {Number} - 参考 V2LiveCode 的定义 */ setRenderMirror(mirrorType) { var _a; this.logger.debug(`setRenderMirror mirrorType:${mirrorType}`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.setRenderMirror(mirrorType); } /** * 设置视频编码镜像,默认不开启。 * 编码镜像只影响观众端看到的视频效果 * * @param {Boolean} mirror - 是否镜像。 * @return {Number} - 参考 V2LiveCode 的定义 */ setEncoderMirror(mirror) { var _a; this.logger.debug(`setEncoderMirror mirror:${mirror}`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.setEncoderMirror(mirror); } /** * 设置本地摄像头预览画面的旋转角度, 默认不旋转。 * 只旋转本地预览画面,不影响推流出去的画面 * * @param {V2LiveRotation} rotation - 预览画面的旋转角度, 参考 V2LiveRotation 的定义。 * @return {Number} - 参考 V2LiveCode 的定义 */ setRenderRotation(rotation) { var _a; this.logger.debug(`setRenderRotation rotation:${rotation}`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.setRenderRotation(rotation); } /** * 设置本地摄像头预览画面的填充模式 * * @param {V2LiveFillMode} mode - 画面填充模式,参考 V2LiveFillMode 的定义。 * @return {Number} - 参考 V2LiveCode 的定义 */ setRenderFillMode(mode) { var _a, _b; this.logger.debug(`setRenderFillMode mode:${mode}`); (_a = this.pusherVideoRender) === null || _a === void 0 ? void 0 : _a.setVideoFillMode((0, converter_1.convertFillModeFromLive)(mode)); return (_b = this.livePusher) === null || _b === void 0 ? void 0 : _b.setRenderFillMode(mode); } /** * 打开本地摄像头 * * @param {String} cameraId - 摄像头ID,可通过 getCameraDevicesList 获取。 * @return {Number} - 参考 V2LiveCode 的定义 */ startCamera(cameraId) { var _a, _b; this.logger.debug(`startCamera cameraId:${cameraId}`); (_a = this.pusherVideoRender) === null || _a === void 0 ? void 0 : _a.createRender(); this._setVideoRenderBuffer(); this._addVideoRenderCallback(); this.enableCustomVideoRender(true, this.pixelFormat, live_define_1.V2LiveBufferType.V2LiveBufferTypeByteBuffer); return (_b = this.livePusher) === null || _b === void 0 ? void 0 : _b.startCamera(cameraId); } /** * 关闭本地摄像头 * * @return {Number} - 参考 V2LiveCode 的定义 */ stopCamera() { var _a, _b; this.logger.debug(`stopCamera`); (_a = this.pusherVideoRender) === null || _a === void 0 ? void 0 : _a.destroyRender(); this._removeVideoRenderCallback(); this.enableCustomVideoRender(false, this.pixelFormat, live_define_1.V2LiveBufferType.V2LiveBufferTypeByteBuffer); return (_b = this.livePusher) === null || _b === void 0 ? void 0 : _b.stopCamera(); } /** * 打开麦克风 * * @return {Number} - 参考 V2LiveCode 的定义 */ startMicrophone() { var _a; this.logger.debug(`startMicrophone`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.startMicrophone(); } /** * 关闭麦克风 * * @return {Number} - 参考 V2LiveCode 的定义 */ stopMicrophone() { var _a; this.logger.debug(`stopMicrophone`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.stopMicrophone(); } /** * 暂停推流器的音频流 * * @return {Number} - 参考 V2LiveCode 的定义 */ pauseAudio() { var _a; this.logger.debug(`pauseAudio`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.pauseAudio(); } /** * 恢复推流器的音频流 * * @return {Number} - 参考 V2LiveCode 的定义 */ resumeAudio() { var _a; this.logger.debug(`resumeAudio`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.resumeAudio(); } /** * 暂停推流器的视频流 * * @return {Number} - 参考 V2LiveCode 的定义 */ pauseVideo() { var _a; this.logger.debug(`pauseVideo`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.pauseVideo(); } /** * 恢复推流器的视频流 * * @return {Number} - 参考 V2LiveCode 的定义 */ resumeVideo() { var _a; this.logger.debug(`resumeVideo`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.resumeVideo(); } /** * 开始音视频数据推流 * * @param {String} url - 推流的目标地址,支持任意推流服务端。 * @return {Number} - 参考 V2LiveCode 的定义 */ startPush(url) { var _a; this.logger.debug(`startPush, url:${url}`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.startPush(url); } /** * 停止推送音视频数据 * * @return {Number} - 参考 V2LiveCode 的定义 */ stopPush() { var _a; this.logger.debug(`stopPush`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.stopPush(); } /** * 当前推流器是否正在推流中 * * @return {Number} - 参考 V2LiveCode 的定义 */ isPushing() { return this.livePusher ? this.livePusher.isPushing() : 0; } /** * 设置推流音频质量 * * @param {V2LiveAudioQuality} quality - 音频质量,参考 V2LiveAudioQuality 的定义。 * @return {Number} - 参考 V2LiveCode 的定义 */ setAudioQuality(quality) { var _a; this.logger.debug(`setAudioQuality, quality:${quality}`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.setAudioQuality(quality); } /** * 设置推流视频编码参数 * * @param {V2LiveVideoEncoderParam} param - 视频编码参数,参考 V2LiveVideoEncoderParam 的定义。 * @return {Number} - 参考 V2LiveCode 的定义 */ setVideoQuality(param) { var _a; this.logger.debug(`setVideoQuality, param:${param}`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.setVideoQuality(param); } /** * 启用采集音量大小提示 * * @param {Number} intervalMs - 决定了 onMicrophoneVolumeUpdate 回调的触发间隔,单位为ms,最小间隔为100ms,如果小于等于0则会关闭回调,建议设置为300ms;【默认值】:0,不开启。 * @return {Number} - 参考 V2LiveCode 的定义 */ enableVolumeEvaluation(intervalMs) { var _a; this.logger.debug(`enableVolumeEvaluation, intervalMs:${intervalMs}`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.enableVolumeEvaluation(intervalMs); } /** * 设置云端的混流转码参数 * * @param {V2TXLiveTranscodingConfig | null} config - 混流转码参数,参考 V2TXLiveTranscodingConfig 的定义。如果传入 null 则取消云端混流转码。 * @return {Number} */ setMixTranscodingConfig(config) { var _a; this.logger.debug(`setMixTranscodingConfig, config:${config}`); return (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.setMixTranscodingConfig(config); } ///////////////////////////////////////////////////////////////////////////////// // // (二)deviceManager相关接口函数 // ///////////////////////////////////////////////////////////////////////////////// /** * 获取摄像头设备列表 * * @example * var cameralist = livePusher.getCameraDevicesList(); * for (i=0;i<cameralist.length;i++) { * var camera = cameralist[i]; * console.info("camera deviceName: " + camera.deviceName + " deviceId:" + camera.deviceId); * } * @return {Array<TRTCDeviceInfo>} 摄像头管理器列表 */ getCameraDevicesList() { return this.deviceManager.getDevicesList(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeCamera); } /** * 设置要使用的摄像头 * * @param {String} deviceId - 从 getCameraDevicesList 中得到的设备 ID */ setCurrentCameraDevice(deviceId) { this.logger.debug(`setCurrentCameraDevice, deviceId:${deviceId}`); this.deviceManager.setCurrentDevice(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeCamera, deviceId); } /** * 获取当前使用的摄像头 * * @return {TRTCDeviceInfo} 设备信息,能获取设备 ID 和设备名称 */ getCurrentCameraDevice() { return this.deviceManager.getCurrentDevice(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeCamera); } /** * 开始摄像头测试 * * @param {HTMLElement} view - 摄像头测试的显示区域 */ startCameraDeviceTest(view) { this.logger.debug(`startCameraDeviceTest`); if (view === null) { return; } if (this.cameraTestVideoRender === null) { // camera videoRender this.cameraTestVideoRender = new video_render_1.VideoRender(); this.cameraTestVideoRender.setRenderView(view); this.cameraTestVideoRender.setVideoFillMode(trtc_define_1.TRTCVideoFillMode.TRTCVideoFillMode_Fit); const trtcPixelFormat = (0, converter_1.convertPixelFormatFromLive)(this.pixelFormat); this.cameraTestVideoRender.setVideoPixelFormat(trtcPixelFormat); // camera vudeoRender buffer const videoBuffer = this.cameraTestVideoRender.getVideoBuffer(); this.deviceManager.setCameraTestVideoBuffer(videoBuffer.buffer, videoBuffer.width, videoBuffer.height, videoBuffer.pixelFormat, videoBuffer.id); } this.deviceManager.startCameraDeviceTest(this._cameraTestVideoRenderCallback); } /** * 停止摄像头测试 */ stopCameraDeviceTest() { var _a; this.logger.debug(`stopCameraDeviceTest`); this.deviceManager.stopCameraDeviceTest(); (_a = this.cameraTestVideoRender) === null || _a === void 0 ? void 0 : _a.destroy(); this.cameraTestVideoRender = null; } /** * 获取麦克风设备列表 * * @example * var miclist = livePusher.getMicDevicesList(); * for (i=0;i<miclist.length;i++) { * var mic = miclist[i]; * console.info("mic deviceName: " + mic.deviceName + " deviceId:" + mic.deviceId); * } * @return {Array<TRTCDeviceInfo>} 麦克风管理器列表 */ getMicDevicesList() { return this.deviceManager.getDevicesList(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeMic); } /** * 获取当前选择的麦克风 * * @return {TRTCDeviceInfo} 设备信息,能获取设备 ID 和设备名称 */ getCurrentMicDevice() { return this.deviceManager.getCurrentDevice(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeMic); } /** * 设置要使用的麦克风 * * 选择指定的麦克风作为录音设备,不调用该接口时,默认选择索引为0的麦克风 * * @param {String} micId - 从 getMicDevicesList 中得到的设备 ID */ setCurrentMicDevice(micId) { this.logger.debug(`setCurrentMicDevice, micId:${micId}`); this.deviceManager.setCurrentDevice(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeMic, micId); } /** * 获取系统当前麦克风设备音量 * * 注意:查询的是系统硬件音量大小。 * @return {Number} 音量值,范围是0 - 100 */ getCurrentMicDeviceVolume() { return this.deviceManager.getCurrentDeviceVolume(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeMic); } /** * 设置系统当前麦克风设备的音量 * * 注意:该接口的功能是调节系统采集音量,如果用户直接调节系统设置的采集音量时,该接口的设置结果会被用户的操作所覆盖。 * @param {Number} volume - 麦克风音量值,范围0 - 100 */ setCurrentMicDeviceVolume(volume) { this.logger.debug(`setCurrentMicDeviceVolume, volume:${volume}`); this.deviceManager.setCurrentDeviceVolume(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeMic, volume); } /** * 设置系统当前麦克风设备的静音状态 * * @param {Boolean} mute 设置为 true 时,麦克风设备静音;设置为 false时,麦克风设备取消静音 */ setCurrentMicDeviceMute(mute) { this.logger.debug(`setCurrentMicDeviceMute, mute:${mute}`); this.deviceManager.setCurrentDeviceMute(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeMic, mute); } /** * 获取系统当前麦克风设备是否静音 * * @return {Boolean} 静音状态 */ getCurrentMicDeviceMute() { return this.deviceManager.getCurrentDeviceMute(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeMic); } /** * 获取扬声器设备列表 * * @example * var speakerlist = livePusher.getSpeakerDevicesList(); * for (i=0;i<speakerlist.length;i++) { * var speaker = speakerlist[i]; * console.info("mic deviceName: " + speaker.deviceName + " deviceId:" + speaker.deviceId); * } * @return {Array<TRTCDeviceInfo>} 扬声器管理器列表 */ getSpeakerDevicesList() { return this.deviceManager.getDevicesList(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeSpeaker); } /** * 获取当前的扬声器设备 * * @return {TRTCDeviceInfo} 设备信息,能获取设备 ID 和设备名称 */ getCurrentSpeakerDevice() { return this.deviceManager.getCurrentDevice(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeSpeaker); } /** * 设置要使用的扬声器 * * @param {String} speakerId - 从 getSpeakerDevicesList 中得到的设备 ID */ setCurrentSpeakerDevice(speakerId) { this.logger.debug(`setCurrentSpeakerDevice, speakerId:${speakerId}`); this.deviceManager.setCurrentDevice(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeSpeaker, speakerId); } /** * 获取系统当前扬声器设备音量 * * @return {Number} 扬声器音量,范围0 - 100 */ getCurrentSpeakerVolume() { return this.deviceManager.getCurrentDeviceVolume(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeSpeaker); } /** * 设置系统当前扬声器设备音量 * * 注意:该接口的功能是调节系统播放音量,如果用户直接调节系统设置的播放音量时,该接口的设置结果会被用户的操作所覆盖。 * * @param {Number} volume - 设置的扬声器音量,范围0 - 100 */ setCurrentSpeakerVolume(volume) { this.logger.debug(`setCurrentSpeakerVolume, volume:${volume}`); this.deviceManager.setCurrentDeviceVolume(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeSpeaker, volume); } /** * 设置系统当前扬声器设备的静音状态 * * @param {Boolean} mute 设置为 true 时,扬声器设备静音;设置为 false时,扬声器设备取消静音 */ setCurrentSpeakerDeviceMute(mute) { this.logger.debug(`setCurrentSpeakerDeviceMute, mute:${mute}`); this.deviceManager.setCurrentDeviceMute(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeSpeaker, mute); } /** * 获取系统当前扬声器设备是否静音 * * @return {Boolean} 静音状态 */ getCurrentSpeakerDeviceMute() { return this.deviceManager.getCurrentDeviceMute(trtc_define_1.TRTCDeviceType.TRTCDeviceTypeSpeaker); } /** * 设置 SDK 使用的音频设备自动跟随系统默认设备 * * 仅支持设置麦克风和扬声器类型,摄像头暂不支持跟随系统默认设备 * * @param {TRTCDeviceType} deviceType - 设备类型,只支持麦克风和扬声器,摄像头不支持 * @param {Boolean} enable - 是否跟随系统默认的音频设备 * - true: 跟随。当系统默认音频设备发生改变时,SDK 立即切换音频设备。 * - false: 不跟随。只有当 SDK 使用的音频设备被移除后或插入新的音频设备为系统默认设备时,SDK 才切换至系统默认的音频设备。 */ enableFollowingDefaultAudioDevice(deviceType, enable) { this.logger.debug(`enableFollowingDefaultAudioDevice, deviceType:${deviceType}, enable:${enable}`); this.deviceManager.enableFollowingDefaultAudioDevice(deviceType, enable); } /** * 设置摄像头采集偏好 * * @param {TRTCCameraCaptureParams} params - 摄像头采集参数 */ setCameraCapturerParam(params) { var _a; this.logger.debug(`setCameraCapturerParam, params:${JSON.stringify(params)}`); (_a = this.deviceManager) === null || _a === void 0 ? void 0 : _a.setCameraCapturerParam(params); } //////////////////////////////////////////////////////////////////////////////// // // 内部接口 // //////////////////////////////////////////////////////////////////////////////// enableCustomVideoRender(enable, pixelFormat, bufferType) { var _a; (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.enableCustomVideoRender(enable, pixelFormat, bufferType); } // videoRender _createPusherRender() { if (this.pusherVideoRender !== null) { return; } this.pusherVideoRender = new video_render_1.VideoRender(); const trtcPixelFormat = (0, converter_1.convertPixelFormatFromLive)(this.pixelFormat); this.pusherVideoRender.setVideoPixelFormat(trtcPixelFormat); } _destroyPusherRender() { if (this.pusherVideoRender) { this.pusherVideoRender.destroy(); this.pusherVideoRender = null; } this._removeVideoRenderCallback(); this.enableCustomVideoRender(false, this.pixelFormat, live_define_1.V2LiveBufferType.V2LiveBufferTypeByteBuffer); } _destroyCameraTestRender() { if (this.cameraTestVideoRender) { this.stopCameraDeviceTest(); } } // videoRender callback and buffer _setVideoRenderBuffer() { var _a; if (this.pusherVideoRender !== null) { const videoBuffer = this.pusherVideoRender.getVideoBuffer(); (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.setVideoRenderBuffer(videoBuffer.buffer, videoBuffer.width, videoBuffer.height, this.pixelFormat, videoBuffer.id); } } _addVideoRenderCallback() { var _a; (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.addVideoRenderCallback(this._pusherVideoRenderCallback); } _removeVideoRenderCallback() { var _a; (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.removeVideoRenderCallback(); } _pusherVideoRenderCallback(args) { if (this.pusherVideoRender) { const [userId, type, width, height, timestamp, rotation, valid, bufferId] = args; const result = this.pusherVideoRender.renderVideoData(userId, type, width, height, timestamp, rotation, valid, bufferId); if (!result) { this._setVideoRenderBuffer(); } } } _cameraTestVideoRenderCallback(args) { if (this.cameraTestVideoRender) { const [userId, type, width, height, timestamp, rotation, valid, bufferId] = args; const result = this.cameraTestVideoRender.renderVideoData(userId, type, width, height, timestamp, rotation, valid, bufferId); if (!result) { const videoBuffer = this.cameraTestVideoRender.getVideoBuffer(); this.deviceManager.setCameraTestVideoBuffer(videoBuffer.buffer, videoBuffer.width, videoBuffer.height, videoBuffer.pixelFormat, videoBuffer.id); } } } initObserver() { var _a; (_a = this.livePusher) === null || _a === void 0 ? void 0 : _a.setObserver((args) => { const key = args[0]; const data = args[1]; switch (key) { case 'onError': this.handleOnError(data.errCode, data.errMsg); break; case 'onWarning': this.handleOnWarning(data.warningCode, data.warningMsg); break; case 'onCaptureFirstAudioFrame': this.handleOnCaptureFirstAudioFrame(); break; case 'onCaptureFirstVideoFrame': this.handleOnCaptureFirstVideoFrame(); break; case 'onMicrophoneVolumeUpdate': this.handleOnMicrophoneVolumeUpdate(data.volume); break; case 'onPushStatusUpdate': this.handleOnPushStatusUpdate(data.status, data.message); break; case 'onStatisticsUpdate': this.handleOnStatisticsUpdate(data.statistics); break; default: break; } }); } // Event Handler define fire(event, ...args) { setImmediate(() => { var _a; (_a = this.eventEmitter) === null || _a === void 0 ? void 0 : _a.emit(event, ...args); }); } handleOnError(errCode, errMsg) { this.fire('onError', errCode, errMsg); } handleOnWarning(warningCode, warningMsg) { this.fire('onWarning', warningCode, warningMsg); } handleOnCaptureFirstAudioFrame() { this.fire('onCaptureFirstAudioFrame'); } handleOnCaptureFirstVideoFrame() { this.fire('onCaptureFirstVideoFrame'); } handleOnMicrophoneVolumeUpdate(volume) { this.fire('onMicrophoneVolumeUpdate', volume); } handleOnPushStatusUpdate(status, message) { this.fire('onPushStatusUpdate', status, message); } handleOnStatisticsUpdate(statistics) { this.fire('onStatisticsUpdate', statistics); } } exports.V2LivePusher = V2LivePusher;