鸿蒙开发融云demo录制语音消息
鸿蒙开发融云demo录制语音消息
融云鸿蒙版是不带UI的,得自己一步步搭建。录制语音,长按录制效果是最难弄的。还有录制声音的声音大小波动。
这次来讲如何长按录制语音消息
一、思路:
自定义TouchEvent,然后调用融云的录制语音方法。声音大小用AudioRecorder.getInstance().avRecorder?.getAudioCapturerMaxAmplitude
二、效果图:
三、关键代码:
// 播放语音的播放器// 区分语音还是文字输入状态@State isVoiceInput:boolean = falsemicrophonePermissions: Permissions = 'ohos.permission.MICROPHONE';hasMicrophonePermissions:boolean = false// 是否正在请求麦克风权限isRequestMicrophonePermissions:boolean = false// Column高度最大值,用于长按是声音的振幅@State yMax: number = 0;// Column高度最小值@State yMin: number = 0;// 声音文件名称,不能重复,否则播放自己本地语音,只会播放最后一条voiceName:string = ''// 当前录音时间,用于录制到50s后倒计时currentRecordVoiceTime:number = 0@State countDownVoiceText:string = ''maxMicVolumeCountId: number = 0// 开始录制时的时间戳audioTapTs: number = 0;audioFile: fs.File | null = null;// 创建音频录制与播放实例avPlayer?:media.AVPlayer@State voicePlayState: AnimationStatus = AnimationStatus.Initial@State voicePlayMessageId:number = 0// 按住说话 录音模态@StateshowTalkContainer: boolean = false// 长按状态@StatepressCancelVoicePostText: PressCancelVoicePostText = PressCancelVoicePostText.none// “x ”的坐标xScreenOffset: ScreenOffset = {x: 0,y: 0,width: 0,height: 0}// 按住说话 持续触发onPressTalk = async (event: TouchEvent) => {if (event.type === TouchType.Down) {this.currentRecordVoiceTime = 0this.countDownVoiceText = ''PermissionUtil.checkPermissions(this.microphonePermissions).then((result:boolean) => {if (result) {// 有权限this.hasMicrophonePermissions = truethis.isRequestMicrophonePermissions = false// 手指按下时触发this.pressCancelVoicePostText = PressCancelVoicePostText.presssing// 按下this.showTalkContainer = true// 开始录音this.startRecordVoice()} else {this.isRequestMicrophonePermissions = true// 问麦克风权限PermissionUtil.requestPermissionsEasy(this.microphonePermissions).then((result:boolean)=>{if (result) {// 有权限this.hasMicrophonePermissions = true// 这里先不录,因为用户放开手去点击允许权限了//this.startRecordVoice()} else {this.hasMicrophonePermissions = false}})}})} else if (event.type === TouchType.Move) {if (this.hasMicrophonePermissions && !this.isRequestMicrophonePermissions) {// 手指移动时持续触发this.pressCancelVoicePostText = PressCancelVoicePostText.presssing// 获取当前手指的坐标const x = event.touches[0].displayXconst y = event.touches[0].displayY// 判断是否碰到了 “X”let isTouchX = this.xScreenOffset.x <= x && this.xScreenOffset.x + this.xScreenOffset.width >= x &&this.xScreenOffset.y <= y && this.xScreenOffset.y + this.xScreenOffset.width >= yif (isTouchX) {// 取消发送this.pressCancelVoicePostText = PressCancelVoicePostText.cancelVoice}}} else if (event.type === TouchType.Up) {// 松开手if (this.showTalkContainer) {this.showTalkContainer = falseclearInterval(this.maxMicVolumeCountId)animateTo({ duration: 0 }, () => {this.yMax = 0this.yMin = 0})if (this.hasMicrophonePermissions && !this.isRequestMicrophonePermissions) {if (this.pressCancelVoicePostText === PressCancelVoicePostText.cancelVoice) {// 取消发送AudioRecorder.getInstance().stopRecordingProcess()} else {// 发送录音this.recordAudioEndAndSendMessage()}}}}}
// 正在说话 页面布局@BuilderTalkContainerBuilder() {Column() {// 1 中心的提示 显示波浪线Column() {// 声纹ButtonWithWaterRipples({ yMax: this.yMax, yMin: this.yMin })if (this.countDownVoiceText){Text(`${this.countDownVoiceText}"后将停止录音`).fontColor($r('app.color.color_white')).margin({top:10})}}.height(80).width("50%").backgroundColor(this.pressCancelVoicePostText === PressCancelVoicePostText.cancelVoice ? Color.Red : "#95EC6A").position({top: "40%",left: "50%"}).translate({x: "-50%"}).borderRadius(10).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)// 2 取消和转文字Column({space:30}) {// 3 松开发送Text(this.pressCancelVoicePostText === PressCancelVoicePostText.cancelVoice ? '取消发送' : "松开发送").fontColor("#fff").width("100%").textAlign(TextAlign.Center)Text("X").fontSize(20).width(60).height(60).borderRadius(30).fontColor(this.pressCancelVoicePostText === PressCancelVoicePostText.cancelVoice ? "#000" : "#ccc").backgroundColor(this.pressCancelVoicePostText === PressCancelVoicePostText.cancelVoice ? "#fff" : "#333").textAlign(TextAlign.Center).align(Alignment.Center).fontColor("#ccc").id("aabb").onAppear(() => {let modePosition: componentUtils.ComponentInfo = componentUtils.getRectangleById("aabb");this.xScreenOffset.x = px2vp(modePosition.screenOffset.x)this.xScreenOffset.y = px2vp(modePosition.screenOffset.y)this.xScreenOffset.width = px2vp(modePosition.size.width)this.xScreenOffset.height = px2vp(modePosition.size.height)})}.width("100%").position({bottom: "23%"}).padding({left: 60, right: 60})// 4 底部白色大球Row() {}.width(600).height(600).backgroundColor("#fff").position({bottom: 0,left: "50%"}).translate({x: "-50%",y: "70%"}).borderRadius("50%")}.width("100%").height("100%").backgroundColor("rgba(0,0,0,0.5)")}
四、鸿蒙融云Demo源码结构图:
有问题或者需要完整源码demo的私信我