JS实时获取录音数据并播放

本文介绍了如何在浏览器中使用原生API获取录音权限,通过WebAudioAPI处理音频数据,然后使用lamejs库将Float32Array转换为MP3Blob对象,最后播放转换后的音频。
摘要由CSDN通过智能技术生成

一 原生拉起录音授权,实时获取音频的返回的Float32arry数据

// 声明获取数据的数组

var getPCMarrayBuffer = []

 // 初始化浏览器录音

  recorderInit() {

    navigator.getUserMedia =

      navigator.getUserMedia ||

      navigator.webkitGetUserMedia ||

      navigator.mozGetUserMedia ||

      navigator.msGetUserMedia

   

    // 创建音频环境

    try {

      this.audioContext = new (window.AudioContext || window.webkitAudioContext)()

      this.audioContext.resume()

      if (!this.audioContext) {

        alert('浏览器不支持webAudioApi相关接口')

        return

      }

    } catch (e) {

      if (!this.audioContext) {

        alert('浏览器不支持webAudioApi相关接口')

        return

      }

    }

    // 获取浏览器录音权限

    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {

      navigator.mediaDevices

        .getUserMedia({

          audio: {

            volume: 1.0,

          },

          video: false,

        })

        .then(stream => {

          getMediaSuccess(stream)

        })

        .catch(e => {

          getMediaFail(e)

        })

    } else if (navigator.getUserMedia) {

      navigator.getUserMedia(

        {

          audio: {

            volume: 1.0,

          },

          video: false,

        },

        stream => {

          getMediaSuccess(stream)

        },

        function(e) {

          getMediaFail(e)

        }

      )

    } else {

      if (navigator.userAgent.toLowerCase().match(/chrome/) && location.origin.indexOf('https://') < 0) {

        alert('chrome下获取浏览器录音功能,因为安全性问题,需要在localhost或127.0.0.1或https下才能获取权限')

      } else {

        alert('无法获取浏览器录音功能,请升级浏览器或使用chrome')

      }

      this.audioContext && this.audioContext.close()

      return

    }

    // 获取浏览器录音权限成功的回调

    let getMediaSuccess = stream => {

      // 创建一个用于通过JavaScript直接处理音频

      this.scriptProcessor = this.audioContext.createScriptProcessor(0, 1, 1)

      this.scriptProcessor.onaudioprocess = e => {

        // 去处理音频数据

        getPCMarrayBuffer.push(e.inputBuffer.getChannelData(0).slice(0))

      }

      // 创建一个新的MediaStreamAudioSourceNode 对象,使来自MediaStream的音频可以被播放和操作

      this.mediaSource = this.audioContext.createMediaStreamSource(stream)

      // 连接

      this.mediaSource.connect(this.scriptProcessor)

      this.scriptProcessor.connect(this.audioContext.destination)

    }

    let getMediaFail = (e) => {

      alert('请求录音权限失败,打开权限再试~')

      this.audioContext && this.audioContext.close()

      this.audioContext = undefined

    }

  }

 二 新建lamejs,并引入;下载方式

npm install lamejs

import lamejs, { Mp3Enc } from 'lamejs'

/**

 * 音频转换

 */

export class AudioConvert {

  /**

   * 录音获得的 Float32Array 的数组转换成 Mp3 格式的 Blob 对象

   * @param data

   */

  static float32ArrayToMp3(data: Float32Array[]): Blob {

    const audioData = AudioConvert.mergeArray(data)

    const int16Buffer = AudioConvert.floatArray2Int16(audioData)

    return AudioConvert.encodeMono(1, 44100, int16Buffer)

  }

  /**

   * 合并单个声道的多个片段

   * @param list

   */

  private static mergeArray(list: Float32Array[]) {

    const length = list.length * list[0].length

    let data = new Float32Array(length)

    let offset = 0

    for (let i = 0; i < list.length; i++) {

      console.log(i)

      data.set(list[i], offset)

      offset += list[i].length

    }

    return data

  }

  private static floatArray2Int16(floatBuffer: Float32Array) {

    const int16Buffer = new Int16Array(floatBuffer.length)

    for (let i = 0, len = floatBuffer.length; i < len; i++) {

      if (floatBuffer[i] < 0) {

        int16Buffer[i] = 0x8000 * floatBuffer[i]

      } else {

        int16Buffer[i] = 0x7fff * floatBuffer[i]

      }

    }

    return int16Buffer

  }

  private static encodeMono(channels: number, sampleRate: number, samples: Int16Array) {

    const buffer = []

    const mp3enc: Mp3Enc = new lamejs.Mp3Encoder(channels, sampleRate, 128)

    let remaining = samples.length

    const maxSamples = 1152

    for (let i = 0; remaining >= maxSamples; i += maxSamples) {

      const mono = samples.subarray(i, i + maxSamples)

      const mp3buf = mp3enc.encodeBuffer(mono)

      if (mp3buf.length > 0) {

        buffer.push(new Int8Array(mp3buf))

      }

      remaining -= maxSamples

    }

    const d = mp3enc.flush()

    if (d.length > 0) {

      buffer.push(new Int8Array(d))

    }

    // console.log('done encoding, size=', buffer.length)

    return new Blob(buffer, { type: 'audio/mp3' })

  }

}

三 调用float32ArrayToMp3方法,录音获得的 Float32Array 的数组转换成 Mp3 格式的 Blob 对象;并播放

let blob = float32ArrayToMp3(getPCMarrayBuffer);

  let blobUrl2 = window.URL.createObjectURL(blob)

  document.getElementById("audio").src = blobUrl2;

  setTimeout(()=>{

    document.getElementById("audio").play()

  },100)

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值