柚子快報(bào)邀請(qǐng)碼778899分享:微信小程序?qū)崿F(xiàn)錄音及播放功能
柚子快報(bào)邀請(qǐng)碼778899分享:微信小程序?qū)崿F(xiàn)錄音及播放功能
使用的是: RecorderManager 全局唯一的錄音管理器 和 InnerAudioContext 實(shí)例
以下為實(shí)現(xiàn)代碼:
WXML
JS(其中 msToTime 秒數(shù)轉(zhuǎn)換成時(shí)間方法, uploadWx 簡(jiǎn)單封裝微信請(qǐng)求, 方法寫(xiě)在最后
data: {
// 全局唯一的錄音管理器
recorderManager: null,
recorderType: '0', // 0-開(kāi)始錄音 1-停止錄音
// recorderCount: 60, // 剩余秒數(shù)
recorderCount: '00:00', // 已經(jīng)錄制秒數(shù)
recCount: 0, // 已經(jīng)錄制秒數(shù)
timer: null,
soundRecordPath: '', // 錄音資源
// 播放器
innerAudioContext: null,
audioCurrentLength: 0,
audioLength: "00:00",
duration: 0, //音頻時(shí)長(zhǎng)
audioType: "4", //3-開(kāi)始播放 4-暫停播放
},
//定時(shí)器方法
audioTimer() {
let that = this
let { recCount } = this.data
that.data.timer = setInterval(function () {
if (++recCount == 600) {
clearInterval(that.data.timer);
that.stop();
that.setData({ recCount: 0, recorderCount: "00:00", recorderType: "2" })
} else {
console.log(recCount, msToTime(recCount * 1000));
that.setData({ recorderCount: msToTime(recCount * 1000) })
}
}, 1000)
// that.data.timer = setInterval(function () {
// console.log(recorderCount);
// if (--recorderCount == 0) {
// clearInterval(that.data.timer);
// that.stop();
// that.setData({ recorderCount: 600, recorderType: "2" })
// } else {
// that.setData({ recorderCount: recorderCount })
// }
// }, 1000)
},
// 開(kāi)始錄音
playRecord(e) {
let { type } = e.currentTarget.dataset
if (type == '3' || type == '4') {
this.setData({ audioType: type })
} else if (type == 2) {
// 停止錄音操作
this.stop();
} else {
this.setData({ recorderType: type })
}
if (type == '1') {
// 開(kāi)始錄音操作
this.start();
} else if (type == '0') {
//重新錄制操作
this.setData({ soundRecordPath: "", audioCurrentLength: 0, audioType: '4', duration: 0 })
this.audioPause() // 暫停
this.audioDestroy() // 釋放音頻資源
this.stop();
} else if (type == '3') {
// 播放音頻操作
this.audioPlay();
} else if (type == '4') {
// 暫停音頻操作
this.audioPause();
}
},
// 錄音start
start() {
const options = {
duration: 600000,
sampleRate: 44100,
numberOfChannels: 1,
encodeBitRate: 192000,
format: 'mp3',
frameSize: 50
}
this.data.recorderManager.start(options)
this.data.recorderManager.onStart(() => {
this.audioTimer();
wx.showToast({ title: '錄音開(kāi)始', icon: 'none' });
console.log('錄音開(kāi)始')
})
},
// 錄音stop
stop() {
let that = this
this.data.recorderManager.stop();
this.data.recorderManager.onStop((res) => {
clearInterval(that.data.timer);
console.log('recorder stop', res)
const { tempFilePath, duration } = res
console.log(tempFilePath, duration, 'duration');
that.setData({ audioLength: msToTime(duration), duration: duration })
wx.showLoading({
title: '上傳中',
})
uploadWx(tempFilePath).then(response => {
if (response.statusCode == 200 && JSON.parse(response.data).code == 200) { //相當(dāng)于success回調(diào)
let resp = JSON.parse(response.data)
if (resp.code == 200) {
console.log(resp, 'resp');
that.setData({ soundRecordPath: resp.url, recorderType: '2', recCount: 0, recorderCount: "00:00", duration: duration });
that.playRecorder(resp.url)
wx.showToast({ title: '上傳成功' });
} else {
that.uploadError();
}
wx.hideLoading();
} else {
wx.hideLoading();
that.uploadError();
}
}).catch(() => {
wx.hideLoading();
that.uploadError();
})
})
},
uploadError(){
this.setData({ soundRecordPath: "", recorderType: '0', duration: 0, recCount: 0, recorderCount: "00:00", duration: duration });
wx.showToast({
title: "上傳失敗,請(qǐng)重新錄制",
icon: 'none',
duration: 2000
})
},
// 錄音器
getRecorder() {
const recorderManager = wx.getRecorderManager()
recorderManager.onPause(() => {
console.log('recorder pause')
})
recorderManager.onFrameRecorded((res) => {
const { frameBuffer } = res
console.log('frameBuffer.byteLength', frameBuffer.byteLength)
})
this.setData({ recorderManager: recorderManager });
},
// 播放器
playRecorder(url) {
const innerAudioContext = wx.createInnerAudioContext({
useWebAudioImplement: false // 是否使用 WebAudio 作為底層音頻驅(qū)動(dòng),默認(rèn)關(guān)閉。對(duì)于短音頻、播放頻繁的音頻建議開(kāi)啟此選項(xiàng),開(kāi)啟后將獲得更優(yōu)的性能表現(xiàn)。由于開(kāi)啟此選項(xiàng)后也會(huì)帶來(lái)一定的內(nèi)存增長(zhǎng),因此對(duì)于長(zhǎng)音頻建議關(guān)閉此選項(xiàng)
})
let that = this
this.setData({ innerAudioContext: innerAudioContext })
this.data.innerAudioContext.src = url
this.data.innerAudioContext.onTimeUpdate(() => {
let prop = (this.data.innerAudioContext.currentTime / (that.data.duration / 1000)) * 100
console.log(prop, this.data.innerAudioContext.currentTime, that.data.duration);
that.setData({ audioCurrentLength: prop })
})
this.data.innerAudioContext.onEnded(() => {
console.log('自然結(jié)束了');
that.setData({ audioCurrentLength: 0, audioType: '4' })
})
},
// 播放play
audioPlay() {
this.data.innerAudioContext.play() // 播放
},
// 暫停pause
audioPause() {
this.data.innerAudioContext.pause() // 暫停
},
// 播放stop
audioDestroy() {
this.data.innerAudioContext.destroy() // 釋放
},
/**
* 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面加載
*/
onLoad(options) {
this.getRecorder();
},
/**
* 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面卸載
*/
onUnload() {
if (this.data.innerAudioContext) {
this.audioPause() // 暫停
this.audioDestroy() // 釋放音頻資源
}
},
WXSS
/* -------------語(yǔ)音音階------------- */
.auditBox {
height: 20px;
display: flex;
align-items: center;
justify-content: space-between;
}
.auditBox .auditItem {
display: block;
background: #333333;
width: 1px;
height: 10%;
margin-right: 2.5px;
float: left;
}
.auditBox .auditItem:last-child {
margin-right: 0px;
}
.auditBox .auditItem:nth-child(1) {
animation: load 2.5s 3.0s infinite linear;
}
.auditBox .auditItem:nth-child(2) {
animation: load 2.5s 2.8s infinite linear;
}
.auditBox .auditItem:nth-child(3) {
animation: load 2.5s 2.6s infinite linear;
}
.auditBox .auditItem:nth-child(4) {
animation: load 2.5s 2.4s infinite linear;
}
.auditBox .auditItem:nth-child(5) {
animation: load 2.5s 2.2s infinite linear;
}
.auditBox .auditItem:nth-child(6) {
animation: load 2.5s 2.0s infinite linear;
}
.auditBox .auditItem:nth-child(7) {
animation: load 2.5s 1.8s infinite linear;
}
.auditBox .auditItem:nth-child(8) {
animation: load 2.5s 1.6s infinite linear;
}
.auditBox .auditItem:nth-child(9) {
animation: load 2.5s 1.4s infinite linear;
}
.auditBox .auditItem:nth-child(10) {
animation: load 2.5s 1.2s infinite linear;
}
.auditBox .auditItem:nth-child(11) {
animation: load 2.5s 1s infinite linear;
}
.auditBox .auditItem:nth-child(12) {
animation: load 2.5s 0.8s infinite linear;
}
.auditBox .auditItem:nth-child(13) {
animation: load 2.5s 0.6s infinite linear;
}
.auditBox .auditItem:nth-child(14) {
animation: load 2.5s 0.4s infinite linear;
}
.auditBox .auditItem:nth-child(15) {
animation: load 2.5s 0.2s infinite linear;
}
.auditBox .auditItem:nth-child(16) {
animation: load 2.5s 0s infinite linear;
}
.auditBox .auditItem:nth-child(17) {
animation: load 2.5s 0.2s infinite linear;
}
.auditBox .auditItem:nth-child(18) {
animation: load 2.5s 0.4s infinite linear;
}
.auditBox .auditItem:nth-child(19) {
animation: load 2.5s 0.6s infinite linear;
}
.auditBox .auditItem:nth-child(20) {
animation: load 2.5s 0.8s infinite linear;
}
.auditBox .auditItem:nth-child(21) {
animation: load 2.5s 1s infinite linear;
}
.auditBox .auditItem:nth-child(22) {
animation: load 2.5s 1.2s infinite linear;
}
.auditBox .auditItem:nth-child(23) {
animation: load 2.5s 1.4s infinite linear;
}
.auditBox .auditItem:nth-child(24) {
animation: load 2.5s 1.6s infinite linear;
}
.auditBox .auditItem:nth-child(25) {
animation: load 2.5s 1.8s infinite linear;
}
.auditBox .auditItem:nth-child(26) {
animation: load 2.5s 2.0s infinite linear;
}
.auditBox .auditItem:nth-child(27) {
animation: load 2.5s 2.2s infinite linear;
}
.auditBox .auditItem:nth-child(28) {
animation: load 2.5s 2.4s infinite linear;
}
.auditBox .auditItem:nth-child(29) {
animation: load 2.5s 2.6s infinite linear;
}
.auditBox .auditItem:nth-child(30) {
animation: load 2.5s 2.8s infinite linear;
}
.auditBox .auditItem:nth-child(31) {
animation: load 2.5s 3.0s infinite linear;
}
@keyframes load {
0% {
height: 10%;
}
25% {
height: 100%;
}
50% {
height: 20%;
}
75% {
height: 100%;
}
100% {
height: 10%;
}
}
方法
// msToTime
export const msToTime = (duration) => {
var milliseconds = parseInt((duration % 1000) / 100)
, seconds = parseInt((duration / 1000) % 60)
, minutes = parseInt((duration / (1000 * 60)) % 60);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
return minutes + ":" + seconds;
}
// uploadWx
export const uploadWx = (tempFilePath) => {
return wxp.uploadFile({
url: 'yourApi',
filePath: tempFilePath,
name: 'file',
formData: {
file: tempFilePath,
},
header: {
'Content-Type': 'multipart/form-data',
// token: wx.getStorageSync('token'), // 看后臺(tái)需要哪種 header
Authorization: "Bearer " + wx.getStorageSync('token'),
}
})
}
柚子快報(bào)邀請(qǐng)碼778899分享:微信小程序?qū)崿F(xiàn)錄音及播放功能
精彩鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。