README.md
1# 音频管理
2
3### 介绍
4
5本示例主要展示了音频的相关功能,使用[@ohos.multimedia.audio](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-audio-kit/js-apis-audio.md)等接口实现音频的发声设备的切换与查询、音频焦点、音效的查询与设置以及音频录制等功能
6
7### 效果预览
8
9| 主页 | 发声设备查询与选择页面 | 音频焦点页面 |
10|--------------------------------------|-----------------------------------------|------------------------------------------------------|
11| | |  |
12
13| 音效管理页面-<br>预置音效查询 | 音效管理页面-<br>实时音效设置 | 音频录制页面-<br>普通录制 | 音频录制页面-<br>并行录制 |
14|-----------------------------------------|----------------------------------------|----------------------------------------|----------------------------------------|
15|  |  |  |  |
16
17| 音频录制页面-<br>直播录制 | 音量组件页面 | 音量组件页面-<br>音量面板 | 空间音频页面 |
18|-----------------------------------------|----------------------------------------------------|---------------------------------------------------------------------|---------------------------------------------------------------------|
19| |  |  |  |
20
21| 音频k歌页面 |
22|-----------------------------------------|
23| |
24
25使用说明
26
27注意:6,7,8是连续的串行操作,不是并行的。空间音频需要在具体路径上添加pcm文件。
28
291. 弹出麦克风权限访问提示框,点击“允许”
302. 在主界面点击“发声设备查询与选择”按钮,进入发声设备查询与选择页面
313. 在发声设备查询与选择页面界面,展示当前发声设备类型名称
324. 在发声设备查询与选择页面界面,当设备存在“插入耳机”、“拔掉耳机”、“连接蓝牙”、“断开蓝牙”等操作行为时,当前发声设备类型名称会随之切换
335. 在发声设备查询与选择页面界面,点击“返回”按钮,回到主页
346. 在主界面点击“音频焦点”按钮,进入音频焦点页面
357. 在音频焦点页面,点击音乐播放器,音乐开始播放
368. 在音频焦点页面,点击铃声播放器,铃声开始播放,同时音乐被暂停
379. 在音频焦点页面,点击铃声播放器,停止铃声播放,音乐恢复播放
3810. 在音频焦点页面,点击“返回”按钮,回到主页
3911. 在主界面点击“音效管理”按钮,进入预置音效查询页面
4012. 在预置音效查询页面,选择内容类型和场景后,点击“查询”按钮,预置音效模式会显示在下方查询结果中
4113. 在预置音效查询页面,重新修改内容类型和场景,查询结果会重置
4214. 在预置音效查询页面,点击右下方”实时音效设置“按钮,进入实时音效设置页面
4315. 在实时音效设置页面,选择内容类型和场景后,点击播放按钮,音频流开始播放,同时内容类型和场景选择框被置灰
4416. 在实时音效设置页面,点击”查询“按钮,当前音频流音效模式会显示在下方的查询结果中
4517. 在实时音效设置页面,点击暂停按钮,音频流暂停,内容类型和场景选择框使能
4618. 在实时音效设置页面,修改内容类型与场景选择,查询结果被重置
4719. 在实时音效设置页面,再次点击播放按钮,音频流开始播放,点击”查询“按钮,结果显示在查询结果内
4820. 在实时音效设置页面,在”音频流音效模式设置“选择框中选择另一种与上次查询结果不同的音效模式,可以听到音频流出现变化
4921. 在实时音效设置页面,再次点击”查询“按钮,查询结果与上一步设置的模式相同
5022. 在实时音效设置页面,点击左上方返回图标,回到主页
5123. 在实时音效设置页面,点击左下方”预置音效查询“按钮,回到预置音效查询页面
5224. 在主界面点击“音频录制”,进入音频录制界面,音频录制界面默认是普通录制界面
5325. 在普通录制界面,点击录制按钮,开始录制,录音时间开始计时,5s内不允许结束
5426. 在普通录制界面,点击暂停按钮,暂停录制,录音时间也停止计时
5527. 在普通录制界面,点击继续按钮,继续录制,录音时间继续计时
5628. 在普通录制界面,点击停止录制按钮,停止录制,也可以不停止录制,应用设置了30s的超时后,自动停止录制
5729. 停止录制后,会生成录制结果,界面上有一个录制成功的音频播放器,点击播放可听到录制的音频
5830. 点击并行录制按钮,可切换到并行录制界面,点击直播录制按钮,可切换到直播录制界面
5931. 在并行录制界面中,点击音乐播放器,播放音乐
6032. 在并行录制界面中,点击录制按钮,开始录制,同时开启麦克风录制和屏幕录制,5s内不允许结束
6133. 在并行录制界面中,点击停止录制按钮,停止录制,或者超时30s会自动停止录制,停止后按钮点成不可点击状态
6234. 在并行录制界面中,录制停止后,会生成两个音频播放器,一个是麦克风的录音结果,一个是屏幕录制的结果,点击进行播放,暂停,播放结束自动停止
6335. 在直播录制界面,点击录制按钮,开始录制,录音时间开始计时,5s内不允许结束
6436. 在直播录制界面,点击暂停按钮,暂停录制,录音时间也停止计时
6537. 在直播录制界面,点击继续按钮,继续录制,录音时间继续计时
6638. 在直播录制界面,点击停止录制按钮,停止录制,也可以不停止录制,应用设置了30s的超时后,自动停止录制
6739. 停止录制后,会生成录制结果,界面上有一个录制成功的音频播放器,点击播放可听到录制的音频
6840. 点击返回按按钮回到主页
6941. 在主界面点击“音量组件”按钮,进入音量组件页面
7042. 在音量组件页面,点击“音量+”或“音量-”按钮,弹出音量面板
7143. 在音量组件页面,点击左上方返回图标,回到主页
7244. 在主界面点击“空间音频”按钮,进入空间音频页面
7345. 若本地没有音频资源,可主动push音频文件到本地媒体库路径:
74```
75hdc file send 2p0.pcm data/app/el2/100/base/com.samples.audio/haps/entry/files/
76hdc file send 5p1.pcm data/app/el2/100/base/com.samples.audio/haps/entry/files/
77```
7846. 在空间音频页面,点击“2.0音乐示例”播放器,开始播放立体声音源
7947. 在空间音频页面,当设备不支持空间音频时,“5.0音乐示例”播放器置灰
8048. 在空间音频页面,当设备支持空间音频时,“5.0音乐示例”播放器亮起,点击出现弹窗提示“请开启空间音频”
8149. 在空间音频页面,当设备支持空间音频且空间音频开关已开启时,点击“5.0音乐示例”播放器,开始播放AudioVivid音源
8250. 在空间音频页面,当设备支持空间音频且空间音频开关被打开时,出现弹窗提示“空间音频已开启”
8351. 在空间音频页面,当设备支持空间音频且空间音频开关被关闭时,出现弹窗提示“空间音频已关闭”
8452. 在主界面点击“k歌”按钮,进入k歌页面
8553. 在k歌页面,点击初始化按钮,创建AudioLoopback实例,在不支持平台会显示“平台不支持硬返”,支持平台会显示“已初始化”。
8654. 在k歌页面,点击开启返听按钮,开启耳返,在设备不支持的时候会显示“当前设备不支持”,场景不支持的时候会显示“当前场景不支持”,开启耳返成功会显示“返听中”。
8755. 在k歌页面,点击关闭耳返按钮,关闭耳返。
8856. 在k歌页面,滑动音量条,调整耳返音量。
89
90### 工程目录
91
92```
93entry/src/main/ets/
94|---pages
95|---|---Index.ets //首页
96|---|---PreferOutputDevice.ets //发声设备的查询与选择页面
97|---|---Focus.ets //音频焦点页面
98|---|---PresetEffect.ets //音效管理页面-预置音效查询
99|---|---RealtimeEffect.ets //音效管理页面-实时音效设置
100|---|---NormalCapturer.ets //音频录制-普通录制
101|---|---ParallelCapturer.ets //音频录制-并行录制
102|---|---LiveCapturer.ets //音频录制-直播录制
103|---|---VolumePanel.ets //音量组件页面
104|---|---SpatialAudio.ets //空间音频页面
105|---|---Karaoke.ets //k歌页面
106library/
107|---Logger.ts //日志打印封装
108```
109
110### 具体实现
111
112* 发声设备查询与切换功能都封装在PreferOutputDevice,源码参考:[PreferOutputDevice.ets](entry/src/main/ets/pages/PreferOutputDevice.ets)
113 * 使用audioRenderer对象来播放一个通话类型的音频,只要进入发声设备查询与选择页面就进行播放,直到退出当前页面
114 * 使用audio.getAudioManager()来获取音频管理对象audioManager,再通过audioManager.getRoutingManager()对象获取audioRoutingManager对象
115 * 使用audioRoutingManager.getPreferOutputDeviceForRendererInfo()获取当前发声设备
116 * 使用audioRoutingManager.on('deviceChange',audio.DeviceFlag.OUTPUT_DEVICES_FLAG)来监听设备上下线
117 * 当收到监听消息后,重新调用audioRoutingManager.getPreferOutputDeviceForRendererInfo()接口来查询当前发声设备
118* 音频焦点功能都封装Focus,源码参考:[Focus.ets](entry/src/main/ets/pages/Focus.ets)
119 * 使用audio.createAudioRenderer()接口分别创建音乐类型和铃声类型的audioRenderer对象
120 * 对每个render对象都调用audioRenderer.setInterruptMode(audio.InterruptMode.INDEPENDENT_MODE),完成独立焦点的设置
121 * 对每个render对象都监听audioRenderer.on('audioInterrupt'),收到回调时,说明当前renderer对象被暂停或者恢复播放,据此更新UI状态,如果是恢复,则需要再次调用audioRenderer.start()和wirte()进行恢复播放
122 * 对每个render对象都监听audioRenderer.on('stateChange'),收到回调时,说明当前renderer对象的状态被改变,据此更新UI状态
123 * 使用audioRenderer.start()方法和audioRenderer.write()进行音频的播放处理,写入字节的长度由audioRenderer.getBufferSize()接口来决定
124 * 使用audioRenderer.stop()进行音频的停止播放处理
125 * 使用resourceManager.getRawFd()接口加载工程里面的resources\rawfile下面的音频文件资源获取对应的文件描述对象fileDescriptor,接口参考:[@ohos.resourceManager](https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/reference/apis/js-apis-resource-manager.md)
126 * 根据文件描述对象,使用fs.read()接口进行音频数据读取,读取到的结果用于audioRenderer.write()的写入,接口参考:[@ohos.file.fs](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-core-file-kit/js-apis-file-fs.md)
127
128* 预置音效查询功能都封装在PresetEffect, 源码参考:[PresetEffect.ets](entry/src/main/ets/pages/PresetEffect.ets)
129 * 在选择框中的类型和场景映射为数字后, 作为之后调用的getAudioEffectInfoArray(content type:number, stream usage:number)的两个入参
130 * 点击”查询“按钮后, 使用audio.getAudioManager()获取音频管理对象audioManager, 再通过audioManager.getStreamManager()对象获取audioStreamManager
131 * 使用audioStreamManager.getAudioEffectInfoArray()获取当前的预置音效模式, api返回数字, 映射后显示在查询结果一栏
132* 实时音效设置功能都封装在RealtimeEffect, 源码参考:[RealtimeEffect.ets](entry/src/main/ets/pages/RealtimeEffect.ets)
133 * 点击播放调用createAudioRenderer(audioRendererOptions),其中的audioRendererOptions使用了在选择框中的类型和场景映射成的数字
134 * 使用audioRenderer.start()方法和audioRenderer.write()进行音频的播放处理, 写入字节的长度由audioRenderer.getBufferSize()接口来决定
135 * 使用resourceManager.getRawFd()接口加载工程里面的resources\rawfile下面的音频文件资源获取对应的文件描述对象fileDescriptor
136 * 使用audioRenderer.pause()方法暂停音频流, 使用audioRenderer.stop()和audioRenderer.release()方法释放当前audioRenderer
137 * 点击查询按钮, 调用audioRenderer.getAudioEffectMode()方法查询当前音频流的音效模式, 显示在查询结果内
138 * 点击”音频流音效模式设置“选项, 调用audioRenderer.setAudioEffectMode()方法,设置要用的音效模式
139 * 通过三个选择框的更新, audioRenderer的state和播放按钮状态的监视, 来触发UI状态的更新
140 * 调用组件的.enabled(enabled: boolean)方法控制其置灰与使能
141
142* 音频录制-普通录制功能都封装在NormalCapturer,源码参考:[NormalCapturer.ets](entry/src/main/ets/pages/NormalCapturer.ets)
143 * 创建一个麦克风源的capturer对象用于录音
144 * 点击开始录制时,调用capturer对象的start方法,同时调用capturer的read读取录音数据,并通过使用fs.write接口将录音数据写入到文件中去存储起来,接口参考:[@ohos.file.fs](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-core-file-kit/js-apis-file-fs.md),同时利用setTimeout开启一个计时器,记录录音时间。
145 * 点击暂停,调用capturer.stop(),同时文件写入也停止
146 * 点击继续,再次调用capturer.start(),capturer.read()以及继续将录音数据写入到文件中去
147 * 点击停止,调用capturer.stop(),同时文件写入也停止,录音结果生成成功,然后创建一个audioRenderer对象用于播放录音结果
148 * 点击音频播放器,调用fs.read()读取数据,并将录音数据调用audioRenderer.wirte写入,进行播放
149 * 再点击可以调用audioRenderer.pause()可以暂停音频播放,文件读取结束后自动调用audioRenderer.stop()停止音频播放
150 * 退出音频录制,会调用caturer.ralease(),audioRenderer.release()释放资源和fs.close()关闭文件
151* 音频录制-并行录制功能都封装在ParallelCapturer,源码参考:[ParallelCapturer.ets](entry/src/main/ets/pages/ParallelCapturer.ets)
152 * 调用audio.createAudioRenderer(options)创建audioRendererMusic,options参数中privacyType设为0,renderInfo设为音乐类型,播放的音频流方可被屏幕录制录到
153 * 调用audioRendererMusic.start(),pause(),stop()以及fs.read()等接口进行音乐的播放,暂停,停止操作
154 * 分别利用audio.createAudioCapturer()创建一个麦克风源的audioCapturerNormal对象和一个屏幕录制源的audioCapturerScreen对象
155 * 点击开始录制,则相继调用audioCapturerNormal.start(),audioCapturerScreen.start(),同时利用setTimeout开始计时,且还要分别调用audioCapturerNormal.read(),audioCapturerScreen.read(),以及调用fs.write将录音数据写入不同的文件
156 * 点击停止录制,则相继调用audioCapturerNormal.stop(),audioCapturerScreen.stop(),同时利用clearInterval清除计时器,从而停止计时,同时也创建两个audiorenderer对象分别用于播放录音数据
157 * 接下来就是分别调用两个audioRenderer对象的start,pause,stop以及fs.read等接口进行录音数据的播放,暂停,停止这些操作
158* 音频录制-直播录制功能都封装在LiveCapturer,源码参考:[LiveCapturer.ets](entry/src/main/ets/pages/LiveCapturer.ets)
159 * 先判断当前平台SOURCE_TYPE_LIVE是否支持回声消除,如果不支持,建议应用创建一个麦克风源的capturer对象用于录音并自己实现回声消除。如果支持则直接创建一个直播类型的capturer对象用于录音
160 * 点击开始录制时,调用capturer对象的start方法,同时调用capturer的read读取录音数据,并通过使用fs.write接口将录音数据写入到文件中去存储起来,接口参考:[@ohos.file.fs](https://docs.openharmony.cn/pages/v5.1/zh-cn/application-dev/reference/apis-core-file-kit/js-apis-file-fs.md),同时利用setTimeout开启一个计时器,记录录音时间。
161 * 点击暂停,调用capturer.stop(),同时文件写入也停止
162 * 点击继续,再次调用capturer.start(),capturer.read()以及继续将录音数据写入到文件中去
163 * 点击停止,调用capturer.stop(),同时文件写入也停止,录音结果生成成功,然后创建一个audioRenderer对象用于播放录音结果
164 * 点击音频播放器,调用fs.read()读取数据,并将录音数据调用audioRenderer.wirte写入,进行播放
165 * 再点击可以调用audioRenderer.pause()可以暂停音频播放,文件读取结束后自动调用audioRenderer.stop()停止音频播放
166 * 退出音频录制,会调用caturer.ralease(),audioRenderer.release()释放资源和fs.close()关闭文件
167* 音量组件功能都封装在VolumePanel,源码参考:[VolumePanel.ets](entry/src/main/ets/pages/VolumePanel.ets)
168 * 调用AVVolumePanel组件创建音量面板,其中参数volumeLevel属于number类型,用于设置设备音量;参数volumeParameter属于AVVolumePanelParameter类型,用于设置音量面板的自定义参数
169 * 点击”音量+”或”音量-”按钮,会传入不同的volumeLevel,从而弹出音量面板
170* 空间音频功能都封装在SpatialAudio,源码参考:[SpatialAudio.ets](entry/src/main/ets/pages/SpatialAudio.ets)
171 * 调用audioRoutingManager.getPreferredOutputDeviceForRendererInfoSync(rendererInfo)获取当前发声设备
172 * 使用audioDeviceDescriptor.SpatializationSupported属性获取设备是否支持空间音频,不支持时“5.0音乐播放示例”将被置灰
173 * 调用isSpatializationEnabledForCurrentDevice()接口查询当前发声设备空间音频开关状态
174 * 调用on("spatializationEnabledChangeForCurrentDevice")接口订阅当前发声设备空间音频空间音频开关状态变化事件
175 * 调用off("spatializationEnabledChangeForCurrentDevice")接口取消订阅当前发声设备空间音频空间音频开关状态变化事件
176* k歌功能都封装在Karaoke,源码参考:[Karaoke.ets](entry/src/main/ets/pages/Karaoke.ets)
177 * 调用audio.getAudioManager().getStreamManager().isAudioLoopbackSupported(mode)查询当前平台是否支持返听能力。
178 * 调用audio.createAudioLoopback(mode)创建AudioLoopback实例。
179 * 调用getStatus方法,查询当前返听状态。
180 * 调用setVolume方法,设置音频返听音量。
181 * 调用enable方法,启用或禁用音频返听功能。
182 * 调用on("statusChange")接口订阅当前返听状态变化事件
183 * 调用off("statusChange")接口取消订阅返听状态变化事件
184### 相关权限
185
186音频录制涉及的权限包括:
187
1881.允许应用使用麦克风:[ohos.permission.MICROPHONE](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissionmicrophone)
189
190空间音频涉及的权限包括:
191
1921.允许应用使用蓝牙:[ohos.permission.BLUETOOTH](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissionuse_bluetooth)
193
194### 依赖
195
196不涉及。
197
198### 约束与限制
199
2001. 本示例仅支持标准系统上运行,支持设备:RK3568;
2012. 本示例仅支持API20版本SDK,SDK版本号(API Version 20 Release),镜像版本号(6.0Release);
2023. 本示例需要使用DevEco Studio 版本号(5.0Release)才可编译运行;
203
204### 下载
205
206如需单独下载本工程,执行如下命令:
207
208```
209git init
210git config core.sparsecheckout true
211echo code/BasicFeature/Media/Audio > .git/info/sparse-checkout
212git remote add origin https://gitee.com/openharmony/applications_app_samples.git
213git pull origin master
214```