当前位置: 首页 > news >正文

做游戏网站需求确认大庆网络推广

做游戏网站需求确认,大庆网络推广,导航类网站模板,做百度推广网站得多少钱关键词:audio、音频录制、音频播放、权限申请、文件管理 在app的开发过程中时常会遇见一些需要播放一段音频或进行语音录制的场景,那么本期将介绍如何利用鸿蒙 audio 模块实现音频写入和播放的功能。本次依赖的是 ohos.multimedia.audio 音频管理模块&am…

关键词:audio、音频录制、音频播放、权限申请、文件管理

在app的开发过程中时常会遇见一些需要播放一段音频或进行语音录制的场景,那么本期将介绍如何利用鸿蒙 audio 模块实现音频写入和播放的功能。本次依赖的是 ohos.multimedia.audio 音频管理模块,核心逻辑为利用 AudioCapturer  创建音频采集器收集音频并写入文件至沙箱,利用 AudioRenderer 播放沙箱中写入的音频文件,确定目标那么开始。

本期文章的完整demo代码已经提交至Gitee:https://gitee.com/luvi/sound-recording

1. 添加权限

需要录音,必不可少的是麦克风权限,需要在 module.json5 中添加 ohos.permission.MICROPHONE 权限。

2. 引导用户授权

在第一步添加完麦克风权限后,app开启后并不能直接使用该权限,用户需要手动确认麦克风权限的开启,在用户手动确认后,麦克风权限则开始在当前app生效。

所以,在代码中我们需要进行访问权限控制弹窗的拉起操作,在这里使用 requestPermissionsFromUser 即可。需要注意的是,若用户拒绝权限后,下次需要引导用户前往设置页手动打开该权限,此处就不做过多逻辑处理,默认用户会同意该权限。

