Record your skills, share your skills, be a great porter.
Framework to choose
The development of wechat small program, using unapp. Why do I choose this one? Because it is relatively mature. I have used MPvue before, and Kbone is particularly immature. Later, UNIAPP was selected through various types of selection.
Problems encountered
- Recording authorization.
- Long press the tape to see if your finger marks the long press area
- File upload.
- Multi-record voice playback.
Initialization work
- Define global recording objects and audio objects, and format your desired audio format
const recorderManager = uni.getRecorderManager(); // Create a recording object
const audioContext = wx.createInnerAudioContext(); // Create the audio object
const options = {
duration: 600000.// Specifies the recording duration, in ms. The maximum value is 10 minutes (600000) and the default value is 1 minute (60000).
sampleRate: 16000./ / sampling rate
numberOfChannels: 1.// Number of recording channels
encodeBitRate: 96000.// Code rate
format: 'mp3'.// Audio format, valid value aAC /mp3, etc
frameSize: 50 // Specify the frame size, in KB
};
Copy the code
The recording authorization
Recording collection is mainly considered from two aspects
- The user who applies for authorization directly agrees to authorize the user
- After the user rejects authorization, the Settings are opened and the user receives authorization.
uni.authorize({
scope: 'scope.record'.success() {
// The user has authorized the recording
},
fail() {
// User authorization fails. You need to open the Settings to manually authorize the user. In some cases openSetting does not open
// The Settings can be opened by popover user via fail.
uni.openSetting({
success: res= > {
// Popup prompt without authorization
if(! res.authSetting['scope.record']) {
// Recording authorization is not configured
uni.showModal({
title: 'tip'.content: 'You are not authorized to record, the function will not be used'.showCancel: false
});
} else {
// Only the second time
// The user has authorized the recording}},fail: function() {
uni.showModal({
title: 'tip'.content: 'You are not authorized to record, the function will not be used'.showCancel: false.success: function(res) { uni.openSetting(); }}); }}); }});Copy the code
Official API link
Interface adjustment link
Long press record/slide area/stop long press
Methods in uniapp
Longpress @longpress (finger touch exceeds 350ms) @longtap longpress @tap click @touchcancel finger touch is interrupted, such as incoming phone alert, popup window @touchend finger touch action ends, For example, release the button @touchMove after finger touch and move @touchStart finger touch action beginsCopy the code
Recording operation
- Gets the distance from the top of the currently clicked element
- While holding down the press, start the timer and record the voice when authorized.
// The distance from the current clicked element is different in the applet. Here's how to get it
const query = uni.createSelectorQuery().in(this);
query
.select('.record-button')
.boundingClientRect(data= > {
// data Specifies information about the current element
})
.exec();
Copy the code
- Obtain current information through event
- Slide out of time to stop recording, and to clear the timer.
- Keep recording as you slide back. Keep the timer going.
- An intermediate state is required to continue recording and stop recording by listening
let touches = e.touches[0];
// When it is exceeded
if (touches.pageY < this.reocrdLocation.top) {
clearInterval(this.timerInfo);
recorderManager.pause();
} else {
recorderManager.resume();
}
Copy the code
Stop by long
- If the recording length is too short, do not upload it.
- If the conditions are met, upload, clear the timer, and stop recording
recorderManager.stop();
// Listen stop event
recorderManager.onStop(res= > {
if (this.duration < 1) {
uni.showToast({
title: 'Recording time is too short'.duration: 1000.icon: 'none'
});
return;
}
// If it meets the criteria, advance the array.
this.voiceList.push({
size: res.fileSize, // Local progress
progress: -1.//-1 does not upload, -100 fails to upload, 100 succeeds, 0-100 is uploaded
path: res.tempFilePath, // Line path
duration: this.duration // Recording duration
});
// Check the upload
this.checkUploadVoice();
});
clearInterval(this.timerInfo);
Copy the code
File upload
- You can set the status of each recording to record each status (-1 no upload, -100 upload failure, 100 upload success, 0-100 upload in progress).
- If the upload fails, you can upload again. So before uploading the file, check the file (check each state).
let obj;
for (let i = 0; i < this.voiceList.length; i++) {
let item = this.voiceList[i];
if (item.progress == -1 || item.progress == -100) {
obj = await this.uploadFiles(item, i); // Wait until the file is uploaded to get the information
// Modify the speech array through set
this.$set(this.voiceList, i, {
name: item.name,
size: item.size,
progress: obj.progress,
path: obj.path, //
duration: item.duration,
nowPlay: false.text: ' '.translateStatus: false.// Whether the record is converted to text
});
this.duration = 0; // After the file is uploaded, the time record must be clear 0}}// Upload the file
uploadFiles(item, i) {
return new Promise((resolve, reject) = > {
const uploadTask = uni.uploadFile({
url: url, // The address to upload the image
filePath: item.path, // Get the address after recording
name: 'file'.header: {
'Content-Type': 'multipart/form-data'.accept: 'application/json'
},
success: upRes= > {
console.log(upRes);
let dataInfo = JSON.parse(upRes.data);
let { code, data } = dataInfo;
Success message is returned after success
resolve({
path: data.fileUrl,
progress: 100
});
},
fail: function(err) {
// Upload failed to record the status
resolve({
path: ' '.progress: -100}); }}); uploadTask.onProgressUpdate(res= > {
// Get the upload progress here and display it in real time
this.$set(this.voiceList, {
name: item.name,
size: item.size,
progress: res.progress,
path: item.path,
duration: item.duration
});
// console.log(' upload progress ', res.progress);
// console.log(' Length of data uploaded ', res.totalBytessent);
// console.log(
// 'Total length of data expected to upload ',
// res.totalBytesExpectedToSend
// );
});
});
},
Copy the code
Multiple Recording Playback
- Keep only one active while playing (main problem)
- Stop any other voice that is playing
- Plays the currently clicked voice
// Play voice
async playVoice(item, index) {
uni.showLoading({
title: 'Recording playback loading'
});
// Click the current voice twice at the same time, you need to stop the previous one to play the new one
if (item.nowPlay && this.nowPlayItem.nowPlay) {
this.stopVoice(item);
return;
}
// The two voices are not the same. Stop the previous one, change the playing state, and play the current one
if(! item.nowPlay &&this.nowPlayItem.nowPlay) {
let status = await this.stopVoice(item);
let obj = Object.assign({}, this.nowPlayItem.item, {
nowPlay: false
});
NowPlayItem: {index: -1, // index is the index value of the current play. nowPlay: False, // Whether a voice is currently being played item: null}, */
this.$set(this.voiceList, this.nowPlayItem.index, obj);
}
audioContext.src = item.path; // Address of the recording to be played
audioContext.play();
this.nowPlayItem.index = index;
this.nowPlayItem.item = item;
// Start listening
audioContext.onPlay(res= > {
uni.hideLoading();
console.log('play');
item.nowPlay = true;
this.nowPlayItem.nowPlay = true;
});
// Stop playback listener (whether the current playback is stopped)
audioContext.onPause(res= > {
console.log('pause');
item.nowPlay = false;
this.nowPlayItem.nowPlay = false;
// Listen on audio and cancel listen on audio
audioContext.offPlay();
audioContext.offPause();
audioContext.offStop();
audioContext.offEnded();
});
// Listen to the audio playback to the end of the event, real machine debugging will have a problem, wechat developer tools will not have a problem
audioContext.onEnded(res= > {
console.log('ended');
item.nowPlay = false;
this.nowPlayItem.nowPlay = false;
// Listen on audio and cancel listen on audio
audioContext.offPlay();
audioContext.offPause();
audioContext.offStop();
audioContext.offEnded();
});
audioContext.onError(res= > {
console.log('error');
// Failed to play audio callback
console.log(res);
});
},
// The next playback starts only when the current playback stops
stopVoice(item) {
return new Promise((resolve, reject) = > {
audioContext.stop();
audioContext.onStop(res= > {
// Failed to play audio callback
this.nowPlayItem.nowPlay = false;
if (item) {
item.nowPlay = false;
}
audioContext.offPlay();
audioContext.offPause();
audioContext.offStop();
audioContext.offEnded();
resolve(true);
});
});
},
Copy the code
This is where things go wrong
- The audio listen event should exist at the same time as the cancel event
- When changing the voice playing status, you must wait until the previous link stops before performing subsequent operations
conclusion
- There’s a big difference between the simulator and the real machine, where events are slower than the real one.
- Long is the art of learning, but persevere.
This article mainly records the problems encountered in the development, encountered what problems, what mistakes, welcome to comment on oh.