一 原生拉起录音授权,实时获取音频的返回的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)