UNPKG

twilio-video

Version:

Twilio Video JavaScript Library

713 lines 34.5 kB
'use strict'; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var MediaStreamTrack = require('./webrtc').MediaStreamTrack; var _a = require('./util'), asLocalTrack = _a.asLocalTrack, asLocalTrackPublication = _a.asLocalTrackPublication, trackClass = _a.trackClass; var _b = require('./util/constants'), E = _b.typeErrors, trackPriority = _b.trackPriority; var validateLocalTrack = require('./util/validate').validateLocalTrack; var _c = require('./media/track/es5'), LocalAudioTrack = _c.LocalAudioTrack, LocalDataTrack = _c.LocalDataTrack, LocalVideoTrack = _c.LocalVideoTrack; var LocalAudioTrackPublication = require('./media/track/localaudiotrackpublication'); var LocalDataTrackPublication = require('./media/track/localdatatrackpublication'); var LocalVideoTrackPublication = require('./media/track/localvideotrackpublication'); var Participant = require('./participant'); /** * A {@link LocalParticipant} represents the local {@link Participant} in a * {@link Room}. * @extends Participant * @property {Map<Track.SID, LocalAudioTrackPublication>} audioTracks - * The {@link LocalParticipant}'s {@link LocalAudioTrackPublication}s * @property {Map<Track.SID, LocalDataTrackPublication>} dataTracks - * The {@link LocalParticipant}'s {@link LocalDataTrackPublication}s * @property {Map<Track.SID, LocalTrackPublication>} tracks - * The {@link LocalParticipant}'s {@link LocalTrackPublication}s * @property {Map<Track.SID, LocalVideoTrackPublication>} videoTracks - * The {@link LocalParticipant}'s {@link LocalVideoTrackPublication}s * @property {string} signalingRegion - The geographical region of the * signaling edge the {@link LocalParticipant} is connected to. * * @emits RemoteParticipant#reconnected * @emits RemoteParticipant#reconnecting * @emits LocalParticipant#trackDimensionsChanged * @emits LocalParticipant#trackDisabled * @emits LocalParticipant#trackEnabled * @emits LocalParticipant#trackPublicationFailed * @emits LocalParticipant#trackPublished * @emits LocalParticipant#trackStarted * @emits LocalParticipant#trackStopped * @emits LocalParticipant#trackWarning * @emits LocalParticipant#trackWarningsCleared */ var LocalParticipant = /** @class */ (function (_super) { __extends(LocalParticipant, _super); /** * Construct a {@link LocalParticipant}. * @param {ParticipantSignaling} signaling * @param {Array<LocalTrack>} localTracks * @param {Object} options */ function LocalParticipant(signaling, localTracks, options) { var _this = this; options = Object.assign({ LocalAudioTrack: LocalAudioTrack, LocalVideoTrack: LocalVideoTrack, LocalDataTrack: LocalDataTrack, MediaStreamTrack: MediaStreamTrack, LocalAudioTrackPublication: LocalAudioTrackPublication, LocalVideoTrackPublication: LocalVideoTrackPublication, LocalDataTrackPublication: LocalDataTrackPublication, shouldStopLocalTracks: false, tracks: localTracks }, options); var tracksToStop = options.shouldStopLocalTracks ? new Set(localTracks.filter(function (localTrack) { return localTrack.kind !== 'data'; })) : new Set(); _this = _super.call(this, signaling, options) || this; Object.defineProperties(_this, { _eventObserver: { value: options.eventObserver }, _LocalAudioTrack: { value: options.LocalAudioTrack }, _LocalDataTrack: { value: options.LocalDataTrack }, _LocalVideoTrack: { value: options.LocalVideoTrack }, _MediaStreamTrack: { value: options.MediaStreamTrack }, _LocalAudioTrackPublication: { value: options.LocalAudioTrackPublication }, _LocalDataTrackPublication: { value: options.LocalDataTrackPublication }, _LocalVideoTrackPublication: { value: options.LocalVideoTrackPublication }, _tracksToStop: { value: tracksToStop }, signalingRegion: { enumerable: true, get: function () { return signaling.signalingRegion; } } }); _this._handleTrackSignalingEvents(); return _this; } /** * @private * @param {LocalTrack} track * @param {Track.ID} id * @param {Track.Priority} priority * @returns {?LocalTrack} */ LocalParticipant.prototype._addTrack = function (track, id, priority) { var addedTrack = _super.prototype._addTrack.call(this, track, id); if (addedTrack && this.state !== 'disconnected') { this._addLocalTrack(track, priority); } return addedTrack; }; /** * @private * @param {LocalTrack} track * @param {Track.Priority} priority * @returns {void} */ LocalParticipant.prototype._addLocalTrack = function (track, priority) { var _a; // check if track has noise cancellation enabled. var vendor = (_a = track.noiseCancellation) === null || _a === void 0 ? void 0 : _a.vendor; this._signaling.addTrack(track._trackSender, track.name, priority, vendor); this._log.info("Added a new " + trackClass(track, true) + ":", track.id); this._log.debug(trackClass(track, true) + ":", track); }; /** * @private * @param {LocalTrack} track * @param {Track.ID} id * @returns {?LocalTrack} */ LocalParticipant.prototype._removeTrack = function (track, id) { var removedTrack = _super.prototype._removeTrack.call(this, track, id); if (removedTrack && this.state !== 'disconnected') { this._signaling.removeTrack(track._trackSender); this._log.info("Removed a " + trackClass(track, true) + ":", track.id); this._log.debug(trackClass(track, true) + ":", track); } return removedTrack; }; /** * Get the {@link LocalTrack} events to re-emit. * @private * @returns {Array<Array<string>>} events */ LocalParticipant.prototype._getTrackEvents = function () { return _super.prototype._getTrackEvents.call(this).concat([ ['disabled', 'trackDisabled'], ['enabled', 'trackEnabled'], ['stopped', 'trackStopped'] ]); }; LocalParticipant.prototype.toString = function () { return "[LocalParticipant #" + this._instanceId + (this.sid ? ": " + this.sid : '') + "]"; }; /** * @private */ LocalParticipant.prototype._handleTrackSignalingEvents = function () { var _this = this; var log = this._log; if (this.state === 'disconnected') { return; } var localTrackDisabled = function (localTrack) { var trackSignaling = _this._signaling.getPublication(localTrack._trackSender); if (trackSignaling) { trackSignaling.disable(); log.debug("Disabled the " + trackClass(localTrack, true) + ":", localTrack.id); } }; var localTrackEnabled = function (localTrack) { var trackSignaling = _this._signaling.getPublication(localTrack._trackSender); if (trackSignaling) { trackSignaling.enable(); log.debug("Enabled the " + trackClass(localTrack, true) + ":", localTrack.id); } }; var localTrackStopped = function (localTrack) { // NOTE(mroberts): We shouldn't need to check for `stop`, since DataTracks // do not emit "stopped". var trackSignaling = _this._signaling.getPublication(localTrack._trackSender); if (trackSignaling) { trackSignaling.stop(); } return trackSignaling; }; var stateChanged = function (state) { log.debug('Transitioned to state:', state); if (state === 'disconnected') { log.debug('Removing LocalTrack event listeners'); _this._signaling.removeListener('stateChanged', stateChanged); _this.removeListener('trackDisabled', localTrackDisabled); _this.removeListener('trackEnabled', localTrackEnabled); _this.removeListener('trackStopped', localTrackStopped); // NOTE(mmalavalli): Remove the stale MediaTrackSender clones so that we // do not call replaceTrack() on their RTCRtpSenders. _this._tracks.forEach(function (track) { var trackSignaling = localTrackStopped(track); if (trackSignaling) { track._trackSender.removeClone(trackSignaling._trackTransceiver); } }); log.info("LocalParticipant disconnected. Stopping " + _this._tracksToStop.size + " automatically-acquired LocalTracks"); _this._tracksToStop.forEach(function (track) { track.stop(); }); } else if (state === 'connected') { // NOTE(mmalavalli): Any transition to "connected" here is a result of // successful signaling reconnection, and not a first-time establishment // of the signaling connection. log.info('reconnected'); // NOTE(mpatwardhan): `stateChanged` can get emitted with StateMachine locked. // Do not signal public events synchronously with lock held. setTimeout(function () { return _this.emit('reconnected'); }, 0); } }; this.on('trackDisabled', localTrackDisabled); this.on('trackEnabled', localTrackEnabled); this.on('trackStopped', localTrackStopped); this._signaling.on('stateChanged', stateChanged); this._tracks.forEach(function (track) { _this._addLocalTrack(track, trackPriority.PRIORITY_STANDARD); _this._getOrCreateLocalTrackPublication(track).catch(function (error) { // Just log a warning for now. log.warn("Failed to get or create LocalTrackPublication for " + track + ":", error); }); }); }; /** * @private * @param {LocalTrack} localTrack * @returns {Promise<LocalTrackPublication>} */ LocalParticipant.prototype._getOrCreateLocalTrackPublication = function (localTrack) { var localTrackPublication = getTrackPublication(this.tracks, localTrack); if (localTrackPublication) { return Promise.resolve(localTrackPublication); } var log = this._log; var self = this; var trackSignaling = this._signaling.getPublication(localTrack._trackSender); if (!trackSignaling) { return Promise.reject(new Error("Unexpected error: The " + localTrack + " cannot be published")); } return new Promise(function (resolve, reject) { function updated() { var error = trackSignaling.error; if (error) { trackSignaling.removeListener('updated', updated); log.warn("Failed to publish the " + trackClass(localTrack, true) + ": " + error.message); self._removeTrack(localTrack, localTrack.id); setTimeout(function () { self.emit('trackPublicationFailed', error, localTrack); }); reject(error); return; } if (!self._tracks.has(localTrack.id)) { trackSignaling.removeListener('updated', updated); reject(new Error("The " + localTrack + " was unpublished")); return; } var sid = trackSignaling.sid; if (!sid) { return; } trackSignaling.removeListener('updated', updated); var options = { log: log, LocalAudioTrackPublication: self._LocalAudioTrackPublication, LocalDataTrackPublication: self._LocalDataTrackPublication, LocalVideoTrackPublication: self._LocalVideoTrackPublication }; localTrackPublication = getTrackPublication(self.tracks, localTrack); var warningHandler = function (twilioWarningName) { return self.emit('trackWarning', twilioWarningName, localTrackPublication); }; var warningsClearedHandler = function () { return self.emit('trackWarningsCleared', localTrackPublication); }; var unpublish = function (publication) { localTrackPublication.removeListener('trackWarning', warningHandler); localTrackPublication.removeListener('trackWarningsCleared', warningsClearedHandler); self.unpublishTrack(publication.track); }; if (!localTrackPublication) { localTrackPublication = asLocalTrackPublication(localTrack, trackSignaling, unpublish, options); self._addTrackPublication(localTrackPublication); } localTrackPublication.on('warning', warningHandler); localTrackPublication.on('warningsCleared', warningsClearedHandler); var state = self._signaling.state; if (state === 'connected' || state === 'connecting') { if (localTrack._processorEventObserver) { localTrack._processorEventObserver.on('event', function (event) { self._eventObserver.emit('event', { name: event.name, payload: event.data, group: 'video-processor', level: 'info' }); }); } // NOTE(csantos): For tracks created before joining a room or already joined but about to publish it if (localTrack.processedTrack) { localTrack._captureFrames(); localTrack._setSenderMediaStreamTrack(true); } } if (state === 'connected') { setTimeout(function () { self.emit('trackPublished', localTrackPublication); }); } resolve(localTrackPublication); } trackSignaling.on('updated', updated); }); }; /** * Publishes a {@link LocalTrack} to the {@link Room}. * @param {LocalTrack} localTrack - The {@link LocalTrack} to publish * @param {LocalTrackPublishOptions} [options] - The {@link LocalTrackPublishOptions} * for publishing the {@link LocalTrack} * @returns {Promise<LocalTrackPublication>} - Resolves with the corresponding * {@link LocalTrackPublication} if successful; In a Large Group Room (Maximum * Participants greater than 50), rejects with a {@link ParticipantMaxTracksExceededError} * if either the total number of published Tracks in the Room exceeds 16, or the {@link LocalTrack} * is part of a set of {@link LocalTrack}s which along with the published Tracks exceeds 16. * @throws {TypeError} * @throws {RangeError} * @example * var Video = require('twilio-video'); * * Video.connect(token, { * name: 'my-cool-room', * audio: true * }).then(function(room) { * return Video.createLocalVideoTrack({ * name: 'camera' * }).then(function(localVideoTrack) { * return room.localParticipant.publishTrack(localVideoTrack, { * priority: 'high' * }); * }); * }).then(function(publication) { * console.log('The LocalTrack "' + publication.trackName * + '" was successfully published with priority "' * * publication.priority + '"'); * }); */ /** * Publishes a MediaStreamTrack to the {@link Room}. * @param {MediaStreamTrack} mediaStreamTrack - The MediaStreamTrack * to publish; if a corresponding {@link LocalAudioTrack} or * {@link LocalVideoTrack} has not yet been published, this method will * construct one * @param {MediaStreamTrackPublishOptions} [options] - The options for publishing * the MediaStreamTrack * @returns {Promise<LocalTrackPublication>} - Resolves with the corresponding * {@link LocalTrackPublication} if successful; In a Large Group Room (Maximum * Participants greater than 50), rejects with a {@link ParticipantMaxTracksExceededError} * if the total number of published Tracks in the Room exceeds 16, or the {@link LocalTrack} * is part of a set of {@link LocalTrack}s which along with the published Tracks exceeds 16. * @throws {TypeError} * @throws {RangeError} * @example * var Video = require('twilio-video'); * * Video.connect(token, { * name: 'my-cool-room', * audio: true * }).then(function(room) { * return navigator.mediaDevices.getUserMedia({ * video: true * }).then(function(mediaStream) { * var mediaStreamTrack = mediaStream.getTracks()[0]; * return room.localParticipant.publishTrack(mediaStreamTrack, { * name: 'camera', * priority: 'high' * }); * }); * }).then(function(publication) { * console.log('The LocalTrack "' + publication.trackName * + '" was successfully published with priority "' * * publication.priority + '"'); * }); */ LocalParticipant.prototype.publishTrack = function (localTrackOrMediaStreamTrack, options) { var trackPublication = getTrackPublication(this.tracks, localTrackOrMediaStreamTrack); if (trackPublication) { return Promise.resolve(trackPublication); } options = Object.assign({ log: this._log, priority: trackPriority.PRIORITY_STANDARD, LocalAudioTrack: this._LocalAudioTrack, LocalDataTrack: this._LocalDataTrack, LocalVideoTrack: this._LocalVideoTrack, MediaStreamTrack: this._MediaStreamTrack }, options); var localTrack; try { localTrack = asLocalTrack(localTrackOrMediaStreamTrack, options); } catch (error) { return Promise.reject(error); } var noiseCancellation = localTrack.noiseCancellation; var allowedAudioProcessors = this._signaling.audioProcessors; if (noiseCancellation && !allowedAudioProcessors.includes(noiseCancellation.vendor)) { this._log.warn(noiseCancellation.vendor + " is not supported in this room. disabling it permanently"); noiseCancellation.disablePermanently(); } var priorityValues = Object.values(trackPriority); if (!priorityValues.includes(options.priority)) { // eslint-disable-next-line new-cap return Promise.reject(E.INVALID_VALUE('LocalTrackPublishOptions.priority', priorityValues)); } var addedLocalTrack = this._addTrack(localTrack, localTrack.id, options.priority) || this._tracks.get(localTrack.id); return this._getOrCreateLocalTrackPublication(addedLocalTrack); }; /** * Publishes multiple {@link LocalTrack}s to the {@link Room}. * @param {Array<LocalTrack|MediaStreamTrack>} tracks - The {@link LocalTrack}s * to publish; for any MediaStreamTracks provided, if a corresponding * {@link LocalAudioTrack} or {@link LocalVideoTrack} has not yet been * published, this method will construct one * @returns {Promise<Array<LocalTrackPublication>>} - The resulting * {@link LocalTrackPublication}s if successful; In a Large Group Room (Maximum * Participants greater than 50), rejects with a {@link ParticipantMaxTracksExceededError} * if the total number of published Tracks in the Room exceeds 16, or the {@link LocalTrack}s * along with the published Tracks exceeds 16. * @throws {TypeError} */ LocalParticipant.prototype.publishTracks = function (tracks) { if (!Array.isArray(tracks)) { // eslint-disable-next-line new-cap throw E.INVALID_TYPE('tracks', 'Array of LocalAudioTrack, LocalVideoTrack, LocalDataTrack, or MediaStreamTrack'); } return Promise.all(tracks.map(this.publishTrack, this)); }; LocalParticipant.prototype.setBandwidthProfile = function () { this._log.warn('setBandwidthProfile is not implemented yet and may be available in future versions of twilio-video.js'); }; /** * Sets the {@link NetworkQualityVerbosity} for the {@link LocalParticipant} and * {@link RemoteParticipant}s. It does nothing if Network Quality is not enabled * while calling {@link connect}. * @param {NetworkQualityConfiguration} networkQualityConfiguration - The new * {@link NetworkQualityConfiguration}; If either or both of the local and * remote {@link NetworkQualityVerbosity} values are absent, then the corresponding * existing values are retained * @returns {this} * @example * // Update verbosity levels for both LocalParticipant and RemoteParticipants * localParticipant.setNetworkQualityConfiguration({ * local: 1, * remote: 2 * }); * @example * // Update verbosity level for only the LocalParticipant * localParticipant.setNetworkQualityConfiguration({ * local: 1 * }); * @example * // Update verbosity level for only the RemoteParticipants * localParticipant.setNetworkQualityConfiguration({ * remote: 2 * }); */ LocalParticipant.prototype.setNetworkQualityConfiguration = function (networkQualityConfiguration) { if (typeof networkQualityConfiguration !== 'object' || networkQualityConfiguration === null) { // eslint-disable-next-line new-cap throw E.INVALID_TYPE('networkQualityConfiguration', 'NetworkQualityConfiguration'); } ['local', 'remote'].forEach(function (prop) { if (prop in networkQualityConfiguration && (typeof networkQualityConfiguration[prop] !== 'number' || isNaN(networkQualityConfiguration[prop]))) { // eslint-disable-next-line new-cap throw E.INVALID_TYPE("networkQualityConfiguration." + prop, 'number'); } }); this._signaling.setNetworkQualityConfiguration(networkQualityConfiguration); return this; }; /** * Set the {@link LocalParticipant}'s {@link EncodingParameters}. * @param {?EncodingParameters} [encodingParameters] - The new * {@link EncodingParameters}; If null, then the bitrate limits are removed; * If not specified, then the existing bitrate limits are preserved * @returns {this} * @throws {TypeError} */ LocalParticipant.prototype.setParameters = function (encodingParameters) { if (typeof encodingParameters !== 'undefined' && typeof encodingParameters !== 'object') { // eslint-disable-next-line new-cap throw E.INVALID_TYPE('encodingParameters', 'EncodingParameters, null or undefined'); } if (encodingParameters) { if (this._signaling.getParameters().adaptiveSimulcast && encodingParameters.maxVideoBitrate) { // eslint-disable-next-line new-cap throw E.INVALID_TYPE('encodingParameters', 'encodingParameters.maxVideoBitrate is not compatible with "preferredVideoCodecs=auto"'); } ['maxAudioBitrate', 'maxVideoBitrate'].forEach(function (prop) { if (typeof encodingParameters[prop] !== 'undefined' && typeof encodingParameters[prop] !== 'number' && encodingParameters[prop] !== null) { // eslint-disable-next-line new-cap throw E.INVALID_TYPE("encodingParameters." + prop, 'number, null or undefined'); } }); } else if (encodingParameters === null) { encodingParameters = { maxAudioBitrate: null, maxVideoBitrate: null }; } this._signaling.setParameters(encodingParameters); return this; }; /** * Stops publishing a {@link LocalTrack} to the {@link Room}. * @param {LocalTrack|MediaStreamTrack} track - The {@link LocalTrack} * to stop publishing; if a MediaStreamTrack is provided, this method * looks up the corresponding {@link LocalAudioTrack} or * {@link LocalVideoTrack} to stop publishing * @returns {?LocalTrackPublication} - The corresponding * {@link LocalTrackPublication} if the {@link LocalTrack} was previously * published, null otherwise * @throws {TypeError} */ LocalParticipant.prototype.unpublishTrack = function (track) { validateLocalTrack(track, { LocalAudioTrack: this._LocalAudioTrack, LocalDataTrack: this._LocalDataTrack, LocalVideoTrack: this._LocalVideoTrack, MediaStreamTrack: this._MediaStreamTrack }); var localTrack = this._tracks.get(track.id); if (!localTrack) { return null; } var trackSignaling = this._signaling.getPublication(localTrack._trackSender); trackSignaling.publishFailed(new Error("The " + localTrack + " was unpublished")); localTrack = this._removeTrack(localTrack, localTrack.id); if (!localTrack) { return null; } var localTrackPublication = getTrackPublication(this.tracks, localTrack); if (localTrackPublication) { this._removeTrackPublication(localTrackPublication); } return localTrackPublication; }; /** * Stops publishing multiple {@link LocalTrack}s to the {@link Room}. * @param {Array<LocalTrack|MediaStreamTrack>} tracks - The {@link LocalTrack}s * to stop publishing; for any MediaStreamTracks provided, this method looks * up the corresponding {@link LocalAudioTrack} or {@link LocalVideoTrack} to * stop publishing * @returns {Array<LocalTrackPublication>} - The corresponding * {@link LocalTrackPublication}s that were successfully unpublished * @throws {TypeError} */ LocalParticipant.prototype.unpublishTracks = function (tracks) { var _this = this; if (!Array.isArray(tracks)) { // eslint-disable-next-line new-cap throw E.INVALID_TYPE('tracks', 'Array of LocalAudioTrack, LocalVideoTrack, LocalDataTrack, or MediaStreamTrack'); } return tracks.reduce(function (unpublishedTracks, track) { var unpublishedTrack = _this.unpublishTrack(track); return unpublishedTrack ? unpublishedTracks.concat(unpublishedTrack) : unpublishedTracks; }, []); }; return LocalParticipant; }(Participant)); /** * The {@link LocalParticipant} has reconnected to the {@link Room} after a signaling connection disruption. * @event LocalParticipant#reconnected */ /** * The {@link LocalParticipant} is reconnecting to the {@link Room} after a signaling connection disruption. * @event LocalParticipant#reconnecting */ /** * One of the {@link LocalParticipant}'s {@link LocalVideoTrack}'s dimensions changed. * @param {LocalVideoTrack} track - The {@link LocalVideoTrack} whose dimensions changed * @event LocalParticipant#trackDimensionsChanged */ /** * A {@link LocalTrack} was disabled by the {@link LocalParticipant}. * @param {LocalTrack} track - The {@link LocalTrack} that was disabled * @event LocalParticipant#trackDisabled */ /** * A {@link LocalTrack} was enabled by the {@link LocalParticipant}. * @param {LocalTrack} track - The {@link LocalTrack} that was enabled * @event LocalParticipant#trackEnabled */ /** * A {@link LocalTrack} failed to publish. Check the error message for more * information. In a Large Group Room (Maximum Participants greater than 50), * this event is raised with a {@link ParticipantMaxTracksExceededError} either * when attempting to publish the {@link LocalTrack} will exceed the Maximum Published * Tracks limit of 16, or the {@link LocalTrack} is part of a set of {@link LocalTrack}s * which along with the published Tracks exceeds 16. * @param {TwilioError} error - A {@link TwilioError} explaining why publication * failed * @param {LocalTrack} localTrack - The {@link LocalTrack} that failed to * publish * @event LocalParticipant#trackPublicationFailed */ /** * A {@link LocalTrack} that was added using {@link LocalParticipant#publishTrack} was successfully published. This event * is not raised for {@link LocalTrack}s added in {@link ConnectOptions}<code>.tracks</code> or auto-created within * <a href="module-twilio-video.html#.connect__anchor"><code>{@link connect}</code></a>. * @param {LocalTrackPublication} publication - The resulting * {@link LocalTrackPublication} for the published {@link LocalTrack} * @event LocalParticipant#trackPublished */ /** * One of the {@link LocalParticipant}'s {@link LocalTrack}s started. * @param {LocalTrack} track - The {@link LocalTrack} that started * @event LocalParticipant#trackStarted */ /** * One of the {@link LocalParticipant}'s {@link LocalTrack}s stopped, either * because {@link LocalTrack#stop} was called or because the underlying * MediaStreamTrack ended). * @param {LocalTrack} track - The {@link LocalTrack} that stopped * @event LocalParticipant#trackStopped */ /** * One of the {@link LocalParticipant}'s {@link LocalTrackPublication}s encountered a warning. * This event is only raised if you enabled warnings using <code>notifyWarnings</code> in <code>ConnectOptions</code>. * @param {string} name - The warning that was raised. * @param {LocalTrackPublication} publication - The {@link LocalTrackPublication} that encountered the warning. * @event LocalParticipant#trackWarning */ /** * One of the {@link LocalParticipant}'s {@link LocalTrackPublication}s cleared all warnings. * This event is only raised if you enabled warnings using <code>notifyWarnings</code> in <code>ConnectOptions</code>. * @param {LocalTrackPublication} publication - The {@link LocalTrackPublication} that cleared all warnings. * @event LocalParticipant#trackWarningsCleared */ /** * Outgoing media encoding parameters. * @typedef {object} EncodingParameters * @property {?number} [maxAudioBitrate] - Max outgoing audio bitrate (bps); * If not specified, retains the existing bitrate limit; A <code>null</code> or a * <code>0</code> value removes any previously set bitrate limit; This value is set * as a hint for variable bitrate codecs, but will not take effect for fixed bitrate * codecs; Based on our tests, Chrome, Firefox and Safari support a bitrate range of * 12000 bps to 256000 bps for Opus codec; This parameter has no effect on iSAC, PCMU * and PCMA codecs * @property {?number} [maxVideoBitrate] - Max outgoing video bitrate (bps); * If not specified, retains the existing bitrate limit; A <code>null</code> or * a <code>0</code> value removes any previously set bitrate limit; This value is * set as a hint for variable bitrate codecs, but will not take effect for fixed * bitrate codecs; Based on our tests, Chrome, Firefox and Safari all seem to support * an average bitrate range of 20000 bps (20 kbps) to 8000000 bps (8 mbps) for a * 720p VideoTrack. * Note: this limit is not applied for screen share tracks published on Chrome. */ /** * Options for publishing a {@link LocalTrack}. * @typedef {object} LocalTrackPublishOptions * @property {Track.Priority} [priority='standard'] - The priority with which the {@link LocalTrack} * is to be published; In Group or Small Group Rooms, the appropriate bandwidth is * allocated to the {@link LocalTrack} based on its {@link Track.Priority}; It has no * effect in Peer-to-Peer Rooms; It defaults to "standard" when not provided */ /** * Options for publishing a {@link MediaStreamTrack}. * @typedef {LocalTrackOptions} MediaStreamTrackPublishOptions * @property {Track.Priority} [priority='standard'] - The priority with which the {@link LocalTrack} * is to be published; In Group or Small Group Rooms, the appropriate bandwidth is * allocated to the {@link LocalTrack} based on its {@link Track.Priority}; It has no * effect in Peer-to-Peer Rooms; It defaults to "standard" when not provided */ /** * @private * @param {Map<Track.SID, LocalTrackPublication>} trackPublications * @param {LocalTrack|MediaStreamTrack} track * @returns {?LocalTrackPublication} trackPublication */ function getTrackPublication(trackPublications, track) { return Array.from(trackPublications.values()).find(function (trackPublication) { return trackPublication.track === track || trackPublication.track.mediaStreamTrack === track; }) || null; } module.exports = LocalParticipant; //# sourceMappingURL=localparticipant.js.map