cloudhub-playback-sdk
Version:
CloudHubPlaybackSDK
257 lines (256 loc) • 13.6 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const ActionFactory_1 = __importDefault(require("../actions/ActionFactory"));
const ActionEvent_1 = __importDefault(require("../ActionEvent"));
const utils_1 = __importDefault(require("../helper/utils"));
const UserController_1 = __importDefault(require("./UserController"));
const Logger_1 = __importDefault(require("../Logger"));
const RoomController_1 = __importDefault(require("./RoomController"));
const RemoteVideoStateChangedAction_1 = __importDefault(require("../actions/RemoteVideoStateChangedAction"));
const RemoteAudioStateChangedAction_1 = __importDefault(require("../actions/RemoteAudioStateChangedAction"));
const MediaStateChangeAction_1 = __importDefault(require("../actions/MediaStateChangeAction"));
const RemoteMultiAudioStateChangedAction_1 = __importDefault(require("../actions/RemoteMultiAudioStateChangedAction"));
class PlaybackPlayerController {
constructor(recordManager, options = {}) {
if (!recordManager) {
Logger_1.default.error('recordManager is required');
}
this.recordManager = recordManager;
this.currIndex = 0; //当前轮询的下标
this.time = null; //当前轮询的时间戳
this.actionTimer = null; //action定时器
this.options = this._defaultOptions(options);
this.timeDifference = 0; //系统时间与 record 开始时间的差值
this.cacheAudioAction = null;
this.cacheVideoAction = null;
this.handleDelUserLeave = {};
}
_defaultOptions(options = {}) {
let defaultOptions = {
timeStep: 1000,
speed: 1
};
for (let key in options) {
defaultOptions[key] = options[key];
}
return defaultOptions;
}
start() {
this.setTimeDifference(0); //初始化 系统时间与 record 开始时间的差值
//开启定时器
this.actionTimer = setInterval(() => {
const curTime = new Date().getTime(); //获取系统时间
this.time = curTime - this.timeDifference; //获取这一次轮询的时间戳
//返回这一次时间戳内的所有 action 事件 默认1s轮询一次 如果设置快进 就根据快进的进度
const { index, actions } = this.recordManager.getActions(this.currIndex, this.time);
this.currIndex = index;
// 循环所有的事件
actions.forEach((action) => {
//派发前处理
this.beforeAction(action);
const actionObject = ActionFactory_1.default.create(action);
/************需要注意的是在派发前处理还是派发后处理************/
//todo 派发事件
ActionEvent_1.default.dispatch(actionObject);
});
}, this.options.timeStep / this.options.speed);
}
setTimeDifference(time = 0) {
Logger_1.default.info('setTimeDifference', time);
//time为0的话 回放时间轴回到初始状态
if (time === 0) {
this.currIndex = 0;
}
const date = new Date();
const startTime = this.recordManager.getStartTime(); //回放开始时间
const endTime = this.recordManager.getEndTime(); //回放结束时间
const nextTime = date.getTime() - (startTime + time); //当前时间与回放开始时间计算出来的差值
if (nextTime <= endTime) {
//快进的时间在合理范围内就赋值
this.timeDifference = nextTime;
this.seekVideoPosition(nextTime);
Logger_1.default.info('setTimeDifference success', date.getTime() - this.timeDifference);
}
else {
//快进时间不合理 赋值为初始时间
this.timeDifference = date.getTime() - startTime;
Logger_1.default.warning('setTimeDifference fail', this.timeDifference);
}
}
seekVideoPosition(actionTs) {
const date = new Date();
const time = date.getTime() - this.timeDifference;
//快进的时间戳如果大于当前action的时间戳 就把视频的进度切换至发送action的时间点(发布视频时记录了发布时间戳)
if (actionTs <= time) {
const users = RoomController_1.default.getUsers();
for (let i = 0; i < users.length; i++) {
const user = users[i];
if (user) {
user.setAllVideoTime(actionTs);
}
}
}
}
beforeAction(action) {
const { method, ts } = action;
//存储加入的用户
if (method === 'join') {
const { properties, userName: uid } = action;
properties.id = uid;
RoomController_1.default.setUser(new UserController_1.default(properties));
}
if (method === 'PubMsg' && action.data && action.data.name === 'SyncProperty') {
const properties = Object.assign({}, action.data.data.user);
RoomController_1.default.setUser(new UserController_1.default(properties));
}
// 删除离开的用户
if (method === 'LEAVE') {
const { username: uid } = action;
const leaveUser = RoomController_1.default.getUser(uid);
if (leaveUser && leaveUser.streams) {
Object.values(leaveUser.streams).map((key) => {
Object.values(key).map((item) => {
const { options, streamId } = item;
const mediaType = leaveUser.getStreamType(streamId);
const customize = {
streamId,
method: 'cancelPublisher',
userName: uid,
};
if (this.handleDelUserLeave[streamId] === true && mediaType !== 'multiAudio') {
const actionObject = new RemoteVideoStateChangedAction_1.default(Object.assign(customize, { options }), RoomController_1.default);
ActionEvent_1.default.dispatch(actionObject);
}
if (this.handleDelUserLeave[streamId] === true && mediaType === 'multiAudio') {
const actionMultiAudioObject = new RemoteMultiAudioStateChangedAction_1.default(Object.assign(customize, { options }), RoomController_1.default);
ActionEvent_1.default.dispatch(actionMultiAudioObject, 'multiStream');
}
});
});
}
RoomController_1.default.delUser(uid);
}
// 音频改变,储存起来
if (method === 'updateStreamAttributes') {
if (action.msg && action.msg.attrs && utils_1.default.hasKey(action.msg.attrs, 'mute_audio')) {
this.cacheAudioAction = action;
const _user = RoomController_1.default.getUserByStreamId(this.cacheAudioAction.streamId);
if (_user) {
const cacheAudioActionObject = new RemoteAudioStateChangedAction_1.default(Object.assign(this.cacheAudioAction, { userName: _user.id }), RoomController_1.default);
ActionEvent_1.default.dispatch(cacheAudioActionObject, 'updateStreamAttributes');
this.cacheAudioAction = null;
}
}
if (action.msg && action.msg.attrs && utils_1.default.hasKey(action.msg.attrs, 'mute_video')) {
this.cacheVideoAction = action;
const _user = RoomController_1.default.getUserByStreamId(this.cacheVideoAction.streamId);
if (_user) {
const mediaType = _user.getStreamType(this.cacheVideoAction.streamId);
if (mediaType !== 'multiAudio') {
const { options } = _user.getStreamByStreamId(this.cacheVideoAction.streamId);
const cacheVideoActionObject = new RemoteVideoStateChangedAction_1.default(Object.assign(this.cacheVideoAction, { userName: _user.id, options }), RoomController_1.default);
ActionEvent_1.default.dispatch(cacheVideoActionObject, 'updateStreamAttributes');
this.cacheVideoAction = null;
}
}
}
}
//发布流时 存储当前用户的流
if (method === 'newPublisher') {
const { userName: uid, streamId, options, filename, ts } = action;
let { type } = options.attributes || {};
const user = RoomController_1.default.getUser(uid);
const isMultiAudio = options && options.extensionId && options.extensionId.includes('audio');
type = isMultiAudio ? 'multiAudio' : type;
if (!user) {
return false;
}
const property = {
streamId,
filename,
publishTime: ts,
type,
uid,
options,
};
user.setStream(type, property, () => {
if (!this.handleDelUserLeave[streamId]) {
this.handleDelUserLeave[streamId] = true;
}
const actionAudioObject = new RemoteAudioStateChangedAction_1.default(action, RoomController_1.default);
if (actionAudioObject && actionAudioObject.options && actionAudioObject.options.attributes && utils_1.default.hasKey(actionAudioObject.options.attributes, 'mute_audio')) {
ActionEvent_1.default.dispatch(actionAudioObject);
}
if (isMultiAudio) {
const actionMultiAudioObject = new RemoteMultiAudioStateChangedAction_1.default(action, RoomController_1.default);
ActionEvent_1.default.dispatch(actionMultiAudioObject, 'multiStream');
return;
}
const actionObject = new RemoteVideoStateChangedAction_1.default(action, RoomController_1.default);
ActionEvent_1.default.dispatch(actionObject);
if (this.cacheAudioAction) {
const _user = RoomController_1.default.getUserByStreamId(this.cacheAudioAction.streamId);
if (_user) {
const cacheAudioActionObject = new RemoteAudioStateChangedAction_1.default(Object.assign(this.cacheAudioAction, { userName: _user.id }), RoomController_1.default);
ActionEvent_1.default.dispatch(cacheAudioActionObject, 'updateStreamAttributes');
this.cacheAudioAction = null;
}
}
if (this.cacheVideoAction) {
const _user = RoomController_1.default.getUserByStreamId(this.cacheVideoAction.streamId);
if (_user) {
const mediaType = _user.getStreamType(this.cacheVideoAction.streamId);
if (mediaType !== 'multiAudio') {
const { options } = _user.getStreamByStreamId(this.cacheVideoAction.streamId);
const cacheVideoActionObject = new RemoteVideoStateChangedAction_1.default(Object.assign(this.cacheVideoAction, { userName: _user.id, options }), RoomController_1.default);
ActionEvent_1.default.dispatch(cacheVideoActionObject, 'updateStreamAttributes');
this.cacheVideoAction = null;
}
}
}
});
user.setVideoTime(ts, streamId);
}
// 媒体进度控制
if (method === 'controlmedia') {
const { cmd, streamId } = action;
const _user = RoomController_1.default.getUserByStreamId(streamId);
const stream = _user.getStreamByStreamId(streamId);
const mediaData = {
attributes: stream.options.attributes,
cmd,
options: stream.options,
streamId
};
const actionObject = new MediaStateChangeAction_1.default(mediaData, RoomController_1.default);
ActionEvent_1.default.dispatch(actionObject);
}
//取消流时 删除当前用户的流
if (method === 'cancelPublisher') {
const { userName: uid, streamId } = action;
const user = RoomController_1.default.getUserByStreamId(streamId);
if (!user) {
return false;
}
if (this.handleDelUserLeave[streamId]) {
this.handleDelUserLeave[streamId] = false;
}
user.delStream(streamId);
const type = user.getStreamType(streamId);
if (type === 'multiAudio') {
const actionMultiAudioObject = new RemoteMultiAudioStateChangedAction_1.default(action, RoomController_1.default);
ActionEvent_1.default.dispatch(actionMultiAudioObject, 'multiStream');
}
}
// 判断是否结束
if (method === 'close') {
Logger_1.default.info('回放已全部播放完成');
clearInterval(this.actionTimer);
window.CloudHubPlayer.playFinished('Player is stop');
}
}
}
exports.default = PlaybackPlayerController;