HarmonyOS5/ArkTs 封装播放录音工具类
前一篇有封装录音案例
两步
1,播放
avPlayer?: media.AVPlayer
async startPlay() {
try {
//先得到这个文件
const file = fileIo.openSync(this.filePath, fileIo.OpenMode.READ_ONLY)
//得到播放对象
this.avPlayer = await media.createAVPlayer()
//监听状态
this.avPlayer.on('stateChange', state => {
if (state === 'initialized') {
//准备
this.avPlayer!.prepare()
} else if (state === 'prepared') {
//循环播放
this.avPlayer!.loop = true
//时长
this.total = this.avPlayer!.duration
this.avPlayer!.play()
}
})
this.avPlayer.url = `fd://${file.fd}`
} catch (e) {
logger.error('startPlay', JSON.stringify(e))
}
}
停止播放
stopPlay() {
if (this.avPlayer) {
this.avPlayer.stop()
this.avPlayer.release()
}
}
结合上一篇封装录音的博客,完整代码如下:
AudioPage
import { permissionUtil } from '../common/utils/PermissionUtil'
import { Permissions } from '@kit.AbilityKit'
import { promptAction, router } from '@kit.ArkUI'
import { media } from '@kit.MediaKit'
import { fileIo } from '@kit.CoreFileKit'
import { logger } from '../common/utils/LoggerUtil'
import { AudioBoComp } from '../views/minPage/AudioBoComp'
@Entry
@Component
struct AudioPage {
@StorageProp('topHeight')
topHeight: number = 0
@StorageProp('bottomHeight')
bottomHeight: number = 0
@State recording: boolean = false
timer?: number
@State maxAmplitude: number = 0
permissions: Permissions[] = ['ohos.permission.MICROPHONE']
//授权提示
confirmConfig: promptAction.ShowDialogOptions = {
title: "温馨提示",
message: "未授权使用麦克风将无法使用该xx录音功能,是否前往设置进行授权?",
buttons: [
{ text: '离开', color: $r('app.color.common_gray_01') },
{ text: '去授权', color: $r('app.color.black') }
]
}
avRecorder?: media.AVRecorder
fd?: number
filePath?: string
//
avPlayer?: media.AVPlayer
@State total: number = 0
@State value: number = 0
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)
}
//停止录音
async stopAudio() {
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))
}
}
}
build() {
Column() {
Button('开始播放')
.onClick(() => {
this.startPlay()
})
Button('停止播放')
.onClick(() => {
this.stopPlay()
})
Progress({ total: this.total, value: this.value })
.width('100%')
//语音震动效果
if (this.recording) {
AudioBoComp({ maxAmplitude: this.maxAmplitude })
}
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
// TO DO 记录录音
} 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
})
}
//
async startPlay() {
try {
//先得到这个文件
const file = fileIo.openSync(this.filePath, fileIo.OpenMode.READ_ONLY)
//得到播放对象
this.avPlayer = await media.createAVPlayer()
//监听状态
this.avPlayer.on('stateChange', state => {
if (state === 'initialized') {
//准备
this.avPlayer!.prepare()
} else if (state === 'prepared') {
//循环播放
this.avPlayer!.loop = true
//时长
this.total = this.avPlayer!.duration
this.avPlayer!.play()
}
})
// 当前最新播放时间
this.avPlayer.on('timeUpdate', (time) => {
this.value = time
})
this.avPlayer.url = `fd://${file.fd}`
} catch (e) {
logger.error('startPlay', JSON.stringify(e))
}
}
stopPlay() {
if (this.avPlayer) {
this.avPlayer.stop()
this.avPlayer.release()
}
}
}
module.json5
"requestPermissions": [
{ "name": "ohos.permission.INTERNET" },
{
"name": "ohos.permission.MICROPHONE",
"usedScene": {},
"reason": "$string:reason_microphone"
}
],
PermissionUtil
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()
AudioBoComp
import { logger } from "../../common/utils/LoggerUtil"
@Component
export struct AudioBoComp {
@Prop @Watch('onChange') maxAmplitude: number
@State per: number = 0
onChange() {
animateTo({ duration: 100 }, () => {
if (this.maxAmplitude < 500) {
this.per = 0
} else if (this.maxAmplitude > 30000) {
this.per = 1
} else {
this.per = this.maxAmplitude / 30000
}
logger.debug('AudioBoComp.this.per', this.per.toString())
})
}
build() {
Row({ space: 5 }) {
ForEach(Array.from({ length: 30 }), () => {
Column()
.layoutWeight(1)
.height(this.per * 100 * Math.random())
.backgroundColor($r('app.color.common_blue'))
})
}.backgroundColor(Color.Pink)
.width('100%')
.height(100)
}
}