This is an automated email from the ASF dual-hosted git repository. solomax pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/openmeetings.git
The following commit(s) were added to refs/heads/master by this push: new a5fb3ae [OPENMEETINGS-2029] audio/video should work better a5fb3ae is described below commit a5fb3ae0e1cd0cacb2355a5c918859cbf5691a29 Author: Maxim Solodovnik <solomax...@gmail.com> AuthorDate: Tue Mar 12 23:47:47 2019 +0700 [OPENMEETINGS-2029] audio/video should work better --- .../apache/openmeetings/web/room/RoomPanel.html | 2 +- .../openmeetings/web/room/VideoSettings.html | 2 +- .../apache/openmeetings/web/room/kurento-utils.js | 4 +- .../apache/openmeetings/web/room/raw-settings.js | 82 +++++++++++++++------- .../org/apache/openmeetings/web/room/raw-video.js | 45 +++++++----- openmeetings-web/src/main/webapp/css/raw-room.css | 15 +--- .../src/main/webapp/css/raw-variables.css | 1 + 7 files changed, 89 insertions(+), 62 deletions(-) diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html index 15f281a..50ded0c 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/RoomPanel.html @@ -43,7 +43,7 @@ <div style="display:none"> <div id="user-video"> <div class="video"> - <div class="level-meter" wicket:message="title:767"></div> + <canvas width="10" class="level-meter" wicket:message="title:767"></canvas> <div class="mute-others" wicket:message="title:video.muteothers"></div> </div> <div class="footer ui-state-highlight"> diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/VideoSettings.html b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/VideoSettings.html index ab04f44..4fbce9c 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/VideoSettings.html +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/VideoSettings.html @@ -70,7 +70,7 @@ <div class="video-conainer"> <video autoplay="autoplay"></video> </div> - <div class="level-meter" wicket:message="title:767"></div> + <canvas class="level-meter" data-orientation="horizontal" wicket:message="title:767" width="250" height="16"></canvas> <div class="sett-row right"> <div class="timer ui-widget-header"><span class="time"></span> <wicket:message key="network.test.sec"/></div> <div><button class="play"><wicket:message key="764"/></button></div> diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/kurento-utils.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/kurento-utils.js index f4bad72..3c1fc36 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/kurento-utils.js +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/kurento-utils.js @@ -400,12 +400,12 @@ function WebRtcPeer(mode, options, callback) { } if (videoStream) { videoStream.getTracks().forEach(function(track) { - pc.addTrack(track); + pc.addTrack(track, videoStream); }); } if (audioStream) { audioStream.getTracks().forEach(function(track) { - pc.addTrack(track); + pc.addTrack(track, audioStream); }); } var browser = parser.getBrowser(); diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-settings.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-settings.js index 8fcebb0..704c197 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-settings.js +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-settings.js @@ -14,9 +14,9 @@ $.widget('openmeetings.iconselectmenu', $.ui.selectmenu, { } }); var MicLevel = (function() { - let ctx, mic, script, vol = .0; + let ctx, mic, analyser, vol = .0; - function _meter(rtcPeer, _micActivity, _error) { + function _meterPeer(rtcPeer, cnvs, _micActivity, _error) { if (!rtcPeer || 'function' !== typeof(rtcPeer.getLocalStream)) { return; } @@ -25,28 +25,55 @@ var MicLevel = (function() { return; } try { - ctx = new AudioContext(); - script = ctx.createScriptProcessor(512); + const AudioCtx = window.AudioContext || window.webkitAudioContext; + if (!AudioCtx) { + _error("AudioContext is inaccessible"); + return; + } + ctx = new AudioCtx(); + analyser = ctx.createAnalyser(); mic = ctx.createMediaStreamSource(stream); - mic.connect(script); - script.connect(ctx.destination); - let t = Date.now(); - script.onaudioprocess = function(event) { - const arr = event.inputBuffer.getChannelData(0) - , al = arr.length; - let avg = 0.0; - for (let i = 0; i < al; ++i) { - avg += arr[i] * arr[i]; - } - avg = Math.sqrt(avg / al); - vol = Math.max(avg, vol * .95); - //we will continuously get volume but do not perform re-draw too often - if (Date.now() - t < 200) { - return; + mic.connect(analyser); + analyser.connect(ctx.destination); + _meter(analyser, cnvs, _micActivity, _error); + } catch (err) { + _error(err); + } + } + function _meter(analyser, cnvs, _micActivity, _error) { + try { + analyser.minDecibels = -90; + analyser.maxDecibels = -10; + analyser.fftSize = 256; + const canvas = cnvs[0] + , color = $('body').css('--level-color') + , canvasCtx = canvas.getContext('2d') + , al = analyser.frequencyBinCount + , arr = new Uint8Array(al) + , horiz = cnvs.data('orientation') === 'horizontal'; + function update() { + const WIDTH = canvas.width + , HEIGHT = canvas.height; + canvasCtx.clearRect(0, 0, WIDTH, HEIGHT); + if (!!analyser && cnvs.is(':visible')) { + analyser.getByteFrequencyData(arr); + let favg = 0.0; + for (let i = 0; i < al; ++i) { + favg += arr[i] * arr[i]; + } + vol = Math.sqrt(favg / al); + _micActivity(vol); + canvasCtx.fillStyle = color; + if (horiz) { + canvasCtx.fillRect(0, 0, WIDTH * vol / 100, HEIGHT); + } else { + const h = HEIGHT * vol / 100; + canvasCtx.fillRect(0, HEIGHT - h, WIDTH, h); + } + requestAnimationFrame(update); } - t = Date.now(); - _micActivity(vol); - }; + } + update(); } catch (err) { _error(err); } @@ -56,14 +83,17 @@ var MicLevel = (function() { VideoUtil.cleanStream(mic.mediaStream); mic.disconnect(); ctx.destination.disconnect(); - script.disconnect(); - script.onaudioprocess = null; ctx.close(); ctx = null; } + if (!!analyser) { + analyser.disconnect(); + analyser = null; + } } return { meter: _meter + , meterPeer: _meterPeer , dispose: _dispose }; }); @@ -205,7 +235,6 @@ var VideoSettings = (function() { _close(); } }); - lm.kendoProgressBar({ value: 0, showStatus: false }); o.width = 300; o.height = 200; o.mode = 'settings'; @@ -304,7 +333,7 @@ var VideoSettings = (function() { return OmUtil.error(error); } level = MicLevel(); - level.meter(rtcPeer, _micActivity, OmUtil.error); + level.meterPeer(rtcPeer, lm, _micActivity, OmUtil.error); rtcPeer.generateOffer(function(error, _offerSdp) { if (error) { return OmUtil.error('Error generating the offer'); @@ -328,7 +357,6 @@ var VideoSettings = (function() { _updateRec(); } function _micActivity(level) { - lm.getKendoProgressBar().value(140 * level); // magic number } function _setLoading(el) { el.find('option').remove(); diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video.js index 79897fe..201c71d 100644 --- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video.js +++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-video.js @@ -1,8 +1,9 @@ /* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */ var Video = (function() { - const self = {}; + const self = {} + , AudioCtx = window.AudioContext || window.webkitAudioContext; let sd, v, vc, t, f, size, vol, slider, handle, video, rtcPeer - , lastVolume = 50, muted = false, aCtx, aSrc, aDest, gainNode + , lastVolume = 50, muted = false, aCtx, aSrc, aDest, gainNode, analyser , lm, level, userSpeaks = false, muteOthers; function _getExtra() { @@ -21,16 +22,19 @@ var Video = (function() { , pw = p.width(), ph = p.height(); _resizeDlgArea(pw, ph); } - function _resize(w, h) { - vc.width(w).height(h); + function _resizeLm(h) { if (!!lm) { - lm.height(h - 10); + lm.attr('height', h).height(h); } + return lm; + } + function _resize(w, h) { + vc.width(w).height(h); + _resizeLm(h - 10); video.width(w).height(h); } function _micActivity(level) { - lm.getKendoProgressBar().value(140 * level); // magic number - const speaks = level > .02; + const speaks = level > 5; if (speaks !== userSpeaks) { userSpeaks = speaks; OmUtil.sendMessage({type: 'mic', id: 'activity', active: speaks}); @@ -90,18 +94,19 @@ var Video = (function() { let _stream = stream; if (stream.getAudioTracks().length !== 0) { vol.show(); - lm = vc.find('.level-meter') - .kendoProgressBar({ value: 0, showStatus: false, orientation: 'vertical' }); - lm.height(vc.height() - 10).show(); - aCtx = new AudioContext(); + lm = vc.find('.level-meter'); + _resizeLm(vc.height() - 10).show(); + aCtx = new AudioCtx(); gainNode = aCtx.createGain(); + analyser = aCtx.createAnalyser(); aSrc = aCtx.createMediaStreamSource(stream); aSrc.connect(gainNode); + gainNode.connect(analyser); if (VideoUtil.isEdge()) { - gainNode.connect(aCtx.destination); + analyser.connect(aCtx.destination); } else { aDest = aCtx.createMediaStreamDestination(); - gainNode.connect(aDest); + analyser.connect(aDest); aSrc.origStream = stream; _stream = aDest.stream; stream.getVideoTracks().forEach(function(track) { @@ -133,7 +138,7 @@ var Video = (function() { return OmUtil.error(error); } level = MicLevel(); - level.meter(rtcPeer, _micActivity, OmUtil.error); + level.meter(analyser, lm, _micActivity, OmUtil.error); this.generateOffer(function(error, offerSdp) { if (error) { return OmUtil.error('Sender sdp offer error ' + error); @@ -441,6 +446,10 @@ var Video = (function() { } function _cleanup() { OmUtil.log('Disposing participant ' + sd.uid); + if (!!analyser) { + analyser.disconnect(); + analyser = null; + } if (!!gainNode) { gainNode.disconnect(); gainNode = null; @@ -463,9 +472,11 @@ var Video = (function() { aCtx = null; } if (!!video && video.length > 0) { - VideoUtil.cleanStream(video[0].srcObject); - video[0].srcObject = null; - video.remove(); + video.attr('id', 'dummy'); + const vidNode = video[0]; + VideoUtil.cleanStream(vidNode.srcObject); + vidNode.srcObject = null; + vidNode.parentNode.removeChild(vidNode); video = null; } if (!!lm && lm.length > 0) { diff --git a/openmeetings-web/src/main/webapp/css/raw-room.css b/openmeetings-web/src/main/webapp/css/raw-room.css index 7337177..c40ceed 100644 --- a/openmeetings-web/src/main/webapp/css/raw-room.css +++ b/openmeetings-web/src/main/webapp/css/raw-room.css @@ -282,26 +282,16 @@ ul.settings-menu { min-width: 300px; padding-left: 305px; } -#video-settings .level-meter { - height: 16px; -} .ui-dialog.video .warn { float: right; margin-right: .3em; } -.level-meter.k-progressbar .k-state-selected { - background: greenyellow; - border-color: #d5d5d5; -} -.ui-dialog.video .level-meter { - background: transparent; -} .ui-dialog.user-video .level-meter { display: inline-block; - width: 10px; position: absolute; bottom: 5px; left: 5px; + width: 10px; } .ui-dialog.video .sett-container { position: relative; @@ -322,9 +312,6 @@ ul.settings-menu { float: left; padding: 2px 4px; } -.ui-dialog.video .sett-row select, #video-settings .level-meter { - width: 250px; -} .ui-dialog.video .ui-dialog-titlebar-collapse span , .ui-dialog.video .ui-dialog-titlebar-volume span , .ui-dialog.video .ui-dialog-titlebar-refresh span diff --git a/openmeetings-web/src/main/webapp/css/raw-variables.css b/openmeetings-web/src/main/webapp/css/raw-variables.css index dc2552f..a7e8679 100644 --- a/openmeetings-web/src/main/webapp/css/raw-variables.css +++ b/openmeetings-web/src/main/webapp/css/raw-variables.css @@ -19,6 +19,7 @@ body { --header-height: 50px; --menu-height: 36px; + --level-color: greenyellow; } body.no-header { --header-height: 0px;