openvidu-browser: streamAudioVolumeChange event

pull/173/head
pabloFuente 2018-12-07 11:22:21 +01:00
parent b0bc3d40d2
commit 5ac41f3471
6 changed files with 144 additions and 34 deletions

View File

@ -29,7 +29,9 @@ declare var MediaRecorder: any;
/**
* Easy recording of [[Stream]] objects straightaway from the browser. Initialized with [[OpenVidu.initLocalRecorder]] method
*
* > WARNING: Performing browser local recording of **remote streams** may cause some troubles. A long waiting time may be required after calling _LocalRecorder.stop()_ in this case
* > WARNINGS:
* - Performing browser local recording of **remote streams** may cause some troubles. A long waiting time may be required after calling _LocalRecorder.stop()_ in this case
* - Only Chrome and Firefox support local stream recording
*/
export class LocalRecorder {

View File

@ -80,11 +80,11 @@ export class Session implements EventDispatcher {
/**
* @hidden
*/
isFirstIonicIosSubscriber: boolean = true;
isFirstIonicIosSubscriber = true;
/**
* @hidden
*/
countDownForIonicIosSubscribers: boolean = true;
countDownForIonicIosSubscribers = true;
/**
* @hidden
@ -567,7 +567,7 @@ export class Session implements EventDispatcher {
// If there are already available remote streams, enable hark 'speaking' event in all of them
for (const connectionId in this.remoteConnections) {
const str = this.remoteConnections[connectionId].stream;
if (!!str && !str.speechEvent && str.hasAudio) {
if (!!str && str.hasAudio) {
str.enableSpeakingEvents();
}
}
@ -596,7 +596,7 @@ export class Session implements EventDispatcher {
// If there are already available remote streams, enable hark in all of them
for (const connectionId in this.remoteConnections) {
const str = this.remoteConnections[connectionId].stream;
if (!!str && !str.speechEvent && str.hasAudio) {
if (!!str && str.hasAudio) {
str.enableOnceSpeakingEvents();
}
}
@ -623,7 +623,7 @@ export class Session implements EventDispatcher {
// If there are already available remote streams, disable hark in all of them
for (const connectionId in this.remoteConnections) {
const str = this.remoteConnections[connectionId].stream;
if (!!str && !!str.speechEvent) {
if (!!str) {
str.disableSpeakingEvents();
}
}

View File

@ -26,6 +26,7 @@ import { OutboundStreamOptions } from '../OpenViduInternal/Interfaces/Private/Ou
import { WebRtcPeer, WebRtcPeerSendonly, WebRtcPeerRecvonly, WebRtcPeerSendrecv } from '../OpenViduInternal/WebRtcPeer/WebRtcPeer';
import { WebRtcStats } from '../OpenViduInternal/WebRtcStats/WebRtcStats';
import { PublisherSpeakingEvent } from '../OpenViduInternal/Events/PublisherSpeakingEvent';
import { StreamManagerEvent } from '../OpenViduInternal/Events/StreamManagerEvent';
import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
@ -156,6 +157,18 @@ export class Stream implements EventDispatcher {
* @hidden
*/
speechEvent: any;
/**
* @hidden
*/
publisherStartSpeakingEventEnabled = false;
/**
* @hidden
*/
publisherStopSpeakingEventEnabled = false;
/**
* @hidden
*/
volumeChangeEventEnabled = false;
/**
@ -334,7 +347,6 @@ export class Stream implements EventDispatcher {
});
}
/* Hidden methods */
/**
@ -439,6 +451,7 @@ export class Stream implements EventDispatcher {
}
if (this.speechEvent) {
this.speechEvent.stop();
delete this.speechEvent;
}
this.stopWebRtcStats();
@ -503,7 +516,6 @@ export class Stream implements EventDispatcher {
const harkOptions = this.session.openvidu.advancedConfiguration.publisherSpeakingEventsOptions || {};
harkOptions.interval = (typeof harkOptions.interval === 'number') ? harkOptions.interval : 50;
harkOptions.threshold = (typeof harkOptions.threshold === 'number') ? harkOptions.threshold : -50;
this.speechEvent = hark(this.mediaStream, harkOptions);
}
}
@ -513,35 +525,106 @@ export class Stream implements EventDispatcher {
*/
enableSpeakingEvents(): void {
this.setSpeechEventIfNotExists();
if (!this.publisherStartSpeakingEventEnabled) {
this.publisherStartSpeakingEventEnabled = true;
this.speechEvent.on('speaking', () => {
this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent(this.session, 'publisherStartSpeaking', this.connection, this.streamId)]);
});
}
if (!this.publisherStopSpeakingEventEnabled) {
this.publisherStopSpeakingEventEnabled = true;
this.speechEvent.on('stopped_speaking', () => {
this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent(this.session, 'publisherStopSpeaking', this.connection, this.streamId)]);
});
}
}
/**
* @hidden
*/
enableOnceSpeakingEvents(): void {
this.setSpeechEventIfNotExists();
this.speechEvent.on('speaking', () => {
if (!this.publisherStartSpeakingEventEnabled) {
this.publisherStartSpeakingEventEnabled = true;
this.speechEvent.once('speaking', () => {
this.session.emitEvent('publisherStartSpeaking', [new PublisherSpeakingEvent(this.session, 'publisherStartSpeaking', this.connection, this.streamId)]);
this.disableSpeakingEvents();
});
this.speechEvent.on('stopped_speaking', () => {
}
if (!this.publisherStopSpeakingEventEnabled) {
this.publisherStopSpeakingEventEnabled = true;
this.speechEvent.once('stopped_speaking', () => {
this.session.emitEvent('publisherStopSpeaking', [new PublisherSpeakingEvent(this.session, 'publisherStopSpeaking', this.connection, this.streamId)]);
this.disableSpeakingEvents();
});
}
}
/**
* @hidden
*/
disableSpeakingEvents(): void {
if (!!this.speechEvent) {
if (this.volumeChangeEventEnabled) {
// 'streamAudioVolumeChange' event is enabled. Cannot stop the hark process
this.speechEvent.off('speaking');
this.speechEvent.off('stopped_speaking');
} else {
this.speechEvent.stop();
this.speechEvent = undefined;
delete this.speechEvent;
}
}
this.publisherStartSpeakingEventEnabled = false;
this.publisherStopSpeakingEventEnabled = false;
}
/**
* @hidden
*/
enableVolumeChangeEvent(): void {
this.setSpeechEventIfNotExists();
if (!this.volumeChangeEventEnabled) {
this.volumeChangeEventEnabled = true;
this.speechEvent.on('volume_change', harkEvent => {
const oldValue = this.speechEvent.oldVolumeValue;
const value = { newValue: harkEvent, oldValue };
this.speechEvent.oldVolumeValue = harkEvent;
this.streamManager.emitEvent('streamAudioVolumeChange', [new StreamManagerEvent(this.streamManager, 'streamAudioVolumeChange', value)]);
});
}
}
/**
* @hidden
*/
enableOnceVolumeChangeEvent(): void {
this.setSpeechEventIfNotExists();
if (!this.volumeChangeEventEnabled) {
this.volumeChangeEventEnabled = true;
this.speechEvent.once('volume_change', harkEvent => {
const oldValue = this.speechEvent.oldVolumeValue;
const value = { newValue: harkEvent, oldValue };
this.speechEvent.oldVolumeValue = harkEvent;
this.disableVolumeChangeEvent();
this.streamManager.emitEvent('streamAudioVolumeChange', [new StreamManagerEvent(this.streamManager, 'streamAudioVolumeChange', value)]);
});
}
}
/**
* @hidden
*/
disableVolumeChangeEvent(): void {
if (!!this.speechEvent) {
if (this.session.speakingEventsEnabled) {
// 'publisherStartSpeaking' and/or publisherStopSpeaking` events are enabled. Cannot stop the hark process
this.speechEvent.off('volume_change');
} else {
this.speechEvent.stop();
delete this.speechEvent;
}
}
this.volumeChangeEventEnabled = false;
}
/**

View File

@ -133,7 +133,7 @@ export class StreamManager implements EventDispatcher {
console.info("Remote 'Stream' with id [" + this.stream.streamId + '] video is now playing');
this.ee.emitEvent('videoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
}
this.ee.emitEvent('streamPlaying', [new StreamManagerEvent(this)]);
this.ee.emitEvent('streamPlaying', [new StreamManagerEvent(this, 'streamPlaying', undefined)]);
};
}
@ -161,10 +161,13 @@ export class StreamManager implements EventDispatcher {
this.videos[0].video.paused === false &&
this.videos[0].video.ended === false &&
this.videos[0].video.readyState === 4) {
this.ee.emitEvent('streamPlaying', [new StreamManagerEvent(this)]);
this.ee.emitEvent('streamPlaying', [new StreamManagerEvent(this, 'streamPlaying', undefined)]);
this.ee.emitEvent('videoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
}
}
if (type === 'streamAudioVolumeChange' && this.stream.hasAudio) {
this.stream.enableVolumeChangeEvent();
}
return this;
}
@ -191,10 +194,13 @@ export class StreamManager implements EventDispatcher {
this.videos[0].video.paused === false &&
this.videos[0].video.ended === false &&
this.videos[0].video.readyState === 4) {
this.ee.emitEvent('streamPlaying', [new StreamManagerEvent(this)]);
this.ee.emitEvent('streamPlaying', [new StreamManagerEvent(this, 'streamPlaying', undefined)]);
this.ee.emitEvent('videoPlaying', [new VideoElementEvent(this.videos[0].video, this, 'videoPlaying')]);
}
}
if (type === 'streamAudioVolumeChange' && this.stream.hasAudio) {
this.stream.enableOnceVolumeChangeEvent();
}
return this;
}
@ -207,6 +213,11 @@ export class StreamManager implements EventDispatcher {
} else {
this.ee.off(type, handler);
}
if (type === 'streamAudioVolumeChange') {
this.stream.disableVolumeChangeEvent();
}
return this;
}

View File

@ -33,14 +33,14 @@ export class ConnectionEvent extends Event {
connection: Connection;
/**
* For 'connectionDestroyed' event:
* For `connectionDestroyed` event:
* - "disconnect": the remote user has called `Session.disconnect()`
* - "forceDisconnectByUser": the remote user has been evicted from the Session by other user calling `Session.forceDisconnect()`
* - "forceDisconnectByServer": the remote user has been evicted from the Session by the application
* - "sessionClosedByServer": the Session has been closed by the application
* - "networkDisconnect": the remote user network connection has dropped
*
* For 'connectionCreated' empty string
* For `connectionCreated` event an empty string
*/
reason: string;

View File

@ -20,15 +20,29 @@ import { StreamManager } from '../../OpenVidu/StreamManager';
/**
* Defines the following events:
* - `streamPlaying`: dispatched by [[StreamManager]] ([[Publisher]] and [[Subscriber]])
* - `streamPlaying`: dispatched by [[StreamManager]] ([[Publisher]] and [[Subscriber]]) whenever its media stream starts playing (one of its videos has media
* and has begun to play)
* - `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
* [[OpenViduAdvancedConfiguration.publisherSpeakingEventsOptions]] (default 50ms)
*/
export class StreamManagerEvent extends Event {
/**
* For `streamAudioVolumeChange` event:
* - `{newValue: number, oldValue: number}`: new and old audio volume values. These values are between -100 (silence) and 0 (loudest possible volume).
* They are not exact and depend on how the browser is managing the audio track, but -100 and 0 can be taken as limit values.
*
* For `streamPlaying` event undefined
*/
value: Object | undefined;
/**
* @hidden
*/
constructor(target: StreamManager) {
super(false, target, 'streamPlaying');
constructor(target: StreamManager, type: string, value: Object | undefined) {
super(false, target, type);
this.value = value;
}
/**