// 此处需要导入权限控制模块
import { abilityAccessCtrl, Permissions,PermissionRequestResult } from '@kit.AbilityKit';let permissionList: Permissions[] = ["ohos.permission.MICROPHONE"]
// 获取访问控制模块对象
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
let context: Context = getContext(this) as common.UIAbilityContext;
atManager.requestPermissionsFromUser(context, permissionList, (err: BusinessError, data: PermissionRequestResult) => {if (err) {console.error(`luvi > requestPermissionsFromUser fail, err->${JSON.stringify(err)}`);} else {// 权限获取成功console.info('luvi > data:' + JSON.stringify(data));}
});

3. 创建 AudioCapturer 音频采集器,准备录音

在第2部授权操作完成后才可进行 AudioCapturer 音频采集器的创建,不然没有权限是会报系统异常的错误。

// 此audioCapturer是写在struct中,自行修改位置
audioCapturer: audio.AudioCapturer | null = null...let audioCapturerOptions: audio.AudioCapturerOptions = {// 音频流信息streamInfo: {samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,channels: audio.AudioChannel.CHANNEL_2,sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW},// 采集器信息capturerInfo: {source: audio.SourceType.SOURCE_TYPE_MIC,capturerFlags: 0}
}// 创建音频采集器
audio.createAudioCapturer(audioCapturerOptions, (err, data) => {if (err) {console.error(`luvi > AudioCapturer Created : Error: ${err}`);} else {console.info('luvi > AudioCapturer Created : Success.');// 音频采集器对象this.audioCapturer = data;}
});

4. 开始录音

在第3步的操作后,我们已经拿到了 audioCapturer 对象,后续需要通过该对象进行音频录制与取消。

在录音过程中,需要不断的写入声音数据到文件中,所以我们需要订阅音频数据读入回调事件 后触发 start 操作开始录音,在文件数据写入前需要增加 fs.OpenMode.READ_WRITE 权限。此处需要注意的是 MyVoice.wav 文件本身并不存在与沙箱文件中,但是我们使用文件管理的 open 方法配置 fs.OpenMode.CREATE 权限则会自动创建出该文件。

// 导入文件管理模块
import { fileIo as fs, ReadOptions } from '@kit.CoreFileKit';...// struct中
destFile: fs.File | null = null...Button("开始采集语音").onClick(() => {let path = getContext().getApplicationContext().filesDir;let bufferSize: number = 0;let filePath = path + '/MyVoice.wav';this.destFile = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.READ_ONLY | fs.OpenMode.CREATE | fs.OpenMode.TRUNC);let readDataCallback = (buffer: ArrayBuffer) => {let options: ReadOptions = {offset: bufferSize,length: buffer.byteLength}fs.writeSync(this.destFile?.fd, buffer, options);bufferSize += buffer.byteLength;}this.audioCapturer?.on('readData', readDataCallback);this.audioCapturer?.start((err: BusinessError) => {if (err) {console.error('luvi > Capturer start failed.');} else {console.info('luvi > Capturer start success.');}});
})

5. 结束录音

录音结束后关闭文件操作,避免资源占用。

Button("结束采集音频").onClick(() => {this.audioCapturer?.stop((err: BusinessError) => {if (err) {console.error('luvi > Capturer stop failed');} else {console.info('luvi > Capturer stopped.');}});fs.close(this.destFile)
})

此时录制的音频已经保存至了沙箱中。

6. 创建音频渲染器

audioRenderer 是写在 struct 中,需要保存音频渲染器对象供后续使用。

// 此audioRenderer是写在struct中,自行修改位置
audioRenderer: audio.AudioRenderer| null = null...
let audioRendererOptions: audio.AudioRendererOptions = {streamInfo: {samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, // 采样率channels: audio.AudioChannel.CHANNEL_2, // 通道sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // 采样格式encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // 编码格式},rendererInfo: {content: audio.ContentType.CONTENT_TYPE_MUSIC, // 媒体类型usage: audio.StreamUsage.STREAM_USAGE_MEDIA, // 音频流使用类型rendererFlags: 0 // 音频渲染器标志}
}audio.createAudioRenderer(audioRendererOptions, (err, renderer) => { // 创建AudioRenderer实例if (!err) {console.info(`luvi > creating AudioRenderer success`);// 音频渲染器对象this.audioRenderer = renderer;} else {console.info(`luvi > creating AudioRenderer failed, error: ${err.message}`);}
});

7.播放音频

播放第5步保存的音频文件,需要使用音频渲染器对象,创建的渲染器本身无音频对象,所以需要在启动音频渲染器后,不断地在音频渲染器中写入音频文件的缓冲数据,从而达到播放效果,当播放完毕后关闭文件和渲染器。

Button("播放音频采集结果").onClick(async () => {if (!this.audioRenderer){return}let stateGroup = [audio.AudioState.STATE_PREPARED, audio.AudioState.STATE_PAUSED, audio.AudioState.STATE_STOPPED];if (stateGroup.indexOf(this.audioRenderer.state) === -1) { // 当且仅当状态为prepared、paused和stopped之一时才能启动渲染console.error('luvi > start failed');return;}await this.audioRenderer.start(); // 启动渲染const bufferSize = await this.audioRenderer.getBufferSize();let context = getContext(this).getApplicationContext();let path = context.filesDir;const filePath = path + '/MyVoice.wav'; // 使用沙箱路径获取文件,实际路径为/data/storage/el2/base/haps/entry/files/test.wavlet file = fs.openSync(filePath, fs.OpenMode.READ_ONLY);let stat = await fs.stat(filePath);let buf = new ArrayBuffer(bufferSize);let len = stat.size % bufferSize === 0 ? Math.floor(stat.size / bufferSize) : Math.floor(stat.size / bufferSize + 1);for (let i = 0; i < len; i++) {let options: ReadOptions = {offset: i * bufferSize,length: bufferSize};let readsize = await fs.read(file.fd, buf, options);// buf是要写入缓冲区的音频数据,在调用AudioRenderer.write()方法前可以进行音频数据的预处理,实现个性化的音频播放功能,AudioRenderer会读出写入缓冲区的音频数据进行渲染let writeSize: number = await new Promise((resolve, reject) => {this.audioRenderer?.write(buf, (err, writeSize) => {if (err) {reject(err);} else {resolve(writeSize);}});});if (this.audioRenderer.state === audio.AudioState.STATE_RELEASED) { // 如果渲染器状态为released,停止渲染fs.close(file);await this.audioRenderer.stop();}if (this.audioRenderer.state === audio.AudioState.STATE_RUNNING) {if (i === len - 1) { // 如果音频文件已经被读取完,停止渲染fs.close(file);await this.audioRenderer.stop();}}}
})

此时,我们就已经完成了音频录制与播放的一整套功能,若在开发中遇到问题可连接设备点击 IDE 右下角的 Device File Browser 文件浏览器,查看音频文件写入是否正确,还有最重要的就算别忘记添加权限。

完整代码已经提交至了Gitee中,可回顶部查看。

http://www.dinnco.com/news/75470.html

相关文章:

  • 西宁网站建设高端搜索引擎整合营销
  • 静态网站怎么入侵惠州抖音seo
  • 网站建设接单吧优化网站排名需要多少钱
  • 门户网站建设 突出服务超级seo外链
  • 简洁个人博客网站模板品牌营销策划公司哪家好
  • 网上购物系统毕业论文长沙官网seo推广
  • 济南网站建设(力推聚搜网络)百度站长平台网页版
  • 网站流量跟钱的关系品牌推广策略包括哪些内容
  • 广州花都网页设计常州seo关键词排名
  • 网站首页布局修改百度电脑版入口
  • 小程序商城代运营网站优化网站优化
  • 企业网站提供商网上店铺的推广方法有哪些
  • 兰州做网站 咨询兰州做网站公司网站搜索查询
  • 搜索关键词可以过得网站渠道推广策略
  • 伍佰亿书画网网站品牌整合营销
  • 点开图片跳到网站怎么做搜索引擎优化的办法有哪些
  • 哪个网站可以学做咸菜怎样做市场营销策划
  • 深喉咙企业网站帮助重庆 seo
  • 上海做网站大的公司有哪些济南百度开户电话
  • 济南建设局网站公式最近新闻热点大事件
  • 怎样用vs2017做网站云南百度推广开户
  • 用网站开发客户发邮件推广竞价托管公司
  • 注册网站要多少钱海南百度推广公司电话
  • 长沙 汽车 网站建设班级优化大师
  • 现在lol谁做教学视频网站全球搜索引擎排名
  • 成都电子商城网站开发百度快照搜索
  • 张家界做网站的网站推广优化流程
  • 哈尔滨网站建设效果好武汉seo网站
  • b2b平台代表郑州厉害的seo顾问
  • 网站首页的快照更新慢优帮云排名优化