mirror of https://github.com/OpenVidu/openvidu.git
openvidu-browser: ExceptionEvent.NO_STREAM_PLAYING_EVENT
parent
8d39c2006e
commit
6a049918d6
|
@ -86,10 +86,6 @@ export class Publisher extends StreamManager {
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
screenShareResizeInterval: NodeJS.Timer;
|
screenShareResizeInterval: NodeJS.Timer;
|
||||||
/**
|
|
||||||
* @hidden
|
|
||||||
*/
|
|
||||||
IEAdapter: any;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent'
|
||||||
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
|
||||||
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
|
||||||
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
|
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
|
||||||
|
import { ExceptionEvent, ExceptionEventName } from '../OpenViduInternal/Events/ExceptionEvent';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
|
@ -90,19 +91,23 @@ export class StreamManager extends EventDispatcher {
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
firstVideoElement?: StreamManagerVideo;
|
protected firstVideoElement?: StreamManagerVideo;
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
lazyLaunchVideoElementCreatedEvent = false;
|
protected element: HTMLElement;
|
||||||
/**
|
|
||||||
* @hidden
|
|
||||||
*/
|
|
||||||
element: HTMLElement;
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
protected canPlayListener: EventListener;
|
protected canPlayListener: EventListener;
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
private streamPlayingEventExceptionTimeout?: NodeJS.Timeout;
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
private lazyLaunchVideoElementCreatedEvent = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
|
@ -138,6 +143,7 @@ export class StreamManager extends EventDispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.canPlayListener = () => {
|
this.canPlayListener = () => {
|
||||||
|
this.deactivateStreamPlayingEventExceptionTimeout();
|
||||||
if (this.stream.isLocal()) {
|
if (this.stream.isLocal()) {
|
||||||
if (!this.stream.displayMyRemote()) {
|
if (!this.stream.displayMyRemote()) {
|
||||||
logger.info("Your local 'Stream' with id [" + this.stream.streamId + '] video is now playing');
|
logger.info("Your local 'Stream' with id [" + this.stream.streamId + '] video is now playing');
|
||||||
|
@ -492,6 +498,7 @@ export class StreamManager extends EventDispatcher {
|
||||||
*/
|
*/
|
||||||
addPlayEventToFirstVideo() {
|
addPlayEventToFirstVideo() {
|
||||||
if ((!!this.videos[0]) && (!!this.videos[0].video) && (!this.videos[0].canplayListenerAdded)) {
|
if ((!!this.videos[0]) && (!!this.videos[0].video) && (!this.videos[0].canplayListenerAdded)) {
|
||||||
|
this.activateStreamPlayingEventExceptionTimeout();
|
||||||
this.videos[0].video.addEventListener('canplay', this.canPlayListener);
|
this.videos[0].video.addEventListener('canplay', this.canPlayListener);
|
||||||
this.videos[0].canplayListenerAdded = true;
|
this.videos[0].canplayListenerAdded = true;
|
||||||
}
|
}
|
||||||
|
@ -533,6 +540,7 @@ export class StreamManager extends EventDispatcher {
|
||||||
*/
|
*/
|
||||||
removeSrcObject(streamManagerVideo: StreamManagerVideo) {
|
removeSrcObject(streamManagerVideo: StreamManagerVideo) {
|
||||||
streamManagerVideo.video.srcObject = null;
|
streamManagerVideo.video.srcObject = null;
|
||||||
|
this.deactivateStreamPlayingEventExceptionTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Private methods */
|
/* Private methods */
|
||||||
|
@ -557,4 +565,24 @@ export class StreamManager extends EventDispatcher {
|
||||||
video.style.webkitTransform = 'unset';
|
video.style.webkitTransform = 'unset';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private activateStreamPlayingEventExceptionTimeout() {
|
||||||
|
if (this.streamPlayingEventExceptionTimeout != null) {
|
||||||
|
// The timeout is already activated
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Trigger ExceptionEvent NO_STREAM_PLAYING_EVENT if after timeout there is no 'canplay' event
|
||||||
|
const msTimeout = this.stream.session.openvidu.advancedConfiguration.noStreamPlayingEventExceptionTimeout || 4000;
|
||||||
|
this.streamPlayingEventExceptionTimeout = setTimeout(() => {
|
||||||
|
const msg = 'StreamManager of Stream ' + this.stream.streamId + ' (' + (this.remote ? 'Subscriber' : 'Publisher') + ') did not trigger "streamPlaying" event in ' + msTimeout + ' ms';
|
||||||
|
logger.warn(msg);
|
||||||
|
this.emitEvent('exception', [new ExceptionEvent(this.stream.session, ExceptionEventName.NO_STREAM_PLAYING_EVENT, this, msg)]);
|
||||||
|
delete this.streamPlayingEventExceptionTimeout;
|
||||||
|
}, msTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private deactivateStreamPlayingEventExceptionTimeout() {
|
||||||
|
clearTimeout(this.streamPlayingEventExceptionTimeout as any);
|
||||||
|
delete this.streamPlayingEventExceptionTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
import { Session } from '../../OpenVidu/Session';
|
import { Session } from '../../OpenVidu/Session';
|
||||||
import { Stream } from '../../OpenVidu/Stream';
|
import { Stream } from '../../OpenVidu/Stream';
|
||||||
|
import { StreamManager } from '../../OpenVidu/StreamManager';
|
||||||
import { Event } from './Event';
|
import { Event } from './Event';
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,7 +37,9 @@ export enum ExceptionEventName {
|
||||||
* The [ICE connection state](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/iceConnectionState)
|
* The [ICE connection state](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/iceConnectionState)
|
||||||
* of an [RTCPeerConnection](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection) reached `failed` status.
|
* of an [RTCPeerConnection](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection) reached `failed` status.
|
||||||
*
|
*
|
||||||
* This is a terminal error that won't have any kind of possible recovery.
|
* This is a terminal error that won't have any kind of possible recovery. If the client is still connected to OpenVidu Server,
|
||||||
|
* then an automatic reconnection process of the media stream is immediately performed. If the ICE connection has broken due to
|
||||||
|
* a total network drop, then no automatic reconnection process will be possible.
|
||||||
*
|
*
|
||||||
* [[ExceptionEvent]] objects with this [[ExceptionEvent.name]] will have as [[ExceptionEvent.origin]] property a [[Stream]] object.
|
* [[ExceptionEvent]] objects with this [[ExceptionEvent.name]] will have as [[ExceptionEvent.origin]] property a [[Stream]] object.
|
||||||
*/
|
*/
|
||||||
|
@ -46,12 +49,38 @@ export enum ExceptionEventName {
|
||||||
* The [ICE connection state](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/iceConnectionState)
|
* The [ICE connection state](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/iceConnectionState)
|
||||||
* of an [RTCPeerConnection](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection) reached `disconnected` status.
|
* of an [RTCPeerConnection](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection) reached `disconnected` status.
|
||||||
*
|
*
|
||||||
* This is not a terminal error, and it is possible for the ICE connection to be reconnected.
|
* This is not a terminal error, and it is possible for the ICE connection to be reconnected. If the client is still connected to
|
||||||
|
* OpenVidu Server and after certain timeout the ICE connection has not reached a success or terminal status, then an automatic
|
||||||
|
* reconnection process of the media stream is performed. If the ICE connection has broken due to a total network drop, then no
|
||||||
|
* automatic reconnection process will be possible.
|
||||||
|
*
|
||||||
|
* You can customize the timeout for the reconnection attempt with property [[OpenViduAdvancedConfiguration.iceConnectionDisconnectedExceptionTimeout]],
|
||||||
|
* which by default is 4000 milliseconds.
|
||||||
*
|
*
|
||||||
* [[ExceptionEvent]] objects with this [[ExceptionEvent.name]] will have as [[ExceptionEvent.origin]] property a [[Stream]] object.
|
* [[ExceptionEvent]] objects with this [[ExceptionEvent.name]] will have as [[ExceptionEvent.origin]] property a [[Stream]] object.
|
||||||
*/
|
*/
|
||||||
ICE_CONNECTION_DISCONNECTED = 'ICE_CONNECTION_DISCONNECTED'
|
ICE_CONNECTION_DISCONNECTED = 'ICE_CONNECTION_DISCONNECTED',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A [[StreamManager]] object has not fired event `streamPlaying` after certain timeout. `streamPlaying` event belongs to [[StreamManagerEvent]]
|
||||||
|
* category. It wraps Web API native event [canplay](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canplay_event).
|
||||||
|
*
|
||||||
|
* OpenVidu Browser can take care of the video players (see [here](/en/latest/cheatsheet/manage-videos/#let-openvidu-take-care-of-the-video-players)),
|
||||||
|
* or you can take care of video players on your own (see [here](/en/latest/cheatsheet/manage-videos/#you-take-care-of-the-video-players)).
|
||||||
|
* Either way, whenever a [[Publisher]] or [[Subscriber]] object is commanded to attach its [[Stream]] to a video element, it is supposed to fire
|
||||||
|
* `streamPlaying` event shortly after. If it does not, then we can safely assume that something wrong has happened and the application may be notified
|
||||||
|
* through this specific ExceptionEvent.
|
||||||
|
*
|
||||||
|
* The timeout can be configured with property [[OpenViduAdvancedConfiguration.noStreamPlayingEventExceptionTimeout]]. By default it is 4000 milliseconds.
|
||||||
|
*
|
||||||
|
* This is just an informative exception. It only means that a Stream that is supposed to be playing by a video player has not done so
|
||||||
|
* in a reasonable time. But the lack of the event can be caused by multiple reasons. If a Subscriber is not playing its Stream, the origin
|
||||||
|
* of the problem could be located at the Publisher side. Or may be caused by a transient network problem. But it also could be a problem with
|
||||||
|
* autoplay permissions. Bottom line, the cause can be very varied, and depending on the application the lack of the event could even be expected.
|
||||||
|
*
|
||||||
|
* [[ExceptionEvent]] objects with this [[ExceptionEvent.name]] will have as [[ExceptionEvent.origin]] property a [[StreamManager]] object.
|
||||||
|
*/
|
||||||
|
NO_STREAM_PLAYING_EVENT = 'NO_STREAM_PLAYING_EVENT'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,8 +99,9 @@ export class ExceptionEvent extends Event {
|
||||||
* Object affected by the exception. Depending on the [[ExceptionEvent.name]] property:
|
* Object affected by the exception. Depending on the [[ExceptionEvent.name]] property:
|
||||||
* - [[Session]]: `ICE_CANDIDATE_ERROR`
|
* - [[Session]]: `ICE_CANDIDATE_ERROR`
|
||||||
* - [[Stream]]: `ICE_CONNECTION_FAILED`, `ICE_CONNECTION_DISCONNECTED`
|
* - [[Stream]]: `ICE_CONNECTION_FAILED`, `ICE_CONNECTION_DISCONNECTED`
|
||||||
|
* - [[StreamManager]]: `NO_STREAM_PLAYING_EVENT`
|
||||||
*/
|
*/
|
||||||
origin: Session | Stream;
|
origin: Session | Stream | StreamManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Informative description of the exception
|
* Informative description of the exception
|
||||||
|
@ -86,7 +116,7 @@ export class ExceptionEvent extends Event {
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
constructor(session: Session, name: ExceptionEventName, origin: Session | Stream, message: string, data?: any) {
|
constructor(session: Session, name: ExceptionEventName, origin: Session | Stream | StreamManager, message: string, data?: any) {
|
||||||
super(false, session, 'exception');
|
super(false, session, 'exception');
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.origin = origin;
|
this.origin = origin;
|
||||||
|
|
|
@ -21,7 +21,10 @@ import { StreamManager } from '../../OpenVidu/StreamManager';
|
||||||
/**
|
/**
|
||||||
* Defines the following events:
|
* Defines the following events:
|
||||||
* - `streamPlaying`: dispatched by [[StreamManager]] ([[Publisher]] and [[Subscriber]]) whenever its media stream starts playing (one of its videos has media
|
* - `streamPlaying`: dispatched by [[StreamManager]] ([[Publisher]] and [[Subscriber]]) whenever its media stream starts playing (one of its videos has media
|
||||||
* and has begun to play). This event will be dispatched when these 3 conditions are met 1) The StreamManager has no video associated in the DOM 2) It is associated to one video 3) That video starts playing
|
* and has begun to play). This event will be dispatched when these 3 conditions are met:
|
||||||
|
* 1. The StreamManager has no video associated in the DOM
|
||||||
|
* 2. It is associated to one video
|
||||||
|
* 3. That video starts playing. Internally the expected Web API event is [HTMLMediaElement.canplay](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canplay_event)
|
||||||
* - `streamAudioVolumeChange`: dispatched by [[StreamManager]] ([[Publisher]] and [[Subscriber]]) when the volume of its Stream's audio track
|
* - `streamAudioVolumeChange`: dispatched by [[StreamManager]] ([[Publisher]] and [[Subscriber]]) when the volume of its Stream's audio track
|
||||||
* changes. Only applies if [[Stream.hasAudio]] is `true`. The frequency this event is fired with is defined by property `interval` of
|
* changes. Only applies if [[Stream.hasAudio]] is `true`. The frequency this event is fired with is defined by property `interval` of
|
||||||
* [[OpenViduAdvancedConfiguration.publisherSpeakingEventsOptions]] (default 100ms)
|
* [[OpenViduAdvancedConfiguration.publisherSpeakingEventsOptions]] (default 100ms)
|
||||||
|
|
|
@ -52,4 +52,20 @@ export interface OpenViduAdvancedConfiguration {
|
||||||
*/
|
*/
|
||||||
forceMediaReconnectionAfterNetworkDrop?: boolean;
|
forceMediaReconnectionAfterNetworkDrop?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The milliseconds that must elapse after triggering [[ExceptionEvent]] of type `ICE_CONNECTION_DISCONNECTED` to perform an automatic reconnection process of the affected media stream.
|
||||||
|
* This automatic reconnection process can only take place if the client still has network connection to OpenVidu Server. If the ICE connection has broken because of a total network drop,
|
||||||
|
* then no reconnection process will be possible at all.
|
||||||
|
*
|
||||||
|
* Default to `4000`.
|
||||||
|
*/
|
||||||
|
iceConnectionDisconnectedExceptionTimeout?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The milliseconds that must elapse for the [[ExceptionEvent]] of name [`NO_STREAM_PLAYING_EVENT`]((/en/latest/api/openvidu-browser/enums/exceptioneventname.html#no_stream_playing_event)) to be fired.
|
||||||
|
*
|
||||||
|
* Default to `4000`.
|
||||||
|
*/
|
||||||
|
noStreamPlayingEventExceptionTimeout?: number;
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue