新增录音回答功能

This commit is contained in:
chenyuanfang
2024-12-18 19:00:40 +08:00
parent 1514cc6d92
commit 8c7e04a024
3 changed files with 106 additions and 1 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

+106 -1
View File
@@ -20,6 +20,30 @@
rows="6"
class="custom-textarea"
/>
<div class="record-group">
<van-button
type="info"
@click="startRecording"
:disabled="isRecording"
> <img style="width: 18px" :src="require('@/assets/images/microphone.png')" />{{ isRecording ? "录音中..." : "录音回答" }}</van-button
>
<van-button
icon="stop"
type="info"
@click="stopRecording"
:disabled="!isRecording"
>停止录音</van-button
>
<van-button
v-if="audioUrl"
icon="volume-o"
type="info"
@click="playRecording"
:disabled="isPlaying"
>播放录音</van-button
>
</div>
<van-button
class="next-button"
:type="isLastQuestion ? 'success' : 'primary'"
@@ -56,6 +80,11 @@ export default {
return {
answer: "",
isSpeaking: false, // 用于跟踪语音播放状态
isRecording: false, // 用于跟踪录音状态
isPlaying: false, // 用于跟踪播放状态
mediaRecorder: null, // 用于存储MediaRecorder实例
audioChunks: [], // 用于存储录音数据
audioUrl: null, // 用于存储录音文件的URL
};
},
computed: {
@@ -90,8 +119,53 @@ export default {
this.isSpeaking = false;
}
},
startRecording() {
if (!this.isRecording) {
this.isRecording = true;
navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {
const mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = (e) => {
this.audioChunks.push(e.data);
};
mediaRecorder.onstop = () => {
this.isRecording = false;
const audioBlob = new Blob(this.audioChunks, {
type: "audio/ogg; codecs=opus",
});
this.audioUrl = URL.createObjectURL(audioBlob); // 创建录音文件的URL
this.audioChunks = []; // 清空录音数据
// 这里可以添加上传逻辑
this.uploadAudio(audioBlob);
};
this.mediaRecorder = mediaRecorder; // 存储MediaRecorder实例
mediaRecorder.start();
});
}
},
stopRecording() {
if (this.isRecording && this.mediaRecorder) {
this.mediaRecorder.stop();
}
},
playRecording() {
if (this.audioUrl && !this.isPlaying) {
this.isPlaying = true;
const audio = new Audio(this.audioUrl);
audio.onended = () => {
this.isPlaying = false;
};
audio.play();
}
},
getMediaRecorder() {
return this.$el.querySelector("media-recorder");
},
uploadAudio(audioBlob) {
// 这里添加上传逻辑,例如使用fetch或axios上传到服务器
console.log("Uploading audio:", audioBlob);
},
nextQuestion() {
this.stopQuestion();
this.stopQuestion();
this.onNext({ questionId: this.questionObj.id, answer: this.answer });
},
},
@@ -99,6 +173,36 @@ export default {
</script>
<style scoped>
.record-group {
display: flex;
flex-direction: column;
align-items: center; /* 水平居中 */
justify-content: center; /* 垂直居中 */
}
.record-group .van-button {
margin: 10px;
color: white;
border-radius: 20px;
transition: background-color 0.3s;
}
.record-group .van-button:first-child {
background-color: #4CAF50;
}
.record-group .van-button:nth-child(2) {
background-color: #2196F3;
}
.record-group .van-button:last-child {
background-color: #FFC107; /* 第三个按钮颜色 */
}
/* 禁用状态的按钮颜色 */
.record-group .van-button:disabled {
background-color: #ccc;
color: #666;
}
.question-title {
font-size: 20px;
}
@@ -125,6 +229,7 @@ export default {
.next-button {
width: 30%;
margin: 0 auto;
margin-top: 30px;
}
</style>