-
Notifications
You must be signed in to change notification settings - Fork 5.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a demo for "Unprocessed volume" #993
Changes from all commits
35da7a0
511e8f8
3270564
b08d2f9
a8008a4
ed5f742
927b73c
23e74df
31d636a
1e7da70
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<!DOCTYPE html> | ||
<!-- | ||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. | ||
* | ||
* Use of this source code is governed by a BSD-style license | ||
* that can be found in the LICENSE file in the root of the source | ||
* tree. | ||
--> | ||
<html> | ||
<head> | ||
|
||
<meta charset="utf-8"> | ||
<meta name="description" content="WebRTC code samples"> | ||
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1, maximum-scale=1"> | ||
<meta itemprop="description" content="Client-side WebRTC code samples"> | ||
<meta itemprop="image" content="../../../images/webrtc-icon-192x192.png"> | ||
<meta itemprop="name" content="WebRTC code samples"> | ||
<meta name="mobile-web-app-capable" content="yes"> | ||
<meta id="theme-color" name="theme-color" content="#ffffff"> | ||
|
||
<base target="_blank"> | ||
|
||
<title>Audio stream volume</title> | ||
|
||
<link rel="icon" sizes="192x192" href="../../../images/webrtc-icon-192x192.png"> | ||
<link href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet" type="text/css"> | ||
<link rel="stylesheet" href="../../../css/main.css" /> | ||
|
||
</head> | ||
|
||
<body> | ||
|
||
<div id="container"> | ||
|
||
<h1><a href="//webrtc.github.io/samples/" title="WebRTC samples homepage">WebRTC samples</a> <span>Audio stream volume</span></h1> | ||
|
||
<p>Measure the volume of a local media stream using WebAudio.</p> | ||
|
||
<div id="meters"> | ||
<div id="instant"> | ||
<div class="label">Instant: </div> | ||
<meter high="0.25" max="1" value="0"></meter> | ||
<div class="value"></div> | ||
</div> | ||
<div id="slow"> | ||
<div class="label">Slow: </div> | ||
<meter high="0.25" max="1" value="0"></meter> | ||
<div class="value"></div> | ||
</div> | ||
<div id="unprocessed"> | ||
<div class="label">Unprocessed: </div> | ||
<meter high="0.25" max="1" value="0"></meter> | ||
<div class="value"></div> | ||
</div> | ||
</div> | ||
|
||
<p>The 'instant' volume changes approximately every 50ms; the 'slow' volume approximates the average volume over about a second.</p> | ||
<p>The third meter shows the volume of a track without audio processing applied; this should be the "input volume".</p> | ||
<p>Note that you will not hear your own voice; use the <a href="../audio">local audio rendering demo</a> for that.</p> | ||
<p>The <code>audioContext</code>, <code>stream</code> and <code>soundMeter</code> variables are in global scope, so you can inspect them from the console.</p> | ||
|
||
<p id="errorMsg" style="color: red;"></p> | ||
<p> | ||
<a href="https://github.com/webrtc/samples/tree/gh-pages/src/content/getusermedia/volume" title="View source for this page on GitHub" id="viewSource">View source on GitHub</a> | ||
</p> | ||
|
||
</div> | ||
|
||
|
||
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script> | ||
<script src="../../../js/common.js"></script> | ||
<script src="../volume/js/soundmeter.js"></script> | ||
<script src="js/main.js"></script> | ||
|
||
<script src="../../../js/lib/ga.js"></script> | ||
|
||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. | ||
* | ||
* Use of this source code is governed by a BSD-style license | ||
* that can be found in the LICENSE file in the root of the source | ||
* tree. | ||
*/ | ||
|
||
/* global AudioContext, SoundMeter */ | ||
|
||
'use strict'; | ||
|
||
const instantMeter = document.querySelector('#instant meter'); | ||
const slowMeter = document.querySelector('#slow meter'); | ||
const unprocessedMeter = document.querySelector('#unprocessed meter'); | ||
|
||
const instantValueDisplay = document.querySelector('#instant .value'); | ||
const slowValueDisplay = document.querySelector('#slow .value'); | ||
const unprocessedValueDisplay = document.querySelector('#unprocessed .value'); | ||
const errorMsg = document.querySelector('#errorMsg'); | ||
|
||
try { | ||
window.AudioContext = window.AudioContext || window.webkitAudioContext; | ||
window.audioContext = new AudioContext(); | ||
} catch (e) { | ||
alert('Web Audio API not supported.'); | ||
} | ||
|
||
// Put variables in global scope to make them available to the browser console. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what what this means. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sam wrote this... but var at top scope have always been available in the console or window[]. No longer true for es6 const/let notably. |
||
let constraints = window.constraints = { | ||
audio: {echoCancellation: true}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be echoCancellation: {exact:true} so that we fail if it cannot be satisfied? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find it confusing and error prone that the same constraints are setup up as a global variable, then used, then modified. If the demo were to have a reset button it would stop working unless this is explicitly reset. I've also not seen "let constraints = window.constraints = ...". Wouldn't "let constraints" work? Or if that didn't work, why not "var constraints"? I don't see this variable adding anything. Can we just pass the desired constraints when we call getUserMedia? Not have a variable for it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ping @alvestrand. I didn't update this part. :) |
||
video: false | ||
}; | ||
|
||
async function handleSuccess(stream) { | ||
// Put variables in global scope to make them available to the | ||
// browser console. | ||
window.stream = stream; | ||
const soundMeter = window.soundMeter = new SoundMeter(window.audioContext); | ||
errorMsg.innerText = ''; | ||
|
||
try { | ||
// eslint-disable-next-line no-unused-vars | ||
const ignored = await soundMeter.connectToSource(stream); | ||
setInterval(function() { | ||
instantMeter.value = instantValueDisplay.innerText = | ||
soundMeter.instant.toFixed(2); | ||
slowMeter.value = slowValueDisplay.innerText = | ||
soundMeter.slow.toFixed(2); | ||
}, 200); | ||
} catch (e) { | ||
handleError(e); | ||
} | ||
|
||
const audioSettings = JSON.stringify(stream.getAudioTracks()[0].getSettings()); | ||
console.log('First track settings:', audioSettings); | ||
|
||
// Set up second track with audio processing disabled | ||
constraints.audio = {echoCancellation: {exact: false}}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any reason why this is {exact: false} and not false? |
||
trace('Getting second audio stream'); | ||
try { | ||
const secondStream = await navigator.mediaDevices.getUserMedia(constraints); | ||
// eslint-disable-next-line no-unused-vars | ||
const ignore = await handleUnprocessedStream(secondStream); | ||
} catch (e) { | ||
handleError(e); | ||
} | ||
} | ||
|
||
async function handleUnprocessedStream(stream) { | ||
trace('Got second audio stream'); | ||
trace('Second track settings: ', | ||
JSON.stringify(stream.getAudioTracks()[0].getSettings())); | ||
trace('Second track constraints: ', | ||
JSON.stringify(stream.getAudioTracks()[0].getConstraints())); | ||
const unprocMeter = window.unprocMeter = new SoundMeter(window.audioContext); | ||
try { | ||
// eslint-disable-next-line no-unused-vars | ||
const ignored = await unprocMeter.connectToSource(stream); | ||
setInterval(function() { | ||
unprocessedMeter.value = unprocessedValueDisplay.innerText = | ||
unprocMeter.slow.toFixed(2); | ||
}, 200); | ||
} catch (e) { | ||
handleError(e); | ||
} | ||
} | ||
|
||
function handleError(error) { | ||
trace('navigator.getUserMedia error: ', error); | ||
errorMsg.innerText = `navigator.getUserMedia error: ${error}`; | ||
} | ||
|
||
async function init() { | ||
try { | ||
const stream = await navigator.mediaDevices.getUserMedia(constraints); | ||
// eslint-disable-next-line no-unused-vars | ||
const ignored = await handleSuccess(stream); | ||
} catch (e) { | ||
handleError(e); | ||
} | ||
} | ||
|
||
// noinspection JSIgnoredPromiseFromCall | ||
init(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are not printing the actual error,
e
is unused.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe you can do try { } catch { }.