在纯音频连麦的过程中,我们经常有这种需求,展示当前是谁在发言,比如当某人说话时就在他的麦克风图标上做高亮处理。为了实现这种需求,我们就需要实时地去获取一个媒体流中正在播放的音频数据。在我们的场景中,这种设计可能显得有些多余,但我们仅仅是为了演示这个功能,所以就来绘制一个实时的声波图吧。

在绘制之前,我想先介绍一下我们 SDK 提供的和音频回调相关的 API,它们分别是:

getCurrentTimeDomainData 获取当前音频的时域数据

getCurrentFrequencyData 获取当前音频的频域数据

onAudioBuffer 获取音频 PCM 数据

这 3 个方法的详细说明可以参见 stream 对象。这里我们主要讨论这 3 种音频采集方法的区别,以及在什么情况下使用哪种方法。

我们知道,音频数据是根据采样率的大小在一个数组里按时间顺序填充的采样数据,播放音频时,也会时序地将这个数组中的数据按批次取出并送入声卡中,声卡中正在处理的那一批音频数据,就是我们在那一刻听到的声音。所以这里的第一个方法 getCurrentTimeDomainData,就是实时地去获取当前正在处理的音频数据(实际上这并不是声卡当前正在处理的数据,只是尽量精确的一个离当前播放 buffer 最近的范围为 2048 长度的音频)。不过这里要注意,我们不能通过不断地调用这个方法来收集音频的原始数据,这个方法仅用于一些实时的音频分析和处理(比如我们绘制声波图),如果想要收集音频的原始数据,使用我们的第三个方法 onAudioBuffer,这个函数的返回不能保证实时性,但是会根据播放的进度不断地将之前用于播放的音频数据回调回来。好了,这样我们还剩下最后一个方法没有介绍,其实很简单,第二个方法 getCurrentFrequencyData 就是将当前的时序音频数据做了一次 STFT 变换得到的频域数据,一般可用用来绘制频谱图,或者用来判断某个频段是否有声音(是否有人说话)。

介绍完了我们 SDK 提供的方法,回到我们的场景,这里需要用到的其实就是获取当前的时域数据(getCurrentTimeDomainData) 这个方法。下面看代码吧,首先在 room.html 里创建 2 个 canvas 对象用于绘制我们的声波图。

...

...

在 room.css 中添加相应的 css,注意这里我们固定了 canvas 的宽高,因为 canvas 跟随窗口动态宽高太过复杂,这里就不赘述了。

/* css/room.css */

canvas {

position: absolute;

top: 0;

left: 0;

}

有了 canvas 之后,就可以开始绘制了,绘制的过程设计到本地音频的绘制和远端音频的绘制,所以我们还是先将绘制操作抽成一个公共的函数,在 room.js 一开始加入如下代码。

// js/room.js

// 绘制声波图,stream 为需要实时绘制的媒体流对象

// ctx 为 canvas 的 context 对象,用来区分画在哪个 canvas 上

function drawAudioWave(stream, ctx) {

// 如果没有流或者流被释放了(远端取消发布等情况)就直接返回

if (!stream || stream.isDestoryed) {

return;

}

// 获取当前实时的时域数据

const timeData = stream.getCurrentTimeDomainData();

// 以下为 canvas 相关的绘制代码

const width = ctx.canvas.width;

const height = ctx.canvas.height;

ctx.fillStyle = "#000";

ctx.strokeStyle = "#fff";

ctx.lineWidth = 2;

ctx.fillRect(0, 0, width, height);

ctx.beginPath();

for (let i = 0; i < width; i += 1) {

const dataIndex = Math.round(i * (timeData.length / width));

const data = Math.round(timeData[dataIndex] * (height / 255.0));

if (i === 0) {

ctx.moveTo(i, data);

} else {

ctx.lineTo(i, data);

}

}

ctx.stroke();

// 调用 requestAnimationFrame 逐帧更新

requestAnimationFrame(() => drawAudioWave(stream, ctx));

}

有了绘制函数,接下来就在相应的地方调用它吧

// js/room.js

function subscribeUser(myRTC, user) {

if (!user.published) {

return;

}

myRTC.subscribe(user.userId).then(remoteStream => {

const remotePlayer = document.getElementById('remoteplayer');

remoteStream.play(remotePlayer);

// 修改订阅函数,如果订阅的目标流没有开启视频(纯音频)

// 就绘制声波图

if (!remoteStream.enableVideo) {

const ctx = document.getElementById('remotewave').getContext('2d');

drawAudioWave(remoteStream, ctx);

}

}).catch(e => {

console.log('subscribe error!', e);

});

}

...

...

const localPlayer = document.getElementById('localplayer');

localStream.play(localPlayer, true);

await myRTC.publish(localStream);

// 如果本地发布的流没有开启视频采集

// 就绘制本地的声波图

if (!enableVideo) {

const ctx = document.getElementById('localwave').getContext('2d');

drawAudioWave(localStream, ctx);

}

...

...

