前端仔,别再用祖传方法实现录音功能了

前端和用户直接相关,所以实现录音功能是很常见的需求。如何实现配音功能,网上一搜全是老掉牙方法。作为一个热爱新技术,喜欢与时俱进的前端仔,我实在看不下去了,就写了这篇文章教大家如何用新方法实现录音功能。

废话不多说,直接上代码(非常简单易懂,而且我封装好了):

 1 function Recorder(stream, mimeType) {
 2     const mediaRecorder = new MediaRecorder(stream);
 3     let chunks = [];    
 4     let blob
 5     mediaRecorder.ondataavailable = function (e) {
 6         chunks.push(e.data);
 7     }
 8     mediaRecorder.onstop = function () {       
 9         blob = new Blob(chunks, { 'type': mimeType });       
10         chunks = [];
11     }
12 
13     // 开始录音方法:
14     this.start = function () {
15         mediaRecorder.start();
16     }
17 
18     // 结束录音方法:
19     this.stop = function () {
20         mediaRecorder.stop();
21     }
22 
23     // 获取录音的音频文件
24     this.getFile = function () {
25         return blob
26     }
27 }
28 
29 export default function getRecorder(mimeType = "audio/ogg; codecs=opus") {
30     if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
31         return Promise.reject(new Error('当前浏览器不支持录音功能。'));
32     }
33     return navigator.mediaDevices.getUserMedia({ audio: true }).then(function (stream) {
34         return new Recorder(stream, mimeType)
35     })
36 }

36行代码全部搞定,而且支持各种文件类型。

再看看网上搜到的祖传方法,代码过多,慎点:

(因为代码过多,我将其分成了三个文件,这里只展示主文件,过于底层的两个就不展示了,因为没有必要教大家如何用老方法实现录音,这里只是为了对比网上搜的老方法有多糟糕。
声明一下,这里没有看不起老方法的意思,在那个年代能够以这样的方式实现录音的肯定是大神。
不过现在确实都2021年了,祖传方法还这么流行,这是国内IT博客互相无脑抄袭的风气造成的。)

 1 import encodeWAV from './utiles/encodeWAV' // 负责将音频数据编码成mav格式的文件,共64行。代码过于底层,这里不展示!
 2 import audioTransform from './utiles/audioTransform' // 输入音频的声道,采样率,比特率和输出要求不一致时,负责做转换的。共52行。代码过于底层,这里不展示!
 3 const channelCount = 1;
 4 const sampleBits = 16
 5 var HZRecorder = function (stream) {
 6     const outConf = { channelCount, sampleBits }
 7     const inConf = { channelCount, sampleBits };
 8 
 9     var context = new AudioContext();
10     var audioInput = context.createMediaStreamSource(stream);
11     outConf.sampleRate = inConf.sampleRate = context.sampleRate
12 
13     var jsProcessor = context.createScriptProcessor(0, inConf.channelCount, outConf.channelCount); //输入声道和输出声道
14     //定义数据    
15     var audioData = {
16         size: 0,          //录音文件长度
17         buffer: [],     //录音缓存                
18         input: function (data) {
19             this.buffer.push(new Float32Array(data));
20             this.size += data.length;
21         },
22         encode: function () {
23             let inputSampleArr = new Float32Array(this.size), offset = 0;
24             for (let i = 0; i < this.buffer.length; i++) {
25                 inputSampleArr.set(this.buffer[i], offset);
26                 offset += this.buffer[i].length;
27             }
28             let res = audioTransform(inputSampleArr, inConf, outConf)
29             return encodeWAV(res.sampleArr, res.sampleRate, res.sampleBits, res.channelCount)
30         },
31         clear: function () {
32             this.size = 0;
33             this.buffer = []
34         }
35     };
36 
37     //开始录音
38     this.start = function () {
39         audioData.clear()
40         audioInput.connect(jsProcessor);       
41         jsProcessor.connect(context.destination);
42     }
43 
44     //停止
45     this.stop = function () {
46         audioInput.disconnect()       
47         jsProcessor.disconnect();
48     }
49 
50     //获取音频文件
51     this.getBlob = function () {
52         this.stop()
53         return audioData.encode();
54     }
55 
56     //音频采集
57     jsProcessor.onaudioprocess = function (e) {
58         /**
59          * @type {Float32Array}
60          */
61         let data = e.inputBuffer.getChannelData(0)    
62         audioData.input(data);
63     }
64 };
65 
66 //获取录音机
67 export default function getRecorder() {
68     if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
69         return Promise.reject(new Error('当前浏览器不支持录音功能。'));
70     }
71     //获取计算机的设备:录音设备
72     return navigator.mediaDevices.getUserMedia({
73         audio: { sampleSize: sampleBits, channelCount: 1 }
74     }).then(stream => {      
75         return new HZRecorder(stream);
76     });
77 };
View Code

 老方法,涉及过多的底层。文件类型只支持wav,扩展不便。

posted @ 2021-02-04 11:07  enne5w4  阅读(1366)  评论(0编辑  收藏  举报