trtc-electron-sdk
Version:
trtc electron sdk
377 lines (376 loc) • 14.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.V2LivePlayer = void 0;
const events_1 = require("events");
const live_define_1 = require("../live_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
*
* // 创建/销毁 V2LivePlayer 对象,以及回调事件监听。
*
* import { V2LivePlayer } from 'trtc-electron-sdk';
* const livePlayer = V2LivePlayer.createV2LivePlayer();
*
* subscribeEvents = (livePlayer) => {
* livePlayer.on('onError', (errcode, errmsg) => {
* console.info('livePlayer_demo: onError :' + errcode + " msg" + errmsg);
* });
* };
*
* V2LivePlayer.releaseV2livePlayer(livePlayer);
*
*/
class V2LivePlayer {
constructor() {
this.livePlayer = new NodeTRTCEngine.NodeV2LivePlayer();
this.initObserver();
this.playerVideoRender = null;
this.pixelFormat = live_define_1.V2LivePixelFormat.V2LivePixelFormatI420;
this.eventEmitter = new events_1.EventEmitter();
this.logger = new logger_1.Logger(`V2LivePlayer`);
this._playerVideoRenderCallback = this._playerVideoRenderCallback.bind(this);
this._createPlayerRender();
}
/**
* 创建 V2LivePlayer 实例
*
* @return {V2LivePlayer} - 播放器实例
*/
static createV2LivePlayer() {
return new V2LivePlayer();
}
/**
* 析构 V2LivePlayer 对象
*
* @param {V2LivePlayer} livePlayer - 推流器实例
*/
static releaseV2LivePlayer(livePlayer) {
livePlayer.destroy();
}
destroy() {
this._destroyPlayerRender();
this.livePlayer.destroy();
this.livePlayer = null;
}
/**
* 监听 LivePlayer 对象事件。
*
* @param {V2LivePlayerEvent} event - 事件名称。
* @param {Function} listener - 事件回调函数。
*/
on(event, listener) {
this.eventEmitter.on(event, listener);
}
/**
* 取消监听 LivePlayer 对象事件。
*
* @param {V2LivePlayerEvent} event - 事件名称。
* @param {Function} listener - 事件回调函数。
*/
off(event, listener) {
this.eventEmitter.off(event, listener);
}
/////////////////////////////////////////////////////////////////////////////////
//
// (一)LivePlayer相关接口函数
//
/////////////////////////////////////////////////////////////////////////////////
/**
* 设置播放器的视频渲染 View, 播放器的视频最终会显示到传入的 View 上。
*
* @param {HTMLElement | null} view - 播放器的视频渲染 View。
*/
setRenderView(view) {
var _a;
this.logger.debug(`setRenderView view:${view}`);
(_a = this.playerVideoRender) === null || _a === void 0 ? void 0 : _a.setRenderView(view);
}
/**
* 设置播放器画面的旋转角度, 默认不旋转。
*
* @param {V2LiveRotation} rotation - 播放器画面的旋转角度, 参考 V2LiveRotation 的定义。
* @return {Number} - 参考 V2LiveCode 的定义
*/
setRenderRotation(rotation) {
var _a;
this.logger.debug(`setRenderRotation rotation:${rotation}`);
return (_a = this.livePlayer) === 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.playerVideoRender) === null || _a === void 0 ? void 0 : _a.setVideoFillMode((0, converter_1.convertFillModeFromLive)(mode));
return (_b = this.livePlayer) === null || _b === void 0 ? void 0 : _b.setRenderFillMode(mode);
}
/**
* 开始播放音视频流
*
* @param {String} url - 音视频流地址
* @return {Number} - 参考 V2LiveCode 的定义
*/
startPlay(url) {
var _a, _b;
this.logger.debug(`startPlay url:${url}`);
(_a = this.playerVideoRender) === null || _a === void 0 ? void 0 : _a.createRender();
this._setVideoRenderBuffer();
this._addVideoRenderCallback();
this.enableObserveVideoFrame(true, this.pixelFormat, live_define_1.V2LiveBufferType.V2LiveBufferTypeByteBuffer);
return (_b = this.livePlayer) === null || _b === void 0 ? void 0 : _b.startPlay(url);
}
/**
* 停止播放音视频流
*
* @return {Number} - 参考 V2LiveCode 的定义
*/
stopPlay() {
var _a, _b;
this.logger.debug(`stopPlay`);
(_a = this.playerVideoRender) === null || _a === void 0 ? void 0 : _a.destroyRender();
this._removeVideoRenderCallback();
this.enableObserveVideoFrame(false, this.pixelFormat, live_define_1.V2LiveBufferType.V2LiveBufferTypeByteBuffer);
return (_b = this.livePlayer) === null || _b === void 0 ? void 0 : _b.stopPlay();
}
/**
* 播放器是否正在播放中
*
* @return {Number} - 是否正在播放中, 1 表示正在播放中, 0 表示未在播放中
*/
isPlaying() {
var _a;
this.logger.debug(`isPlaying`);
return (_a = this.livePlayer) === null || _a === void 0 ? void 0 : _a.isPlaying();
}
/**
* 暂停播放器的音频流
*
* @return {Number} - 参考 V2LiveCode 的定义
*/
pauseAudio() {
var _a;
this.logger.debug(`pauseAudio`);
return (_a = this.livePlayer) === null || _a === void 0 ? void 0 : _a.pauseAudio();
}
/**
* 恢复播放器的音频流
*
* @return {Number} - 参考 V2LiveCode 的定义
*/
resumeAudio() {
var _a;
this.logger.debug(`resumeAudio`);
return (_a = this.livePlayer) === null || _a === void 0 ? void 0 : _a.resumeAudio();
}
/**
* 暂停播放器的视频流
*
* @return {Number} - 参考 V2LiveCode 的定义
*/
pauseVideo() {
var _a;
this.logger.debug(`pauseVideo`);
return (_a = this.livePlayer) === null || _a === void 0 ? void 0 : _a.pauseVideo();
}
/**
* 恢复播放器的视频流
*
* @return {Number} - 参考 V2LiveCode 的定义
*/
resumeVideo() {
var _a;
this.logger.debug(`resumeVideo`);
return (_a = this.livePlayer) === null || _a === void 0 ? void 0 : _a.resumeVideo();
}
/**
* 设置播放器音量
*
* @param {Number} volume - 音量大小,取值范围0 - 100。【默认值】: 100
* @return {Number} - 参考 V2LiveCode 的定义
*/
setPlayoutVolume(volume) {
var _a;
this.logger.debug(`setPlayoutVolume volume:${volume}`);
return (_a = this.livePlayer) === null || _a === void 0 ? void 0 : _a.setPlayoutVolume(volume);
}
/**
* 设置播放器缓存自动调整的最小和最大时间
*
* @param {Number} minTime - 缓存自动调整的最小时间,取值需要大于0。【默认值】:1
* @param {Number} maxTime - 缓存自动调整的最大时间,取值需要大于0。【默认值】:5
* @return {Number} - 参考 V2LiveCode 的定义
*/
setCacheParams(minTime, maxTime) {
var _a;
this.logger.debug(`setCacheParams minTime:${minTime}, maxTime:${maxTime}`);
return (_a = this.livePlayer) === null || _a === void 0 ? void 0 : _a.setCacheParams(minTime, maxTime);
}
/**
* 直播流无缝切换,支持 FLV 和 LEB
*
* @param {String} url - 新的拉流地址
* @return {Number} - 参考 V2LiveCode 的定义
*/
switchStream(newUrl) {
var _a;
this.logger.debug(`switchStream newUrl:${newUrl}`);
return (_a = this.livePlayer) === null || _a === void 0 ? void 0 : _a.switchStream(newUrl);
}
/**
* 启用播放音量大小提示
*
* @param {Number} intervalMs - onPlayoutVolumeUpdate 回调的触发间隔,单位为ms,最小间隔为100ms,如果小于等于0则会关闭回调,建议设置为300ms;【默认值】:0,不开启。
* @return {Number} - 参考 V2LiveCode 的定义
*/
enableVolumeEvaluation(intervalMs) {
var _a;
this.logger.debug(`enableVolumeEvaluation intervalMs:${intervalMs}`);
return (_a = this.livePlayer) === null || _a === void 0 ? void 0 : _a.enableVolumeEvaluation(intervalMs);
}
////////////////////////////////////////////////////////////////////////////////
//
// 内部接口
//
////////////////////////////////////////////////////////////////////////////////
enableObserveVideoFrame(enable, pixelFormat, bufferType) {
var _a;
this.logger.debug(`enableObserveVideoFrame enable:${enable}, pixelFormat:${pixelFormat}, bufferType:${bufferType}`);
(_a = this.livePlayer) === null || _a === void 0 ? void 0 : _a.enableObserveVideoFrame(enable, pixelFormat, bufferType);
}
_createPlayerRender() {
if (this.playerVideoRender !== null) {
return;
}
this.playerVideoRender = new video_render_1.VideoRender();
const trtcPixelFormat = (0, converter_1.convertPixelFormatFromLive)(this.pixelFormat);
this.playerVideoRender.setVideoPixelFormat(trtcPixelFormat);
}
_destroyPlayerRender() {
if (this.playerVideoRender) {
this.playerVideoRender.destroy();
this.playerVideoRender = null;
}
this._removeVideoRenderCallback();
this.enableObserveVideoFrame(false, this.pixelFormat, live_define_1.V2LiveBufferType.V2LiveBufferTypeByteBuffer);
}
_setVideoRenderBuffer() {
var _a;
if (this.playerVideoRender !== null) {
const videoBuffer = this.playerVideoRender.getVideoBuffer();
(_a = this.livePlayer) === null || _a === void 0 ? void 0 : _a.setVideoRenderBuffer(videoBuffer.buffer, videoBuffer.width, videoBuffer.height, this.pixelFormat, videoBuffer.id);
}
}
_addVideoRenderCallback() {
var _a;
(_a = this.livePlayer) === null || _a === void 0 ? void 0 : _a.addVideoRenderCallback(this._playerVideoRenderCallback);
}
_removeVideoRenderCallback() {
var _a;
(_a = this.livePlayer) === null || _a === void 0 ? void 0 : _a.removeVideoRenderCallback();
}
_playerVideoRenderCallback(args) {
if (this.playerVideoRender) {
const [userId, type, width, height, timestamp, rotation, valid, bufferId] = args;
const result = this.playerVideoRender.renderVideoData(userId, type, width, height, timestamp, rotation, valid, bufferId);
if (!result) {
this._setVideoRenderBuffer();
}
}
}
initObserver() {
var _a;
(_a = this.livePlayer) === 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 'onVideoResolutionChanged':
this.handleOnVideoResolutionChanged(data.width, data.height);
break;
case 'onConnected':
this.handleOnConnected();
break;
case 'onVideoPlaying':
this.handleOnVideoPlaying(data.firstPlay);
break;
case 'onAudioPlaying':
this.handleOnAudioPlaying(data.firstPlay);
break;
case 'onVideoLoading':
this.handleOnVideoLoading();
break;
case 'onAudioLoading':
this.handleOnAudioLoading();
break;
case 'onPlayoutVolumeUpdate':
this.handleOnPlayoutVolumeUpdate(data.volume);
break;
case 'onStatisticsUpdate':
this.handleOnStatisticsUpdate(data.statistics);
break;
case 'onStreamSwitched':
this.handleOnStreamSwitched(data.url, data.code);
break;
default:
this.logger.error(`unknown event: ${key}`);
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);
}
handleOnVideoResolutionChanged(width, height) {
this.fire('onVideoResolutionChanged', width, height);
}
handleOnConnected() {
this.fire('onConnected');
}
handleOnVideoPlaying(firstPlay) {
this.fire('onVideoPlaying', firstPlay);
}
handleOnAudioPlaying(firstPlay) {
this.fire('onAudioPlaying', firstPlay);
}
handleOnVideoLoading() {
this.fire('onVideoLoading');
}
handleOnAudioLoading() {
this.fire('onAudioLoading');
}
handleOnPlayoutVolumeUpdate(volume) {
this.fire('onPlayoutVolumeUpdate', volume);
}
handleOnStatisticsUpdate(statistics) {
this.fire('onStatisticsUpdate', statistics);
}
handleOnStreamSwitched(url, code) {
this.fire('onStreamSwitched', url, code);
}
}
exports.V2LivePlayer = V2LivePlayer;