亚马逊AWS官方博客

利用Graviton2配置虚拟声卡实时处理音频

随着技术的进步,当今互联网内容中音视频内容日益增长,随之而来的挑战就是对音视频的处理。不仅互联网企业,传统企业的语音呼叫中心很多也迁移到了云上,并且利用人工智能技术做语音应答。这样就对云上主机的声音处理有了要求,比如在云端实时变更声道、采样率,实时混音,实时录音等。

Graviton2处理声音的优势

由于Linux下的音频框架繁多,中文资料相对较少,所以很多公司还在使用windows下的Virtual Audio Cable (VAC)做虚拟声卡,即一个Loopback设备,来处理应用与应用,应用与设备间的虚拟连接。Virtual Audio Cable (VAC)是一个商业软件,本身需要购买授权。另外,可以运行windows实例的价格也要略高。从成本角度考虑,相同配置的Graviton2一样可以胜任音频处理任务,实例价格至少会低20%。并且Linux上的音频框架都是开源,不需要授权费用。下面我将介绍如何使用Linux下的音频框架Advanced Linux Sound Architecture (ALSA)和PulseAudio来替代windows下的Virtual Audio Cable (VAC)。

创建Loopback设备(虚拟声卡)

由于EC2实例并没有配置声卡,所以我们需要创建Loopback设备(虚拟声卡)。但由于亚马逊云科技的Ubuntu AMI的内核是优化过的,去掉了audio loopback部分,所以我们要先替换回Ubuntu通用内核。

先用Ubuntu Server 20.04 LTS ARM版AMI创建一个EC2实例,然后运行查看内核的命令,得到如下结果:

$ uname -r

5.4.0-1029-aws

我们可以看到,当前内核是亚马逊云优化过的aws内核,我们需要更换为generic内核。执行下面2条命令,安装generic内核。其中内核版本可能和您选择的系统版本不同有所变化,请以实际为准。

$ sudo apt update

$ sudo apt install linux-modules-extra-5.4.0-88-generic

使用下面命令,得到要删除内核的信息:

$ sudo dpkg -l|egrep linux-image-.*-aws|awk '{print $2}'

linux-image-5.4.0-1029-aws

使用apt命令删除刚才得到的package,期间会提示是否取消删除内核,选择No:

$ sudo apt autoremove linux-image-aws

$ sudo apt autoremove linux-image-5.4.0-1029-aws

重启实例,再次查看内核版本,已经变成通用内核:

$ uname -r

5.4.0-88-generic

安装ALSA工具集,并加载snd_aloop内核模块,加载完成后,查看loopback设备。

$ sudo apt install alsa-utils

$ sudo modprobe snd_aloop

$ aplay -l

**** List of PLAYBACK Hardware Devices ****

card 0: Loopback [Loopback], device 0: Loopback PCM [Loopback PCM]

  Subdevices: 8/8

  Subdevice #0: subdevice #0

  Subdevice #1: subdevice #1

  Subdevice #2: subdevice #2

  Subdevice #3: subdevice #3

  Subdevice #4: subdevice #4

  Subdevice #5: subdevice #5

  Subdevice #6: subdevice #6

  Subdevice #7: subdevice #7

card 0: Loopback [Loopback], device 1: Loopback PCM [Loopback PCM]

  Subdevices: 8/8

  Subdevice #0: subdevice #0

  Subdevice #1: subdevice #1

  Subdevice #2: subdevice #2

  Subdevice #3: subdevice #3

  Subdevice #4: subdevice #4

  Subdevice #5: subdevice #5

  Subdevice #6: subdevice #6

  Subdevice #7: subdevice #7

如上面显示,audio loopback设备已经正常创建,如果需要每次启动自动加载,我们还需要在/etc/modules文件内写入内核模块的名字,直接新起一行键入snd_aloop,保存文件即可。下面来测试下loopback设备,我们看到loopback设备是card0,card0下面又有device0和device1,每个device下面又有8个子设备。每个子设备可以表示为 hw:card,device,suddevice,举例说明,card0的device0的subdevice #5可以写为hw:0,0,5。当声音从一个device0的某个子设备输入,那么就一定会从device1的相同编号的子设备输出。

下面实验下loopback子设备使用,我们使用arecord在card0,device1,subdevice #2上进行录音,其中指定格式为S16_LE,采样率48000,声道为2,注意,声音输入输出的格式采样率声道需匹配:

