HarmonyOS NEXT 语音录制和声音动效实现

2024-08-16 20:59:05 浏览数 (4)

介绍

本示例使用AVrecord录制音频和AVrecord的getAudioCapturerMaxAmplitude接口获取振幅实现UI动效;使用AVplayer播放音频

效果图预览

使用说明

  1. 按住按钮开始录音。
  2. 上划取消录制。
  3. 录制完成后点击消息框可播放录音。

实现思路

  1. 利用组合手势来实现音频录制与取消录制。build() { Column() { Button($r('app.string.button')) .gesture( GestureGroup(GestureMode.Sequence, LongPressGesture() .onAction( () => { this.AVrecord.startRecordingProcess(); }) .onActionEnd( () => { this.AVrecord.stopRecordingProcess(); }), PanGesture() .onActionStart( () => { clearInterval(this.count); }) .onActionEnd( () => { this.AVrecord.stopRecordingProcess(); }) ) .onCancel( () => { this.AVrecord.startRecordingProcess(); }) ) } }async startRecordingProcess() { if (this.avRecorder !== undefined) { await this.avRecorder.release(); this.avRecorder = undefined; } // 1.创建录制实例 this.avRecorder = await media.createAVRecorder(); this.setAudioRecorderCallback(); // 2.获取录制文件fd赋予avConfig里的url;参考FilePicker文档 const context = getContext(this); const path = context.filesDir; const filepath = path '01.mp3'; const file = fs.openSync(filepath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); const fdNumber = file.fd; this.avConfig.url = 'fd://' fdNumber; // 3.配置录制参数完成准备工作 await this.avRecorder.prepare(this.avConfig); // 4.开始录制 await this.avRecorder.start(); // 获取最大振幅 this.time = setInterval(() => { this.avRecorder!.getAudioCapturerMaxAmplitude((_: BusinessError, amplitude: number) => { this.maxAmplitude = amplitude; }); }, Const.COLUMN_HEIGHT); } Button($r('app.string.button')) .gesture( GestureGroup(GestureMode.Sequence, LongPressGesture() .onAction(() => { // 获取时间戳 this.timeStart = Math.floor(new Date().getTime() / Const.ANIMATION_DURATION); this.flag2 = Const.OPACITY_FALSE; this.isListening = !this.isListening; this.flag = Const.OPACITY_TRUE; this.AVrecord.startRecordingProcess(); // 每隔100ms获取一次振幅 this.count = setInterval(() => { if (this.AVrecord.maxAmplitude > Const.MIN_AMPLITUDE) { this.maxNumber = (this.AVrecord.maxAmplitude) / Const.MAX_AMPLITUDE * Const.COLUMN_HEIGHT; this.minNumber = (this.AVrecord.maxAmplitude) / Const.MAX_AMPLITUDE * Const.COLUMN_HEIGHT - Const.HEIGHT_MIN; } else { this.maxNumber = Const.OPACITY_FALSE; this.minNumber = Const.OPACITY_FALSE; } if (this.isListening) { animateTo({ duration: Const.ANIMATION_DURATION, curve: Curve.EaseInOut }, () => { this.yMax = this.maxNumber; this.yMin = this.minNumber; }) } }, Const.SET_INTERVAL_TIME); }) .onActionEnd(() => { clearInterval(this.count); this.flag2 = Const.OPACITY_TRUE; this.yMax = Const.OPACITY_FALSE; this.yMin = Const.OPACITY_FALSE; this.AVrecord.stopRecordingProcess(); }), // 上划取消 PanGesture() .onActionStart(() => { clearInterval(this.count); }) .onActionEnd(() => { this.isListening = false; animateTo({ duration: Const.OPACITY_FALSE }, () => { this.yMax = Const.OPACITY_FALSE; this.yMin = Const.OPACITY_FALSE; }) this.flag = Const.OPACITY_FALSE; this.flag2 = Const.OPACITY_FALSE; this.AVrecord.stopRecordingProcess(); }) ) .onCancel(() => { // 获取结束时间戳并计算出手势持续时间 this.timeEnd = Math.floor(new Date().getTime() / Const.ANIMATION_DURATION); this.timeAv = this.timeEnd - this.timeStart; clearInterval(this.count); this.isListening = false; animateTo({ duration: Const.OPACITY_FALSE }, () => { this.yMax = Const.OPACITY_FALSE; this.yMin = Const.OPACITY_FALSE; }); this.flag = Const.OPACITY_FALSE; this.flag2 = Const.OPACITY_TRUE; this.AVrecord.startRecordingProcess(); }) ) build() { Row ({ space: 5 }) { ForEach(this.arr, (_:number) => { Column() .width(this.x) .height(Math.floor(Math.random() * (this.yMin - this.yMax Const.ONE) this.yMax)) }, (index: number) => index.toString()) } ... }Image($r('app.media.icon')) .width($r('app.integer.width_image')) .height($r('app.integer.height_image')) .onClick( () => { this.AVplaer.avPlayerUrlDemo(); } )工程结构&模块类型
  2. 在音频录制的时候通过getAudioCapturerMaxAmplitude获取声音振幅使UI变化。
  3. 使用AVplayer播放已录制的音频。
代码语言:shell复制
normalcaptu                                      // har类型
|---src
|   |---main
|   |     |---ets
|   |     |  |---common                        
|   |        |    |---CommonConstants.ets       // 常量定义 
|   |     |  |---pages                          
|   |        |    |---Index.ets                 // 主页面

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