前言
在開發小程序過程中,有一個實現錄音功能并播放錄音,將錄音上傳至服務器的需求。開發過程中使用了Taro框架,錄音功能通過Taro.getRecorderManager()接口實現,上傳錄音至服務器通過Taro.uploadFile接口實現,播放錄音使用Taro.createInnerAudioContext()接口實現。下面就詳細介紹整個流程是如何實現的。
小程序錄音
首先獲取錄音管理器模塊:
1
|
const recorderManager = Taro.getRecorderManager(); |
在組件掛載完畢時注冊錄音監聽事件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
useEffect(() => { // 監聽錄音開始 recorderManager.onStart(() => { console.log( '開始錄音' ); }); // 監聽錄音暫停 recorderManager.onPause(() => { console.log( '暫停錄音' ); }); // 監聽錄音繼續 recorderManager.onResume(() => { console.log( '繼續錄音' ); }); // 監聽錄音停止 recorderManager.onStop((res) => { if (res.duration < 1000) { Taro.showToast({ title: '錄音時間太短' , duration: 1000, icon: 'none' , }); } else { console.log( '停止錄音' ); fileUpload(res.tempFilePath); } }); recorderManager.onError(() => { Taro.showToast({ title: '錄音失敗!' , duration: 1000, icon: 'none' , }); }); }, []); |
在錄音onStop的回調函數中,我們可以獲取到錄音的臨時地址res.tempFilePath,但這個地址是有有效期限的,所以我們需要將這個錄音上傳至服務器后臺,進行保存,后續才能正常使用。
onStop回調函數中我們調用了fileUpload函數實現文件上傳,fileUpload函數的實現如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
const fileUpload = (tempFilePath) => { Taro.uploadFile({ url: 'http://127.0.0.1:7001/record' , // 服務器地址 filePath: tempFilePath, name: 'file' , // 這個隨便填 header: { 'content-type' : 'multipart/form-data' , // 格式必須是這個 Authorization: Taro.getStorageSync( 'token' ), }, // formData用于傳輸除文件以外的一些信息 formData: { record_name: '朗誦作品' , poem_id: poemInfo.id, category: poemInfo.category, }, success: (res) => { console.log(res); const url = res.data; playAudio(url); // 播放錄音 }, fail: (error) => { console.log( 'failed!' ); console.error(error); }, }); }; |
需要注意的點是:header中的content-type必須是multipart/form-data。
錄音事件的處理
第一次點擊handleClick就會觸發開始錄音,之后會通過當前狀態判斷是暫停錄音還是繼續錄音。handleComplete用于停止錄音。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
const handleClick = () => { const curPause = pause; setPause(!curPause); if (firstRecord) { setfirstRecord( false ); recorderManager.start({ duration: 60000, sampleRate: 44100, numberOfChannels: 1, encodeBitRate: 192000, format: 'mp3' , frameSize: 50, }); Taro.showToast({ title: '開始錄音' , duration: 1000, icon: 'none' , }); } else { if (curPause) { recorderManager.pause(); // 暫停錄音 } else { recorderManager.resume(); // 繼續錄音 } } }; const handleComplete = () => { recorderManager.stop(); // 停止錄音 }; |
后臺實現錄音存儲并返回錄音地址
網上大多數博客都沒有涉及這塊內容,下面就介紹一下如何實現,后臺框架我用的是阿里的egg.js。
文件上傳需要配置的東西可見官方文檔:egg.js文件上傳。我們這里使用它的第一種File模式來實現。
因為egg.js框架內置了Multipart插件,可以解析上傳的multipart/form-data類型的數據。
首先,現在配置文件config.default.js中寫入multipart配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
module.exports = (app) => { const config = (exports = {}); ... config.multipart = { mode: 'file' , fileSize: '50mb' , } ... return { ...config, ...userConfig, }; }; |
然后,在router.js中定義路由:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// 提交錄音 router.post( '/record' , auth, controller.record.postRecord); 在controller目錄下定義record.js文件寫入如下內容: const Controller = require( 'egg' ).Controller; class RecordController extends Controller { async postRecord() { const { ctx } = this ; const file = ctx.request.files[0]; const { record_name, poem_id, category } = ctx.request.body; const res = await ctx.service.record.postRecord(file, record_name, poem_id, category); ctx.body = res; } } module.exports = RecordController; |
在service目錄下定義record.js寫入具體實現:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
const Service = require( 'egg' ).Service; let OSS = require( 'ali-oss' ); let aliInfo = { // https://help.aliyun.com/document_detail/31837.html region: 'oss-cn-guangzhou' , bucket: 'poem-mini-program' , accessKeyId: 'xxx' , // 填入阿里云的accessKeyId accessKeySecret: 'xxx' , // 填入阿里云的accessKeySecret }; let client = new OSS(aliInfo); class RecordService extends Service { async postRecord(file, record_name, poem_id, category) { const url = await this .uploadOSS(file); await this .updateRecord(url, record_name, poem_id, category); return url; } async uploadOSS(file) { const { ctx } = this ; let result; try { // 處理文件,比如上傳到云端 result = await client.put(file.filename, file.filepath); } finally { // 需要刪除臨時文件 await ctx.cleanupRequestFiles(); } return result.url; } async updateRecord(url, record_name, poem_id, category) { const { ctx } = this ; console.log( '從ctx.locals中取openid' ); console.log(ctx.locals.openid); const openid = ctx.locals.openid; // 將用戶信息記錄到數據庫中 const res = await ctx.model.Record.create({ record_name: record_name, record_url: url, poem_id: poem_id, category: category, openid: openid, }); } } module.exports = RecordService; |
這里需要注意的是:
- 需要注冊阿里云賬號,并在對象存儲那里新建一個存儲桶用于存放音頻,也就是云存儲的實現。
- 需要安裝ali-ossnpm包,用于連接阿里云對象存儲。在后臺接收到前端上傳的臨時文件后,就會將音頻上傳至阿里云對象存儲中(client.put)。
播放錄音
細心的小伙伴可以注意到在使用Taro.uploadFile接口上傳錄音后,在success回調中調用了playAudio函數用于播放音頻,接下來講一下播放音頻是如何實現的。
首先,使用Taro.createInnerAudioContext獲取audio的上下文對象:
1
|
const innerAudioText = Taro.createInnerAudioContext(); |
和錄音一樣,在組件掛載完成時,注冊監聽事件:
1
2
3
4
5
6
7
8
9
10
|
useEffect(() => { innerAudioText.onPlay(() => { console.log( '開始播放' ); }); innerAudioText.onError((e) => { console.log( '播放異常' ); console.log(e); }); }, []); |
在錄音文件上傳成功后,調用playAudio方法用于播放錄音:
1
2
3
4
|
const playAudio = (url) => { innerAudioText.autoplay = true ; innerAudioText.src = url; }; |
在src被賦予值的時候,錄音就會開始播放。
總結
到此這篇關于小程序錄音功能實現的文章就介紹到這了,更多相關小程序 錄音內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://juejin.cn/post/6936718733767344136