Harmony OS5/ArkTs 封装录音工具
1,录音之前,先获取权限
avRecorder?: media.AVRecorder
fd?: number
filePath?: string
permissions: Permissions[] = ['ohos.permission.MICROPHONE']
const atManager = abilityAccessCtrl.createAtManager()
const ctx = AppStorage.get<Context>('context')
//获取用户权限 authResults数组=>[0,-1]权限1 同意了,权限2 用户没同意
const result = await atManager.requestPermissionsFromUser(ctx, permissions)
const isOK = result.authResults.every(result => result === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)
if(!isOK){
return
}
// 弹窗提示
//二次授权
const confirm = await promptAction.showDialog({
title: "温馨提示",
message: "未授权使用麦克风将无法使用该录音功能,是否前往设置进行授权?",
buttons: [
{ text: '离开', color: $r('app.color.common_gray_01') },
{ text: '去授权', color: $r('app.color.black') }
]
})
//用户选择了去设置
if (confirm.index === 1) {
const isOk2 = await this.atManager.requestPermissionOnSetting(this.ctx, permissions)
if (isOk2) {
return
}
}
router.back()
module.json5
"requestPermissions": [
{ "name": "ohos.permission.INTERNET" },
{
"name": "ohos.permission.MICROPHONE",
"usedScene": {},
"reason": "$string:reason_microphone"
}
],
reason_microphone原因格式:用于xxx模块xxx功能
用于审核使用
2,AvRecorder录音生命周期
3开始录音, 保存的文件不能存在缓存中,否则一清缓存,录音文件就没有了
//1,先准备一个文件接收录音
const ctx = getContext(this)
this.filePath = ctx.filesDir + '/' + Date.now() + '.m4a'
const file = fileIo.openSync(this.filePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
this.fd = file.fd
//开始录制了
//2,音频配置项设置
const config: media.AVRecorderConfig = {
audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC,
profile: {
audioBitrate: 100000, // 音频比特率
audioChannels: 1, // 音频声道数
audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式,当前只支持aac
audioSampleRate: 48000, // 音频采样率
fileFormat: media.ContainerFormatType.CFT_MPEG_4A, // 封装格式,当前只支持m4a
},
url: `fd://${file.fd}`
}
// 3. 获取音频对象
const avRecorder = await media.createAVRecorder()
//prepare中指定了,存放的录音的位置和录音的质量等等配置
await avRecorder.prepare(config)
//开始录制
await avRecorder.start()
//暂存到全局,方便其他函数内调用
this.avRecorder = avRecorder
停止录音后记得释放!
if (this.avRecorder) {
try {
await this.avRecorder.stop()
await this.avRecorder.release()
fileIo.closeSync(this.fd)
// stopRecord 清理定时器
clearInterval(this.timer)
} catch (e) {
logger.debug('stopAudio', JSON.stringify(e))
}
}
4,封装的工具类如下
import { abilityAccessCtrl, Permissions } from '@kit.AbilityKit';
export class PermissionUtil {
//获取管理实例
atManager = abilityAccessCtrl.createAtManager()
ctx = AppStorage.get<Context>('context')
// 请求用户授权
async requestPermissions(permissions: Permissions[]) {
if (this.ctx) {
//获取用户权限 authResults数组=>[0,-1]权限1 同意了,权限2 用户没同意
const result = await this.atManager.requestPermissionsFromUser(this.ctx, permissions)
console.log('PermissionsResult', JSON.stringify(result))
//得到用户权限 只有有结果 等于0就是允许,-1是拒绝
return result.authResults.every(result => result === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)
}
return false
}
// 打开权限设置 beta3
async openPermissionSetting(permissions: Permissions[]) {
if (this.ctx) {
//打开设置
const authResults = await this.atManager.requestPermissionOnSetting(this.ctx, permissions)
return authResults.every(result => result === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)
}
return false
}
}
export const permissionUtil = new PermissionUtil()
示例
@Entry
@Component
struct AudioPage {
@State recording: boolean = false
permissions: Permissions[] = ['ohos.permission.MICROPHONE']
//授权提示
confirmConfig: promptAction.ShowDialogOptions = {
title: "温馨提示",
message: "未授权使用麦克风将无法使用该面试录音功能,是否前往设置进行授权?",
buttons: [
{ text: '离开', color: $r('app.color.common_gray_01') },
{ text: '去授权', color: $r('app.color.black') }
]
}
avRecorder?: media.AVRecorder
fd?: number
filePath?: string
aboutToAppear(): void {
this.getPermission()
}
//授权
async getPermission() {
try {
// 第一请求授权
const isOk = await permissionUtil.requestPermissions(this.permissions)
if (isOk) {
return
}
// 弹窗提示
//二次授权
const confirm = await promptAction.showDialog(this.confirmConfig)
if (confirm.index === 1) {
const isOk2 = await permissionUtil.openPermissionSetting(this.permissions)
if (isOk2) {
return
}
}
router.back()
} catch (e) {
promptAction.showToast({ message: '未授权' })
router.back()
}
}
//开始录音
async startAudio() {
//先准备一个文件接收录音
const ctx = getContext(this)
this.filePath = ctx.filesDir + '/' + Date.now() + '.m4a'
const file = fileIo.openSync(this.filePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
this.fd = file.fd
//开始录制了
//准备路由配置音频对象
const config: media.AVRecorderConfig = {
audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC,
profile: {
audioBitrate: 100000, // 音频比特率
audioChannels: 1, // 音频声道数
audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式,当前只支持aac
audioSampleRate: 48000, // 音频采样率
fileFormat: media.ContainerFormatType.CFT_MPEG_4A, // 封装格式,当前只支持m4a
},
url: `fd://${file.fd}`
}
// 3. 开始录制
this.avRecorder = await media.createAVRecorder()
await this.avRecorder.prepare(config) //prepare中指定了,存放的录音的位置和录音的质量等等配置
await this.avRecorder.start() //开始录制
//实时获取音频震动幅度效果
// startRecord 4. 每100ms获取一下声音振幅
this.timer = setInterval(async () => {
this.maxAmplitude = await this.avRecorder!.getAudioCapturerMaxAmplitude()
logger.debug('startAudio', this.maxAmplitude.toString())
}, 100)
}
build() {
Column() {
Row() {
Image($r('sys.media.ohos_ic_public_voice'))
.width(24)
.aspectRatio(1)
.fillColor($r('app.color.white'))
.onClick(async () => {
if (this.recording) {
await this.stopAudio()
this.recording = false
} else {
await this.startAudio()
this.recording = true
}
})
}
.justifyContent(FlexAlign.Center)
.height(50)
.width(50)
.borderRadius(25)
.margin({ top: 20 })
.backgroundColor($r('app.color.black'))
}
.width('100%')
.height(240)
.backgroundColor($r('app.color.common_gray_bg'))
.padding({
bottom: this.bottomHeight,
left: 80,
right: 80,
top: this.topHeight
})
}
}
录音文件在沙箱中查看
播放录音请看我下一个博客