使用WebAPI获取麦克风MediaStream(媒体流)+显示频谱+【控制麦克风音量】(.net FrameWork MVC)
使用WebAPI获取麦克风MediaStream(媒体流)+显示频谱+【控制麦克风输入音量】(.net FrameWork MVC)
一、使用WebAPI官网获取麦克风MediaStream(媒体流)+并实时显示频谱
效果如图:
选择媒体文件播放后(系统声音)显示其频谱可参考另一博客
呼叫台功能页面布局【canvas绘制音频频谱图】【绘制音量控制滑块】 (示例使用.net framework mvc) - じ逐梦 - 博客园 (cnblogs.com)
1/1、定义全局变量
var localStream;// 录音产生的音频流、麦克风收集到的音频数据 let audioCtx = null; // 音频上下文 let source = null; // 音频源 let localStream = null; // 录音产生的音频流 录音产生的音频流、麦克风收集到的音频数据 let analyser = null; // 用于分析音频实时数据的节点(分析器)
1/2利用Web Audio Api 处理获取麦克风音频流数据
获取到音频流之后,我们通过音频上下文AudioContext,创建音频源。这里选择MediaStreamAudioSourceNode,它接收一个MediaStream对象来创建音频源。 然后我们在音频源和destination中间插入一个音频节点,用来获取及处理音频数据,进而利用数据绘制出波形图。这里选择AnalyserNode,当然像ScriptProcessorNode和AudioWorkletNode节点也能够实现获取和处理实时音频数据,具体可以参考相关Api。
当前业务-点击左上角呼叫台总开关-调用start方法(获取麦克风音频使用web audio api,我们在页面一加载就获取麦克风数据,否则出现时序问题)
$(function () { var constraints = { video: false, audio: true,//音频 } if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { console.error('浏览器不支持getUserMedia') return; } else { navigator.mediaDevices.getUserMedia(constraints) .then(function gotMediaStream(stream) { localStream = stream;//麦克风采集到的数据赋值给全局变量 initAudioData(localStream);//调用音频数据处理方法--调用显示频谱的方法 }) .catch(handleError); } }
1/3音频数据处理并绘制频谱 调用initAudioData方法 -参数为麦克风采集到的数据

// 音频数据处理 function initAudioData(stream) { console.error("1"); console.error(stream); //localStream = stream; // 创建音频上下文 audioCtx = new (window.AudioContext || window.webkitAudioContext)(); // 创建音频源 -将声音输入这个对象 source = audioCtx.createMediaStreamSource(stream); // 创建音频分析节点 analyser = audioCtx.createAnalyser(); // fftSize决定了能够获取到的音频数据的数量 analyser.fftSize = 4096; // 音频源连接至analyser source.connect(analyser); // analyserNode再连接至扬声器播放--本人不需要暂时注释掉了 analyser.connect(audioCtx.destination); // 简单用定时器来绘制波形图,该文档使用requestAnimationFrame来以屏幕刷新的评率来反复执行绘制函数 //animateFrame = setInterval(drawWaver, 60); //开始绘制频谱图 var canvas = document.getElementById('canvas'), cwidth = canvas.width, cheight = canvas.height - 2, meterWidth = 10,//能量条的宽度 gap = 2,//能量条的间距 meterNum = 800 / (10 + 2);//计算当前画布上能画多少条 var ctx = canvas.getContext('2d'); var capHeight = 2,//冒头的高度 capStyle = '#fff',//冒头的颜色 capYPositionArray = [];//将上一面各个冒头的位置保存到这个数组1e9fff //定义一个渐变样式用于画图 var gradient = ctx.createLinearGradient(0, 0, 0, 300); //gradient.addColorStop(1, '#0f0'); //gradient.addColorStop(0.5, '#ff0'); //gradient.addColorStop(0, '#f00'); gradient.addColorStop(1, '#1e9fff');//低音颜色 gradient.addColorStop(0.5, '#70bbf2');//中音颜色 gradient.addColorStop(0, '#1e9fff');//高音颜色 //绘制频谱图 function drawSpectrum() { var array = new Uint8Array(analyser.frequencyBinCount); analyser.getByteFrequencyData(array); var step = Math.round(array.length / meterNum);//计算从analyser中的采样步长 //清理画布 ctx.clearRect(0, 0, cwidth, cheight); //对信源数组进行抽样遍历,画出每个频谱条 for (var i = 0; i < meterNum; i++) { var value = array[i * step]; //取样作为y轴的值 //绘制缓慢降落的冒头 if (capYPositionArray.length < Math.round(meterNum)) { capYPositionArray.push(value);//初始化保存冒头位置的数组,将第一个画面位置保存 } ctx.fillStyle = capStyle; //1.开始绘制冒头 if (value < capYPositionArray[i]) { //使用前一次数据 ctx.fillRect(i * 12, cheight - (--capYPositionArray[i]), meterWidth, capHeight); } else { //否则,直接使用当前数据并记录 ctx.fillRect(i * 12, cheight - value, meterWidth, capHeight); capYPositionArray[i] = value; } //2.开始绘制频谱条 ctx.fillStyle = gradient; ctx.fillRect(i * 12/*频谱条的宽度+条间距*/, cheight - value + capHeight, meterWidth, cheight); } //用requestAnimationFrame来以屏幕刷新的评率来反复执行绘制函数 requestAnimationFrame(drawSpectrum); } //用requestAnimationFrame来以屏幕刷新的评率来反复执行绘制函数 requestAnimationFrame(drawSpectrum); } initAudioData
完成麦克风数据获取并显示频谱
采集成功后的麦克风MeidaStream(媒体流)样式
二、控制麦克风输入音量
官方网站:BaseAudioContext.createGain()
BaseAudioContext接口的createGain()方法创建了一个GainNode,它可以用来控制音频图的整体增益(或音量)。
1、设置全局变量extraGain
// 16、定义全局变量localStream let audioCtx = null; // 音频上下文 let source = null; // 音频源 let sysStream = null; // 系统声音音频流 let micStream = null;// 录音产生的音频流 录音产生的音频流、麦克风收集到的音频数据 let localStream = null;// 录音产生的音频流 录音产生的音频流、麦克风收集到的音频数据 let extraGain = null; //麦克风控制 let analyser = null; // 用于分析音频实时数据的节点(分析器) //定义全局变量pc1 var pc1;
2、js编写控制音量方法 --参数为一个int数值
extraGain为全局变量--他的生成参考另一博客的第四点媒体流和麦克风混流方法中有生成extraGain(将其改为全局就可)
//麦克风音量控制 extraGain为全局变量 c的值为一个int值 1-100 function ctrmic(c) { if (extraGain != "") { //为空表示呼叫台开关没开,extraGain这也没有生成 extraGain.gain.setValueAtTime(c/100, audioCtx.currentTime);//目前理解设置他的音量值是0-1区间的数 } }
3、参考另一博客中绘制音量滑块代码--在滑动麦克风滑块的触发事件中调用上面控制音量的方法
呼叫台功能页面布局【canvas绘制音频频谱图】【绘制音量控制滑块】 (示例使用.net framework mvc) - じ逐梦 - 博客园 (cnblogs.com)
如图:
本文来自博客园,作者:じ逐梦,转载请注明原文链接:https://www.cnblogs.com/ZhuMeng-Chao/p/16956098.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码