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


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

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

     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,扩展不便。

    enne5w4 原创博文,转载请注明出处! 地址:https://www.cnblogs.com/zhwc-5w4/ (欢迎技术交流探讨)
  • 相关阅读:
    Android ANR原因以及开发时如何预防
    Nmon工具的使用以及通过nmon_analyse生成分析报表
    LInux在线安装JDK
    linux使用JMETER进行分布式压力测试
    Jmeter-调整占用内存解决内存溢出
    参数化之利用CSV Data Set Config从文件读取参数并关联变量
    JMETER 定时器 之 常数吞吐量定时器
    【Jmeter】Jmeter聚合报告分析
    Nmon的安装及使用
    MySQL CURDATE() 函数
  • 原文地址:https://www.cnblogs.com/zhwc-5w4/p/14371334.html
Copyright © 2020-2023  润新知