Table of Contents
最近有个需求,微信小程序录音并播放。
录音
- 首先,获取全局录音管理器。
- 然后 onLoad 里面配置各种事件监听。
- 调用录音/停止 api,处理录音事件。
// 录音管理器 const recordManager = wx.getRecorderManager() Page({ data: { voiceReportInfo: '', // 工单详情语音 url voiceSeconds: 0, // 语音时间 recordStatus: '', // ready, recording recordConfig: { // 录音配置 duration: 600000, sampleRate: 44100, numberOfChannels: 1, encodeBitRate: 192000, frameSize: 50, format: 'aac', }, }, onLoad: function (options) { recordManager.onStart((e) => this.handleRecordStart(e)) recordManager.onStop((e) => this.handleRecordStop(e)) recordManager.onError((e) => this.handleRecordError(e)) }, /** * 开始录音 */ startRecord() { console.log('touchStart') const { recordStatus } = this.data if (recordStatus === 'recording') return if (!recordStatus) { const _self = this wx.getSetting({ success(res) { if (!res.authSetting['scope.record']) { wx.authorize({ scope: 'scope.record', success() { _self.setData({ recordStatus: 'ready', }) console.log('ready') recordManager.start(_self.data.recordConfig) }, fail() { wx.showToast({ title: '未授权', icon: 'none', }) }, }) } else { _self.setData({ recordStatus: 'ready', }) console.log('ready') recordManager.start(_self.data.recordConfig) } }, fail() { wx.showToast({ title: '抱歉,目前无法录音', icon: 'none', }) }, }) } else { this.setData({ recordStatus: 'ready', }) console.log('ready') recordManager.start(this.data.recordConfig) } }, /** * 结束录音 */ endRecord() { console.log('touchEnd') const { recordStatus } = this.data if (recordStatus === 'ready' || !recordStatus) return recordManager.stop() }, /** * 开始录音事件 */ handleRecordStart() { console.log('start') this.setData({ recordStatus: 'recording', }) }, /** * 结束录音事件 */ handleRecordStop(e) { const { tempFilePath, duration } = e if (tempFilePath) { // 把音频上传到云服务器 uploadFile({ url: config.uploadUrl, filePath: tempFilePath, }) .then((res) => { if (res[0].success && res[0].result) { this.setData({ voiceReportInfo: res[0].result, voiceSeconds: Math.round(duration / 1000), }) } else { wx.showToast({ title: '上传失败', icon: 'none', }) } this.setData({ recordStatus: 'ready', }) }) .catch((e) => { wx.showToast({ title: e.message || '上传失败', icon: 'none', }) this.setData({ recordStatus: 'ready', }) }) } }, /** * 录音出错 */ handleRecordError(e) { console.log(e) }, })
播放音频
为了方便复用,播放音频封装成了组件。内部处理和在页面里写差不多。
- 创建音频上下文。
- 监听音频地址,监听相关事件。
- 播放/暂停处理。
// components/audio-player/index.js // 音频上下文 const innerAudioContext = wx.createInnerAudioContext() Component({ /** * 组件的属性列表 */ properties: { src: String, duration: Number, }, /** * 组件的初始数据 */ data: { isPlaying: false, }, observers: { src: function (value) { if (typeof value === 'string' && value) { innerAudioContext.src = value // innerAudioContext.onCanplay((e) => this.handleAudioCanplay(e)) innerAudioContext.onPlay((e) => this.handleAudioPlay(e)) innerAudioContext.onPause((e) => this.handleAudioPause(e)) innerAudioContext.onStop((e) => this.handleAudioPause(e)) innerAudioContext.onEnded((e) => this.handleAudioPause(e)) innerAudioContext.onError((e) => this.handleAudioError(e)) } else { innerAudioContext.src = '' } }, }, /** * 组件的方法列表 */ methods: { /** * 播放音频 */ playAudio() { const { isPlaying } = this.data if (isPlaying) { innerAudioContext.pause() } else { innerAudioContext.play() } }, /** * 音频播放成功 */ handleAudioPlay() { console.log('play: ', innerAudioContext) this.setData({ audioPlay: true, }) }, /** * 音频播放暂停 */ handleAudioPause() { console.log('pause') this.setData({ audioPlay: false, }) }, /** * 音频播放失败 */ handleAudioError(e) { console.log(e) wx.showToast({ title: '播放失败', icon: 'none', }) }, }, })
本来是准备在 onCanplay 事件里获取音频时长的,但获取到的都是 0。所以还是用的录音时记录的时长。
小程序的摸索总是比 web 坎坷。