WebRTC打开麦克风,获取音频,在网页上显示音量。

播放示例音频

先从播放音频入手。准备一个现成的音频文件。

界面上放一个audio元素,提前准备好一个音频文件,路径填入src

<audio id="sample-audio" src="God_knows_01.mp3" controls autoplay></audio>

audio有默认的样式。打开网页就可以利用这个来播放示例音频了。

WebRTC打开麦克风

准备

html页面上放audio,meter,button等等

<audio id="play-audio" controls autoplay></audio>

<div id="meters">
<div id="instant">
<div class="label">实时:</div>
<meter high="0.25" max="1" value="0"></meter>
<div class="value"></div>
</div>
<div id="slow">
<div class="label">秒级:</div>
<meter high="0.25" max="1" value="0"></meter>
<div class="value"></div>
</div>
<div id="clip">
<div class="label">Clip:</div>
<meter max="1" value="0"></meter>
<div class="value"></div>
</div>
</div> <div>
<button id="startBtn">启动</button>
<button id="stopBtn" disabled>停止</button>
</div> <div id="msg"></div>

引入js脚本

    <!-- 使用本地的适配器 -->
<script src="../js/adapter-latest.js" async></script>
<script src="js/soundmeter.js"></script>
<script src="js/main.js"></script>
  • 使用了本地的适配器
  • main.js 主要的控制逻辑
  • soundmeter.js 计算音频音量的方法

soundmeter.js

在使用WebRTC之前,先来看音频相关的方法和类。

要使用web的音频API,需要用到AudioContext

try {
window.AudioContext = window.AudioContext || window.webkitAudioContext;
window.audioContext = new AudioContext();
} catch (e) {
alert('Web Audio API 不支持');
}

AudioContext.createScriptProcessor(int, int, int)

创建js处理音频的工具,接受3个数字参数

  • bufferSize

    • 缓冲区大小,以样本帧为单位。具体来讲,数值必须是以下这些值当中的某一个: 256, 512, 1024, 2048, 4096, 8192, 16384. 如果不传,或者参数为0,则取当前环境最合适的缓冲区大小, 取值为2的幂次方的一个常数,在该node的整个生命周期中都不变.
    • 该取值控制着audioprocess事件被分派的频率,以及每一次调用多少样本帧被处理. 较低bufferSzie将导致一定的延迟。较高的bufferSzie就要注意避免音频的崩溃和故障。推荐作者不要给定具体的缓冲区大小,让系统自己选一个好的值来平衡延迟和音频质量。
    • 重要: Webkit (version 31)要求调用这个方法的时候必须传入一个有效的bufferSize .
  • numberOfInputChannels
    • 值为整数,用于指定输入node的声道的数量,默认值是2,最高能取32.
  • numberOfOutputChannels
    • 值为整数,用于指定输出node的声道的数量,默认值是2,最高能取32.

参考:https://developer.mozilla.org/zh-CN/docs/Web/API/BaseAudioContext/createScriptProcessor

AudioContext.onaudioprocess

监听音频数据

基本用法

var audioCtx = new AudioContext();
var scriptNode = audioCtx.createScriptProcessor(4096, 1, 1);
scriptNode.onaudioprocess = function(event) { /* ... */ }

本文示例使用这个监听。但它目前已经不推荐使用(deprecated)了。

参考:https://developer.mozilla.org/en-US/docs/Web/API/ScriptProcessorNode/onaudioprocess#browser_compatibility

完整soundmeter.js代码如下

'use strict';

// 这个类生成音频音量相关的数值
function SoundMeter(context) {
this.context = context;
this.instant = 0.0; // 实时
this.slow = 0.0; // 秒级
this.clip = 0.0;
this.script = context.createScriptProcessor(2048, 1, 1);
const that = this;
this.script.onaudioprocess = function (event) {
const input = event.inputBuffer.getChannelData(0); // 得到一个长度为2048的数组
let i;
let sum = 0.0;
let clipcount = 0;
for (i = 0; i < input.length; ++i) {
sum += input[i] * input[i];
if (Math.abs(input[i]) > 0.99) {
clipcount += 1;
}
}
console.log('clip count', clipcount);
that.instant = Math.sqrt(sum / input.length);
that.slow = 0.95 * that.slow + 0.05 * that.instant;
that.clip = clipcount / input.length;
};
} SoundMeter.prototype.connectToSource = function (stream, callback) {
console.log('SoundMeter connecting');
try {
this.mic = this.context.createMediaStreamSource(stream);
this.mic.connect(this.script);
this.script.connect(this.context.destination);
if (typeof callback !== 'undefined') {
callback(null);
}
} catch (e) {
console.error(e);
if (typeof callback !== 'undefined') {
callback(e);
}
}
}; SoundMeter.prototype.stop = function () {
console.log('SoundMeter 正在停止');
this.mic.disconnect();
this.script.disconnect();
};

