Adds audio level statistics for the local stream.
This commit is contained in:
parent
ccfa620f46
commit
873cfebe84
57
app.js
57
app.js
|
@ -14,6 +14,12 @@ var ssrc2jid = {};
|
|||
*/
|
||||
var statsCollector = null;
|
||||
|
||||
/**
|
||||
* The stats collector for the local stream.
|
||||
* @type {LocalStatsCollector}
|
||||
*/
|
||||
var localStatsCollector = null;
|
||||
|
||||
/**
|
||||
* Indicates whether ssrc is camera video or desktop stream.
|
||||
* FIXME: remove those maps
|
||||
|
@ -123,6 +129,8 @@ function audioStreamReady(stream) {
|
|||
|
||||
VideoLayout.changeLocalAudio(stream);
|
||||
|
||||
startLocalRtpStatsCollector(stream);
|
||||
|
||||
if (RTC.browser !== 'firefox') {
|
||||
getUserMediaWithConstraints(['video'],
|
||||
videoStreamReady,
|
||||
|
@ -445,19 +453,55 @@ function statsUpdated(statsCollector)
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback called by {@link LocalStatsCollector} in intervals supplied to it's
|
||||
* constructor.
|
||||
* @param statsCollector {@link LocalStatsCollector} source of the event.
|
||||
*/
|
||||
function localStatsUpdated(statsCollector)
|
||||
{
|
||||
console.info("Local audio level: " + statsCollector.audioLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the {@link StatsCollector} if the feature is enabled in config.js.
|
||||
*/
|
||||
function startRtpStatsCollector()
|
||||
{
|
||||
if (config.enableRtpStats)
|
||||
if (config.enableRtpStats && !statsCollector)
|
||||
{
|
||||
statsCollector = new StatsCollector(
|
||||
getConferenceHandler().peerconnection, 200, statsUpdated);
|
||||
|
||||
stopLocalRtpStatsCollector();
|
||||
|
||||
statsCollector.start();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Starts the {@link LocalStatsCollector} if the feature is enabled in config.js
|
||||
* @param stream the stream that will be used for collecting statistics.
|
||||
*/
|
||||
function startLocalRtpStatsCollector(stream)
|
||||
{
|
||||
if(config.enableRtpStats)
|
||||
{
|
||||
localStatsCollector = new LocalStatsCollector(stream, 200, localStatsUpdated);
|
||||
localStatsCollector.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the {@link LocalStatsCollector}.
|
||||
*/
|
||||
function stopLocalRtpStatsCollector()
|
||||
{
|
||||
if(localStatsCollector)
|
||||
{
|
||||
localStatsCollector.stop();
|
||||
localStatsCollector = null;
|
||||
}
|
||||
}
|
||||
|
||||
$(document).bind('callincoming.jingle', function (event, sid) {
|
||||
var sess = connection.jingle.sessions[sid];
|
||||
|
@ -965,10 +1009,10 @@ $(window).bind('beforeunload', function () {
|
|||
}
|
||||
});
|
||||
}
|
||||
disposeConference();
|
||||
disposeConference(true);
|
||||
});
|
||||
|
||||
function disposeConference() {
|
||||
function disposeConference(onUnload) {
|
||||
var handler = getConferenceHandler();
|
||||
if (handler && handler.peerconnection) {
|
||||
// FIXME: probably removing streams is not required and close() should be enough
|
||||
|
@ -985,6 +1029,13 @@ function disposeConference() {
|
|||
statsCollector.stop();
|
||||
statsCollector = null;
|
||||
}
|
||||
if(!onUnload) {
|
||||
startLocalRtpStatsCollector(connection.jingle.localAudio);
|
||||
}
|
||||
else
|
||||
{
|
||||
stopLocalRtpStatsCollector();
|
||||
}
|
||||
focus = null;
|
||||
activecall = null;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<script src="moderatemuc.js?v=3"></script><!-- moderator plugin -->
|
||||
<script src="analytics.js?v=1"></script><!-- google analytics plugin -->
|
||||
<script src="rtp_stats.js?v=1"></script><!-- RTP stats processing -->
|
||||
<script src="local_stats.js?v=1"></script><!-- Local stats processing -->
|
||||
<script src="videolayout.js?v=4"></script><!-- video ui -->
|
||||
<script src="toolbar.js?v=2"></script><!-- toolbar ui -->
|
||||
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* Provides statistics for the local stream.
|
||||
*/
|
||||
var LocalStatsCollector = (function() {
|
||||
/**
|
||||
* Size of the webaudio analizer buffer.
|
||||
* @type {number}
|
||||
*/
|
||||
var WEBAUDIO_ANALIZER_FFT_SIZE = 512;
|
||||
|
||||
/**
|
||||
* Value of the webaudio analizer smoothing time parameter.
|
||||
* @type {number}
|
||||
*/
|
||||
var WEBAUDIO_ANALIZER_SMOOTING_TIME = 0.1;
|
||||
|
||||
/**
|
||||
* <tt>LocalStatsCollector</tt> calculates statistics for the local stream.
|
||||
*
|
||||
* @param stream the local stream
|
||||
* @param interval stats refresh interval given in ms.
|
||||
* @param {function(LocalStatsCollector)} updateCallback the callback called on stats
|
||||
* update.
|
||||
* @constructor
|
||||
*/
|
||||
function LocalStatsCollectorProto(stream, interval, updateCallback) {
|
||||
window.AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
this.stream = stream;
|
||||
this.intervalId = null;
|
||||
this.intervalMilis = interval;
|
||||
this.updateCallback = updateCallback;
|
||||
this.audioLevel = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Starts the collecting the statistics.
|
||||
*/
|
||||
LocalStatsCollectorProto.prototype.start = function () {
|
||||
if (!window.AudioContext)
|
||||
return;
|
||||
|
||||
var context = new AudioContext();
|
||||
var analyser = context.createAnalyser();
|
||||
analyser.smoothingTimeConstant = WEBAUDIO_ANALIZER_SMOOTING_TIME;
|
||||
analyser.fftSize = WEBAUDIO_ANALIZER_FFT_SIZE;
|
||||
|
||||
|
||||
var source = context.createMediaStreamSource(this.stream);
|
||||
source.connect(analyser);
|
||||
|
||||
|
||||
var self = this;
|
||||
|
||||
this.intervalId = setInterval(
|
||||
function () {
|
||||
var array = new Uint8Array(analyser.frequencyBinCount);
|
||||
analyser.getByteFrequencyData(array);
|
||||
self.audioLevel = FrequencyDataToAudioLevel(array);
|
||||
self.updateCallback(self);
|
||||
},
|
||||
this.intervalMilis
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops collecting the statistics.
|
||||
*/
|
||||
LocalStatsCollectorProto.prototype.stop = function () {
|
||||
if (this.intervalId) {
|
||||
clearInterval(this.intervalId);
|
||||
this.intervalId = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts frequency data array to audio level.
|
||||
* @param array the frequency data array.
|
||||
* @returns {number} the audio level
|
||||
*/
|
||||
var FrequencyDataToAudioLevel = function (array) {
|
||||
var maxVolume = 0;
|
||||
|
||||
var length = array.length;
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (maxVolume < array[i])
|
||||
maxVolume = array[i];
|
||||
}
|
||||
|
||||
return maxVolume / 255;
|
||||
}
|
||||
|
||||
return LocalStatsCollectorProto;
|
||||
})();
|
Loading…
Reference in New Issue