HarmonyOS5/ArkTs 播放录音案例

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)
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值