js

获取页面元素

'use strict';

const instantMeter = document.querySelector('#instant meter');
const slowMeter = document.querySelector('#slow meter');
const clipMeter = document.querySelector('#clip meter'); const instantValueDisplay = document.querySelector('#instant .value');
const slowValueDisplay = document.querySelector('#slow .value');
const clipValueDisplay = document.querySelector('#clip .value'); const playAudio = document.querySelector('#play-audio');
const msgEle2 = document.querySelector("#msg");
const startBtn = document.getElementById("startBtn");
const stopBtn = document.getElementById('stopBtn'); let meterRefresh = null; const constraints = window.constraints = {
audio: true,
video: false
};

开启麦克风

开启麦克风,和之前打开摄像头类似,用的也是getUserMedia方法。

startBtn.onclick = function (e) {
startBtn.disabled = true;
stopBtn.disabled = false;
try {
window.AudioContext = window.AudioContext || window.webkitAudioContext;
window.audioContext = new AudioContext();
} catch (e) {
alert('Web Audio API 不支持.');
}
navigator.mediaDevices.getUserMedia(constraints).then(gotAudioStream).catch(onErr);
};

处理音频

成功打开麦克风后,处理音频流

function gotAudioStream(stream) {
stream.oninactive = function () {
console.log('音频停止');
};
window.stream = stream;
playAudio.srcObject = stream; console.log('对接麦克风的音频'); const soundMeter = window.soundMeter = new SoundMeter(window.audioContext);
soundMeter.connectToSource(stream, function (e) {
if (e) {
alert(e);
return;
}
meterRefresh = setInterval(() => {
instantMeter.value = instantValueDisplay.innerText =
soundMeter.instant.toFixed(2);
slowMeter.value = slowValueDisplay.innerText =
soundMeter.slow.toFixed(2);
clipMeter.value = clipValueDisplay.innerText =
soundMeter.clip;
}, 100);
});
} function onErr(error) {
const errorMessage = '报错 navigator.MediaDevices.getUserMedia : ' + error.message + ' ' + error.name;
msgEle2.innerText = errorMessage;
console.error(errorMessage);
}

创建soundMeter,对接到音频流soundMeter.connectToSource(stream, function(e){});

设置一个定时器setInterval,定时刷新音量数据

停止

把音频流停下

stopBtn.onclick = function (e) {
console.log('停止');
startBtn.disabled = false;
stopBtn.disabled = true;
window.stream.getTracks().forEach(track => track.stop());
window.soundMeter.stop();
clearInterval(meterRefresh);
instantMeter.value = instantValueDisplay.innerText = '';
slowMeter.value = slowValueDisplay.innerText = '';
clipMeter.value = clipValueDisplay.innerText = '';
}

运行效果

运行效果链接

小结

getUserMedia打开麦克风,获取音频流。使用AudioContext的功能,得到音频音量的数值。

本文链接:WebRTC音频音量