$ arecord -D hw:0,1,2 -f S16_LE -c 2 -r 48000 recorded.wav

打开一个新终端,使用aplay命令在card0,device0,subdevice #2播放一段音频,其中指定采样率48000,声道为2:

$ aplay -D hw:0,0,2 -c 2 -r 48000 test1.wav

播放完成后,使用Ctrl+C终止arecord录制,播放recorded.wav,验证录音成功。

使用ALSA插件

ALSA 正常工作不需要使用 .asoundrc 和 asound.conf 配置文件。 大多数应用程序可以在没有它们的情况下工作。 这些文件用于通过 alsa-lib 层实现额外的功能,例如路由和采样率转换。 大多数应用程序可以在没有这些用户自定义配置文件的情况下工作。通常 alsa-lib 的默认安装提供了一个足够强大的设置,包括分层配置文件(它总是使用标准的 .asoundrc 格式语法),它们特别能够支持某些声卡品牌,也包含了Loopback虚拟声卡。

当我们需要使用ALSA做做一些复杂的事情,比如将多个设备组合成一个设备混音输出等,就需要用到ALSA的插件,文档可以参考官网:https://alsa.opensrc.org/ALSA_plugins 下面,我将简单介绍插件的配置方法以及几个非常常用的插件。前面已经提到,ALSA的配置使用文件,有三个地方可以对ALSA进行配置,第一个是用户目录,$HOME/.asoundrc ,这个配置文件的影响范围仅为用户本身。第二个是/usr/share/alsa/alsa.conf ,这是原始配置文件,建议不要修改。第三个是/etc/asound.conf,这是全局配置文件,对所有用户生效。

Loopback虚拟声卡是单工设备,而且一次仅可以连接一个声音程序。很多客户的需求是,可以多个声音程序同时输入,输入的同时完成混音,并且在输出端,可以有多个设备同时获取声音。如果要完成上面的功能,我们需要使用4个ALSA插件:

1、 dmix 插件提供了多个流的直接混合。 允许在通道、文件和声卡设备之间进行低级样本转换和复制。

2、dsnoop 相当于 dmix 插件,但用于录制声音。 dsnoop 插件允许多个应用程序同时从同一设备录制。

3、asym 是一种 ALSA PCM 插件,它将 dsnoop 和 dmix 等半双工 PCM 插件组合成一个全双工设备。

4、plug负责各种样本转换、通道之间的样本复制等,可以自动调整输入的音频。

把下面代码复制到用户的home目录下的.asoundrc文件中:

pcm.dmixed {

       ipc_key 1025

       type dmix

       slave.pcm "hw:0,0,1"

   }

 

pcm.dsnooped {

       ipc_key 1027

       type dsnoop

       slave.pcm "hw:0,1,1"

   }

 

pcm.asymed {

       type asym

       playback.pcm "dmixed"

       capture.pcm "dsnooped"

   }

 

pcm.!default {

       type plug

       slave.pcm "asymed"

   }

使用arecord命令,对default设备进行录音:

$ arecord -D default -f S16_LE -c 2 -r 48000 recorded.wav

再打开2个终端,分别向default设备输出2段不一样的声音test1.wav和test2.wav:

$ aplay -D default -c 2 -r 48000 test1.wav

$ aplay -D default -c 2 -r 48000 test2.wav

最终我们得到的是test1.wav和test2.wav混音的结果。

配置pulseaudio

我们刚才使用的是ALSA工具aplay和arecord对ALSA设备进行输入和输出,但实际很多应用并不能直接支持ALSA,需要通过pulseaudio将这些声音流传给ALSA。在/etc/pulse/default.pa中添加load-module module-alsa-sink device=default,这样ALSA中的默认设备就添加到pulseaudio中做输入设备。

结论

通过上面的介绍,我们可以看到,Linux中的音频处理功能也非常强大,而且,运行在Graviton2上的Linux相比windows音频处理方案性价比更高。关键在Linux中使用各种开源音频框架,可以做一些定制化的修改,这是相对商业软件来说不可比拟的优势。

本篇作者

夏焱

亚马逊云科技解决方案架构师,目前专注于容器化解决方案。在加入AWS之前,曾就职于惠普、IBM等科技公司,从事数据中心基础架构相关工作,拥有十余年技术服务经验。