应用场景

在上一篇文章中,我们完成了一个简单的录音功能,但是我们在录音的过程中,并不能看见看到自己说话的音量大小,所以要完成一个实时显示音量大小的组件。

上一篇文章:

鸿蒙中使用 AvRecorder-完成录音功能

实现效果

核心API 版本API 11+

通过 getAudioCapturerMaxAmplitude 观察音频区间

异步方式获取当前音频最大振幅。通过注册回调函数获取返回值。

在prepare()成功触发后,才能调用此方法。

首先通过打印的方式实时打印音量大小

在开始录制的方法中,使用延时器,每隔100毫秒打印一次声音的音量大小。

// 记录声音的振幅
  @State maxAmplitude: number = 0
  // 定时器id
  timerId = 0


// 开始录制方法
  async startRecord() {

    ...... 省略之前的录制代码,最后附上完整版

// 监听声音的振幅
    this.timerId = setInterval(async () => {
      // 获取 振幅
      const res = await avRecorder.getAudioCapturerMaxAmplitude()
      // 记录用于 一会传递给视图的振幅
      this.maxAmplitude = res
      // 打印
      console.log('振幅:' + res)
    }, 100)
  }

开始录制后,在日志中能实时打印出音量即可。经过观察,很大声说话的振幅在30000左右。

封装振幅组件

逻辑:

  1. 父组件传入振幅maxAmplitude,子组件通过@Prop接收
  2. 子组件@Watch 监听 maxAmplitude 的实时变化
  3. 根据刚才打印的声音振幅,发现 500 以下基本没声音,30000基本封顶了
  4. 所以我们就定义 500 以下不让显示,30000就达到最大音量了
  5. 500到30000中间的平均分为 一百份,决定条状结构的高度
  6. 使用 animateTo 使得条状的高度变化时有动画效果而不是一卡一卡的
  7. 最后在 一个row容器中循环生成30个条状结构。
  8. 那么可能有疑问?我30 个条传入同一个高度变量,怎么做到波形效果呢?
  9. 这里就用 乘以 随机数的办法,让每个条的高度不一样。
@Component
export struct AudioBoComp {
  @Prop @Watch('onChange') maxAmplitude: number
  @State per: number = 0

  // 监听 maxAmplitude 变化
  onChange() {
    // 为了减少动画的卡顿,使用 animateTo 来做动画
    animateTo({ duration: 100 }, () => {
      // 大于 30000 基本就是最大声音了
      if (this.maxAmplitude >= 30000) {
        this.per = 1
        // 小于 500 基本就是静音了
      } else if (this.maxAmplitude <= 500) {
        this.per = 0
        //   中间按比例算
      } else {
        this.per = this.maxAmplitude / 30000
      }
    })
  }

  build() {
    Row({ space: 3 }) {
      // 这里虽然30个竖条传入同一个变量,但是乘以随机数,但是会生成30个不同的值,就模拟了音浪
      ForEach(Array.from({ length: 30 }), () => {
        Column()
          .height(this.per * 100 * Math.random())
          .layoutWeight(1)
          .backgroundColor(Color.Blue)
      })
    }
    .width(200)
    .height(100)
  }
}

在父组件中使用并传入maxAmplitude

Column({ space: 10 }) {
      // 振幅组件
      AudioBoComp({ maxAmplitude: this.maxAmplitude })
      
      Button('开始录制')
        .onClick(() => {
          this.startRecord()
          promptAction.showToast({ message: '开始录制' })
        })
      Button('停止录制')
        .onClick(() => {
          this.stopRecord()
          promptAction.showToast({ message: '停止录制' })
        })
    }

点击开始录制就会出现振幅,但是这时候还有问题,当我们点击停止录制后,maxAmplitude并不会重置为0,所以振幅组件会停止在最后一个振幅

这时候就要在停止录制时手动将maxAmplitude归零。

this.maxAmplitude = 0 加在 stopRecord() 方法最后即可。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