WebRTC与音频音量的更多相关文章

  1. 单独编译使用WebRTC的音频处理模块

    块,每块个点,(12*64=768采样)即AEC-PC仅能处理48ms的单声道16kHz延迟的数据,而 - 加载编译好的NS模块动态库 接下来只需要按照 此文 的描述在 android 的JAVA代码 ...

  2. 【单独编译使用WebRTC的音频处理模块 - android】

    更新 [2015年2月15日] Bill 这段时间没有再关注 WebRTC 以及音频处理的相关信息,且我个人早已不再推荐单独编译 WebRTC 中的各个模块出来使用.实际上本文的参考价值已经很小了,甚 ...

  3. //点击按钮加减音频音量到最小会出现bug什么意思???

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. 千位分隔符,音频音量加强,transform 垂直居中

    1.最近做阴阳师日本官网,其中有个功能是获取预约人数,设计稿上的人数是这样151,567,000,想了想自己写还有点麻烦,于是网上copy了代码,再修改了下. 其中,有一点需要注意的是:函数中的str ...

  5. WebRTC APM音频处理流程概述

    本文主要介绍WebRTC的APM. 现在主要介绍一下audio_processing.h. 首先插入了几个类,这些都是audio_processing的核心模块. class AudioFrame; ...

  6. C++ 调节PCM音频音量大小

    在用解码器解码音频数据得到PCM音频数据块之后,可以在将数据送给声卡播放之前调节其音量大小,具体的实现函数如下: void RaiseVolume(char* buf, UINT32 size, UI ...

  7. WebRTC的音频编码(转)

    一.一个典型的IP通信模型 二.Server2Server技术分类 Server2Server这块也是一个专门的领域,这里只简单分个类. 1.同一国家相同运营商之间: 同一运营商之间也有丢包,在铁通, ...

  8. webrtc的音频处理模块apm( audio processing)下载与编译出libwebrtc_audio_preprocessing.so

    webrtc代码在android和chromium项目中都有.但是android中的那个带有Android.mk,稍微修改下就能用ndk-build编译出libwebrtc_audio_preproc ...

  9. 基于webRTC技术 音频和视频,IM解

    由于原来的文章 http://blog.csdn.net/voipmaker  转载注明出处. 基于WebRTC技术可实现点对点音视频.即时通信.视频会议.最新的系统组件包含: TeleICE NAT ...

随机推荐

  1. [atAGC047F]Rooks

    如果将$x$和$y$都离散,那么删除的点的$x_{i}$和$y_{i}$必然都组成了一个完整的区间(包括过程中) 将所有点按$x$排序,再令$f[i][j][0/1]$表示当删除完区间$[i,j]$且 ...

  2. jvm的小练习

    代码如下: public static void main(String[] args) { byte[] array= new byte[1024*1024]; array=new byte[102 ...

  3. tomcat进行远程debug

    Windows下   进入目录下的bin目录,编辑打开startup.bat 在前面添加: SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Djava.com ...

  4. [源码解析] PyTorch 分布式 Autograd (2) ---- RPC基础

    [源码解析] PyTorch 分布式 Autograd (2) ---- RPC基础 目录 [源码解析] PyTorch 分布式 Autograd (2) ---- RPC基础 0x00 摘要 0x0 ...

  5. 洛谷 P3285 - [SCOI2014]方伯伯的OJ(平衡树)

    洛谷题面传送门 在酒店写的,刚了一整晚终于调出来了-- 首先考虑当 \(n\) 比较小(\(10^5\) 级别)的时候怎么解决,我们考虑将所有用户按排名为关键字建立二叉排序树,我们同时再用一个 map ...

  6. [R] read.table的check.names参数防止读入数据时列名前自动加上"X."

    最近用之前写的R脚本重新跑数据时,出现了报错.经检查,才发现是数据的列名读入R时发生了变化,列名前自动加上了X.符号. read.table系列函数有一个check.names参数,默认为 TRUE ...

  7. R语言与医学统计图形-【9】过渡函数qplot

    ggplot2绘图系统 基础绘图包向ggplot2过渡--qplot 绘图理念的不同: 基础绘图包是先铺好画布,再在这张画布上作图(常规思维): ggplot2打破常规,采用图层叠加的方法. qplo ...

  8. nginx_日志

    192.168.31.250 - - [13/Nov/2019:08:38:07 +0800] "GET /aa HTTP/1.1" 404 571 "-" & ...

  9. Linux—ps -ef 命令输出信息的具体含义(显示所有正在运行的命令程序)

    linux 中使用 ps -ef 输出参数的具体含义 功能:显示所有正在运行的命令程序 UID: 说明该程序被谁拥有PID:就是指该程序的 IDPPID: 就是指该程序父级程序的 IDC: 指的是 C ...

  10. 26-Palindrome Number

    回文数的判定,不使用额外的空间 Determine whether an integer is a palindrome. Do this without extra space. 思路:将一个整数逆 ...