vue前端獲取/切換麥克風(fēng)、播放采集音頻和采集音量大小完整代碼
一、前言
使用時(shí)確保你有如下依賴且版本為Vue2,終端里面運(yùn)行
npm install element-ui npm install recordrtc npm install sass sass-loader
二、案列圖示


三、代碼
1、獲取麥克風(fēng)列表
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
var Mic = []
// 彈框獲取麥克風(fēng)
navigator.mediaDevices.getUserMedia({audio: true}).then((stream) => {
navigator.mediaDevices.enumerateDevices().then(function (devices) {
devices.forEach(function (device) {
if(device.kind === 'audioinput'){ // 麥克風(fēng)
if(device.deviceId != 'default' && device.deviceId != 'communications'){
that.Mic.push(device)
}
}
});
})
// 只是為了獲取麥克風(fēng)權(quán)限,獲取以后立馬關(guān)閉
stream.getTracks().forEach(track => track.stop());
})
}
2、用戶在麥克風(fēng)列表里面選擇一個(gè)麥克風(fēng)
<el-form
style="padding: 0 80px"
ref="mainFormRef"
:model="main_form"
label-width="100px"
:rules="rules"
>
<el-form-item label="聲紋采集:" prop="file">
<el-select :disabled="voiceStatus" style="width: 200px;" v-model="main_form.chooseMicDeviceId" placeholder="請(qǐng)選擇麥克風(fēng)">
<el-option
v-for="item in Mic"
:key="item.deviceId"
:label="item.label"
:value="item.deviceId">
</el-option>
</el-select>
<div class="voiceGather" v-if="main_form.chooseMicDeviceId != ''">
<el-button style="margin-top: 20px;" @click="voiceInput">{{ voiceStatus ? '取消錄音' : '開始錄音' }}</el-button>
<!-- 正在錄制 -->
<template v-if="voiceStatus">
<div class="bo">
<div v-for="(item, index) in RMSList" :key="index" :style="{height: item / 100 * 40 + 'px'}" class="RMS"></div>
</div>
</template>
</div>
</el-form-item>
</el-form>
3、選取了麥克風(fēng)以后使用當(dāng)前麥克風(fēng)錄音
重要代碼:audio: { deviceId: this.form.chooseMicDeviceId },將上面選的麥克風(fēng)放到getUserMedia中,即可啟用用戶自己選擇的麥克風(fēng)
// 開始錄音
startRecord(){
var that = this
this.voiceStatus = true
// mediaDevices可提供對(duì)相機(jī)和麥克風(fēng)等媒體輸入設(shè)備的連接訪問
window.navigator.mediaDevices.getUserMedia(
{ audio: { deviceId: this.main_form.chooseMicDeviceId }}
).then((stream) => {
this.stream = stream;
this.getVoice()
this.recorder = RecordRTC(stream, {
type: 'audio',
mimeType: 'audio/wav',
recorderType: RecordRTC.StereoAudioRecorder,
desiredSampRate: 16000,
numberOfAudioChannels: 1, // 單聲道
timeSlice: 30000,
// bufferSize: 4096, // 緩存大小
ondataavailable: this.sendData,
});
this.recorder.startRecording();
}).catch(function(err) {
console.log(err);
console.log('當(dāng)前瀏覽器不支持開啟麥克風(fēng)!');
that.voiceStatus = false
});
},
在sendData中可以把數(shù)據(jù)流傳給后端,可以播放/下載采集到的數(shù)據(jù)流,也可以將數(shù)據(jù)流轉(zhuǎn)換成file傳給后端
sendData(blob) {
var BB =new Blob([blob], {'type': 'audio/wav; codecs=opus'})
// var audioURL = window.URL.createObjectURL(BB)
// 播放
// const audio = document.createElement('audio')
// audio.controls = true // 音頻是否顯示控件
// audio.src = audioURL
// audio.play()
// 下載
// let a = document.createElement("a");
// a.href = audioURL;
// a.download = '測(cè)試';
// a.click();
// // 釋放這個(gè)臨時(shí)的對(duì)象url
// window.URL.revokeObjectURL(audioURL);
let file = new window.File([BB], '測(cè)試.wav')
console.log(file);
},
4、獲取采集的音頻音量大小
// 獲取音量值大小
getVoice() {
const audioContext = new (window.AudioContext || window.webkitAudioContext)()
// 將麥克風(fēng)的聲音輸入這個(gè)對(duì)象
const mediaStreamSource = audioContext.createMediaStreamSource(this.stream)
// 創(chuàng)建分析節(jié)點(diǎn)
const analyserNode = audioContext.createAnalyser()
// 連接節(jié)點(diǎn)
mediaStreamSource.connect(analyserNode)
// 可以實(shí)時(shí)聽到麥克風(fēng)采集的聲音
// analyserNode.connect(audioContext.destination)
// 獲取音量數(shù)據(jù)
const dataArray = new Uint8Array(analyserNode.frequencyBinCount);
function getVolume() {
analyserNode.getByteFrequencyData(dataArray);
let sum = 0;
for (let i = 0; i < dataArray.length; i++) {
sum += dataArray[i];
}
// 計(jì)算平均音量
const averageVolume = sum / dataArray.length;
return averageVolume;
}
// 每隔一段時(shí)間獲取一次音量
this.timer1 = setInterval(() => {
const volume = getVolume();
console.log('音量:', Math.round( volume ));
// 在這里可以根據(jù)需要進(jìn)行相應(yīng)的處理
}, 100);
},
四、全部代碼
<template>
<div class="Page">
<el-form
style="padding: 0 80px"
ref="mainFormRef"
:model="main_form"
label-width="100px"
:rules="rules"
>
<el-form-item label="聲紋采集:" prop="file">
<el-select :disabled="voiceStatus" style="width: 200px;" v-model="main_form.chooseMicDeviceId" placeholder="請(qǐng)選擇麥克風(fēng)">
<el-option
v-for="item in Mic"
:key="item.deviceId"
:label="item.label"
:value="item.deviceId">
</el-option>
</el-select>
<div class="voiceGather" v-if="main_form.chooseMicDeviceId != ''">
<el-button style="margin-top: 20px;" @click="voiceInput">{{ voiceStatus ? '取消錄音' : '開始錄音' }}</el-button>
<!-- 正在錄制 -->
<template v-if="voiceStatus">
<div class="bo">
<div v-for="(item, index) in RMSList" :key="index" :style="{height: item / 100 * 40 + 'px'}" class="RMS"></div>
</div>
</template>
</div>
</el-form-item>
</el-form>
</div>
</template>
<script>
import RecordRTC from 'recordrtc'
export default {
data() {
return {
recorder: '',
voiceStatus: false, // 是否正在錄音
main_form: {
chooseMicDeviceId: '', // 選擇的麥克風(fēng)id
},
Mic: [], // 可選擇的麥克風(fēng)
rules: {
file: [
{ required: true, message: "不能為空", trigger: "blur" },
],
},
};
},
created() {},
mounted() {
this.getMic()
},
methods: {
// 獲取當(dāng)前頁面可以選擇的麥克風(fēng)
getMic(){
let that = this;
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
// 彈框獲取麥克風(fēng)
navigator.mediaDevices.getUserMedia({audio: true}).then((stream) => {
navigator.mediaDevices.enumerateDevices().then(function (devices) {
devices.forEach(function (device) {
console.log(devices);
if(device.kind === 'audioinput'){ // 麥克風(fēng)
if(device.deviceId != 'default' && device.deviceId != 'communications'){
that.Mic.push(device)
}
}
});
})
stream.getTracks().forEach(track => track.stop());
})
}
},
// 語音輸入
voiceInput(){
// 正在語音輸入
if(this.voiceStatus) {
this.stopRecord() // 停止輸入
} else { // 開啟語音輸入
this.startRecord()
}
},
// 開始錄音
startRecord(){
var that = this
this.voiceStatus = true
// mediaDevices可提供對(duì)相機(jī)和麥克風(fēng)等媒體輸入設(shè)備的連接訪問
window.navigator.mediaDevices.getUserMedia(
{ audio: { deviceId: this.main_form.chooseMicDeviceId }}
).then((stream) => {
this.stream = stream;
this.getVoice()
this.recorder = RecordRTC(stream, {
type: 'audio',
mimeType: 'audio/wav',
recorderType: RecordRTC.StereoAudioRecorder,
desiredSampRate: 16000,
numberOfAudioChannels: 1, // 單聲道
timeSlice: 1000,
// bufferSize: 4096, // 緩存大小
ondataavailable: this.sendData,
});
this.recorder.startRecording();
}).catch(function(err) {
console.log(err);
console.log('當(dāng)前瀏覽器不支持開啟麥克風(fēng)!');
that.voiceStatus = false
});
},
// 結(jié)束錄音
stopRecord(){
this.voiceStatus = false
if (this.recorder != null) {
let recorder = this.recorder
recorder.stopRecording();
let stream = this.stream;
clearInterval(this.timer1);
stream.getAudioTracks().forEach(track => track.stop());
}
},
// 獲取音量值大小
getVoice() {
const audioContext = new (window.AudioContext || window.webkitAudioContext)()
// 將麥克風(fēng)的聲音輸入這個(gè)對(duì)象
const mediaStreamSource = audioContext.createMediaStreamSource(this.stream)
// 創(chuàng)建分析節(jié)點(diǎn)
const analyserNode = audioContext.createAnalyser()
// 連接節(jié)點(diǎn)
mediaStreamSource.connect(analyserNode)
// 可以實(shí)時(shí)聽到麥克風(fēng)采集的聲音
// analyserNode.connect(audioContext.destination)
// 獲取音量數(shù)據(jù)
const dataArray = new Uint8Array(analyserNode.frequencyBinCount);
function getVolume() {
analyserNode.getByteFrequencyData(dataArray);
let sum = 0;
for (let i = 0; i < dataArray.length; i++) {
sum += dataArray[i];
}
// 計(jì)算平均音量
const averageVolume = sum / dataArray.length;
return averageVolume;
}
// 每隔一段時(shí)間獲取一次音量
this.timer1 = setInterval(() => {
const volume = getVolume();
console.log('音量:', Math.round( volume ));
// 在這里可以根據(jù)需要進(jìn)行相應(yīng)的處理
}, 100);
},
// 每timeSlice執(zhí)行一次
sendData(blob) {
var BB = new Blob([blob], {'type': 'audio/wav; codecs=opus'})
// var audioURL = window.URL.createObjectURL(BB)
// 播放
// const audio = document.createElement('audio')
// audio.controls = true // 音頻是否顯示控件
// audio.src = audioURL
// audio.play()
// 下載
// let a = document.createElement("a");
// a.href = audioURL;
// a.download = '測(cè)試';
// a.click();
// // 釋放這個(gè)臨時(shí)的對(duì)象url
// window.URL.revokeObjectURL(audioURL);
let file = new window.File([BB], '測(cè)試.wav')
console.log(file);
},
},
};
</script>
<style lang="scss" scoped>
.Page{
padding: 20px;
}
</style>總結(jié)
到此這篇關(guān)于vue前端獲取/切換麥克風(fēng)、播放采集音頻和采集音量大小的文章就介紹到這了,更多相關(guān)vue獲取麥克風(fēng)播放采集音頻和音量大小內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue-Jest 自動(dòng)化測(cè)試基礎(chǔ)配置詳解
目前開發(fā)大型應(yīng)用,測(cè)試是一個(gè)非常重要的環(huán)節(jié),而在 Vue 項(xiàng)目中做單元測(cè)試可以用 Jest,本文主要介紹了Vue-Jest 自動(dòng)化測(cè)試,感興趣的可以了解一下2021-07-07
vue-cli中devServer.proxy相關(guān)配置項(xiàng)的使用
這篇文章主要介紹了vue-cli中devServer.proxy相關(guān)配置項(xiàng)的使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
Vue實(shí)現(xiàn)Hover功能(mouseover與mouseenter的區(qū)別及說明)
這篇文章主要介紹了Vue實(shí)現(xiàn)Hover功能(mouseover與mouseenter的區(qū)別及說明),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
vue如何動(dòng)態(tài)獲取當(dāng)前時(shí)間
這篇文章主要介紹了vue如何動(dòng)態(tài)獲取當(dāng)前時(shí)間問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
Vue響應(yīng)式原理深入解析及注意事項(xiàng)
Vue 最顯著的一個(gè)功能是響應(yīng)系統(tǒng) —— 模型只是普通對(duì)象,修改它則更新視圖。下面這篇文章主要給大家深入講解了關(guān)于Vue的響應(yīng)式原理,以及Vue響應(yīng)式的一些注意事項(xiàng),需要的朋友下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-12-12
vue實(shí)現(xiàn)某元素吸頂或固定位置顯示(監(jiān)聽滾動(dòng)事件)
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)某元素吸頂或固定位置顯示,監(jiān)聽滾動(dòng)事件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12