好了,现在再使用纯音频连麦进入的话,就可以看到自己和远端的声波图啦。这里是用了最简单的方法绘制的声波图,仅仅展示 API 用,使用频域和一些算法搭配绘制会有更好的效果,这里就不赘述了。

php 声波图,绘制声波图(获取音频回调)相关推荐

  1. 【安卓R 源码】获取音频焦点和释放音频焦点

    一. 获取焦点流程 1. 电话焦点只有系统可以申请,如果是电话焦点,系统会把所有多媒体和游戏的音频流实例全部mute.同理电话焦点释放会解除mute操作 2. 系统管理的焦点栈有大小限制限制为100. ...

  2. 获取音频的时域频谱-振幅图-音频可视化-音量图-音谱图

    找了很久的资料,基本都是音频的实时频谱图,即通过MediaPlayer-Visualizer-onWaveFormDataCapture.onFftDataCapture获取数据,然后解析.绘制出来的 ...

  3. WebRTC本地音频回调、选用音频采集设备及自定义输入音频

    由于工作需要,开始研究WebRTC源码,现将如何把本地音频回调出来分享一下. 如果要使用Native WebRTC封装SDK,就要把RTC的一些基础能力暴露出来,本地视频.远端音视频都可以在相应的tr ...

  4. html javascript 音频、视频、 mp3 、mp4 的播放、暂停、重新播放、获取音频时长、视频自动全屏播放

    html javascript 音频.视频. mp3 .mp4 的播放.暂停.重新播放.获取音频时长 视频 https://www.bilibili.com/video/BV1WE411o7Ft?fr ...

  5. android获取小程序音频时长,最新微信小程序获取音频时长与实时获取播放进度...

    #微信小程序获取音频时长与实时获取播放进度 在小程序官方文档中 audio 注意:1.6.0 版本开始,该组件不再维护.建议使用能力更强的 wx.createInnerAudioContext 接口 ...

  6. php获取音频的时长,PHP编程获取音频文件时长的方法【基于getid3类】

    本文实例讲述了PHP编程获取音频文件时长的方法.分享给大家供大家参考,具体如下: 问题: 昨天在新增论坛功能的时候,移动端显示音频文件需要知道是多长的音频: 具体解决方案如下: 首先就是数据库中增加保 ...

  7. java 获取音频文件时长

    需要导入jar包:jave 1.0.2 jar 如果是maven项目,在pom.xml文件中添加: <dependency><groupId>it.sauronsoftware ...

  8. java获取音频_java获取音频文件播放时长

    方法一: 在项目开发过程中,需要获取音视频文件时长.查询资料后发现 JAVE能够完美得到想要的结果,JAVE项目简介如下: The JAVE (Java Audio Video Encoder) li ...

  9. 最新微信小程序获取音频时长与实时获取播放进度

    #微信小程序获取音频时长与实时获取播放进度 在小程序官方文档中 audio 注意:1.6.0 版本开始,该组件不再维护.建议使用能力更强的 wx.createInnerAudioContext 接口 ...

最新文章

  1. 消息幂等(去重)通用解决方案
  2. java applet 输出多行_java学习笔记-输入输出、Applet和多线程开发
  3. Advanced Installer 9.8打包实录
  4. 微信小程序开发-微信登陆流程
  5. 【hortonworks/registry】创建嵌套结构的scheam和带空值的schema
  6. nginx离线安装_做一个属于自己的离线下载服务器原来这么简单
  7. 记录——《C Primer Plus (第五版)》第十一章编程练习第三题
  8. Pytorch——计算机视觉工具包:torchvision
  9. 信息系统集成将成为IT行业的主流的主要原因
  10. 教你不要光驱一样重装系统
  11. ug建模教程ug建模怎么学ug10.0编程教程入门ug建模实例
  12. 移动通信网络规划:多址技术
  13. 惠普暗影精灵u盘启动linux,暗影精灵5 安装w10+ Ubuntu18.0.4
  14. java md5加密长度_java中使用MD5加密算法进行加密
  15. 华为鸿蒙开发者公测报名,华为发布鸿蒙2.0手机开发者测试版!华为老手机可申请公测...
  16. 【信息安全】RSA非对称加密算法原理(详解和C++代码实现)
  17. 【Java面试题】List如何一边遍历,一边删除?
  18. windows从零搭建hugo博客
  19. js字符串截取函数的三种方式(slice()、substring()、substr())
  20. 如何在线将CAD转成PDF格式

热门文章

  1. Res-Net(Pytorch)
  2. WebStorm中关于出现windows 找不到文件chrome,请确定文件名是否正确后,再试一次问题的解决方法
  3. 【HTML——奇幻彩色粒子】(效果+代码)
  4. BWT901BLECL5.0连接Ubuntu
  5. dbeaver快速找表
  6. linux 4412 adc字符设备,迅为4412开发板Linux字符设备控制(二)
  7. 视频制作软件——会声会影的使用心得
  8. 台式计算计算机怎么分区,新攒的电脑怎样分区|新攒的台式机分区方法
  9. 成在规划,赢在执行 ——项目管理思维与技能精要
  10. vs编译freeswitch 的mod_sofia库。