Skip to content

Commit

Permalink
task-2810229177954560:audio-record
Browse files Browse the repository at this point in the history
  • Loading branch information
wangxue08 committed Feb 27, 2024
1 parent 102c410 commit cb31af1
Show file tree
Hide file tree
Showing 7 changed files with 476 additions and 113 deletions.
75 changes: 72 additions & 3 deletions packages/cw/cw_audio_library/components/cw-audio-record/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,76 @@
belong: component
labels: [Runtime]
attrs:
- name: value
- name: waveBgColor
title: 声波背景颜色
type: color
default: 'rgb(200, 200, 200)'
description: 设定声波背景颜色
- name: waveColor
title: 声波波形颜色
type: color
default: 'rgb(0, 0, 0)'
description: 设定波形绘制颜色
- name: maxFileSize
title: 最大文件大小
type: number
compType: inputNumber
default: 10
description: 上传文件的最大大小
- name: uploadUrl
title: 上传音频地址
type: string
default: 请在这里编写代码
description: 需要传入的值
compType: interfaceSelect
default:
description: 上传的地址
methods:
- name: startRecord
title: 开始录制
description: 开始录制音频
- name: stopRecord
title: 停止录制
description: 停止录制音频
- name: pauseRecord
title: 暂停录制
description: 暂停录制音频
- name: uploadRecord
title: 上传录制
description: 上传录制的音频
params:
- name: type
type: string
description: 上传的文件格式(wav,mp3,pcm)
- name: downloadRecord
title: 下载录制
description: 下载录制的音频
params:
- name: type
type: string
description: 下载的文件格式(wav,mp3,pcm)
- name: deleteRecord
title: 删除录制
description: 删除录制的音频
- name: playRecord
title: 播放录制
description: 播放录制的音频
- name: pausePlayRecord
title: 暂停播放
description: 暂停播放录制的音频
- name: resumePlayRecord
title: 继续播放
description: 继续播放录制的音频
events:
- name: onUploadSuccess
description: 上传音频成功时
title: 上传成功时
params:
- name: value
type: string
description: 改变的值
- name: onUploadError
description: 上传失败时
title: 上传失败时
params:
- name: value
type: string
description: 错误原因
Original file line number Diff line number Diff line change
@@ -1,5 +1,53 @@
### 基本用法

``` html
<cw-audio-record></cw-audio-record>
``` vue
<template>
<div>
<div style="display: flex; flex-direction: column;">
<u-button @click="startRecord">开始录音</u-button>
<u-button @click="pauseRecord">暂停录音</u-button>
<u-button @click="resumeRecord">恢复录音</u-button>
<u-button @click="stopRecord">停止录音</u-button>
<u-button @click="downloadPCM">下载PCM格式录音</u-button>
<u-button @click="downloadWAV">下载WAV格式录音</u-button>
<u-button @click="downloadMP3">下载MP3格式录音</u-button>
<u-button @click="upload">上传录音</u-button>
</div>
<cw-audio-record ref='audioRecord'></cw-audio-record>
</div>
</template>
<script>
export default {
methods:{
startRecord() {
this.$refs.audioRecord.startRecord()
},
pauseRecord() {
this.$refs.audioRecord.pauseRecord()
},
resumeRecord() {
this.$refs.audioRecord.resumeRecord()
},
stopRecord() {
this.$refs.audioRecord.stopRecord()
},
downloadPCM() {
this.$refs.audioRecord.downloadPCM()
},
downloadWAV() {
this.$refs.audioRecord.downloadWAV()
},
downloadMP3() {
this.$refs.audioRecord.downloadMP3()
},
upload() {
this.$refs.audioRecord.uploadRecord()
}
}
}
</script>
```
173 changes: 150 additions & 23 deletions packages/cw/cw_audio_library/components/cw-audio-record/index.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
<template>
<div>
<div :class="$style.recordRoot" ref="canvasParent">
<canvas ref="audioCanvas"></canvas>
<u-button @click="startRecord">开始录音</u-button>

</div>

</template>

<script>
import Recorder from 'js-audio-recorder';
import { convertToMp3 } from './utils'
import axios from "axios"
export default {
name: "cw-audio-record",
props: {
Expand All @@ -25,14 +23,55 @@ export default {
type: Number,
default: 1
},
maxFileSize: {
type: Number,
default: 10
},
uploadUrl: {
type: String,
default: '/gateway/lowcode/api/v1/app/upload'
},
waveColor: {
type: String,
default: 'rgb(0, 0, 0)'
},
waveBgColor: {
type: String,
default: 'rgb(200, 200, 200)'
},
urlField: { type: String, default: 'url' },
},
data() {
return {
isRecording: false, // 是否正在录音
duration: 0, // 录音时长
fileSize: 0, // 文件大小
};
},
methods: {
deleteRecord() {
if (this.recorder) {
this.recorder.destroy().then(() => {
console.log('删除录音');
recorder = null;
this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
});
}
},
playRecord() {
this.recorder && this.recorder.play();
this.drawRecordId && this.cancelAnimationFrame(drawRecordId);
this.drawRecordId = null;
console.log('播放录音');
},
pausePlayRecord() {
this.recorder && this.recorder.pausePlay();
console.log('暂停播放录音');
},
resumeRecord() {
this.recorder && this.recorder.resumePlay();
console.log('继续播放录音');
},
startRecord() {
const config = {
sampleRate: this.sampleRateOptions,
Expand All @@ -43,56 +82,134 @@ export default {
this.recorder = new Recorder(config);
this.recorder.start().then(() => {
console.log('开始录音');
this.isRecording = true;
}, (error) => {
console.log(`异常了,${error.name}:${error.message}`);
});
this.recorder.onprogress = (params) => {
this.duration = params.duration.toFixed(2);
this.fileSize = params.fileSize;
if (this.fileSize >= this.maxFileSize * 1024 * 1024) {
this.stopRecord();
console.log('录音文件超过最大限制');
}
};
this.drawRecord();
}
},
async uploadRecord(type = 'wav') {
if (this.recorder && !this.isRecording && this.uploadUrl) {
const authorization = this.getCookie('authorization');
const formData = new FormData();
const blob = this.getAudioData(type);
const file = new File([blob], `recordFile_${new Date().getTime()}.${type}`, { type });
formData.append('file', file);
const headers = authorization ? { Authorization: authorization, 'Content-Type': `multipart/form-data; boundary=${formData._boundary}` } : {};
const r = await axios.post(this.uploadUrl ? this.uploadUrl : '/gateway/lowcode/api/v1/app/upload', formData, headers);
if (r.data.code === 200) {
this.$emit("onUploadSuccess", r.data.result)
} else {
this.$emit("onUploadError", r.data.message)
}
}
},
getAudioData(type) {
const map = {
'wav': this.recorder.getWAVBlob(),
'pcm': this.recorder.getPCMBlob(),
'mp3': convertToMp3(this.recorder.getWAV(), this.recorder)
};
return map[type];
},
pauseRecord() {
if (this.recorder) {
this.recorder.pause();
console.log('暂停录音');
this.isRecording = false;
this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
this.drawRecordId = null;
}
},
resumeRecord() {
this.recorder && this.recorder.resume();
console.log('恢复录音');
this.isRecording = true;
this.drawRecord();
},
stopRecord() {
this.recorder && this.recorder.stop();
this.isRecording = false;
this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
this.drawRecordId = null;
},
downloadRecord(type = 'wav') {
if (this.isRecording) {
return;
}
const map = {
'wav': this.downloadWAV(),
'pcm': this.downloadPCM(),
'mp3': this.downloadMP3()
};
if (map[type]) {
map[type]();
} else {
console.log('不支持的下载类型');
}
},
downloadWAV() {
if (this.isRecording) {
return;
}
this.recorder && this.recorder.downloadWAV();
},
downloadPCM() {
if (this.isRecording) {
return;
}
this.recorder && this.recorder.downloadPCM();
},
getCookie(cname) {
const name = `${cname}=`;
const ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
const c = ca[i].trim();
if (c.indexOf(name) === 0)
return c.substring(name.length, c.length);
}
return '';
},
downloadMP3() {
if (this.isRecording) {
return;
}
if (this.recorder) {
this.recorder.stop().then((blob) => {
console.log('停止录音');
console.log('录音时长:' + this.recorder.duration + 'ms');
this.duration = this.recorder.duration;
this.recorder = null;
this.drawRecordId && cancelAnimationFrame(this.drawRecordId);
this.drawRecordId = null;
});
const mp3Blob = convertToMp3(this.recorder.getWAV(), this.recorder);
this.recorder.download(mp3Blob, 'recorder', 'mp3');
}
},
drawRecord() {
const oCanvas = this.$refs.imgCanvas;
const parentElement = this.$refs.canvasParent;
const oCanvas = this.$refs.audioCanvas;
oCanvas.width = parentElement.clientWidth;
oCanvas.height = parentElement.clientHeight;
const ctx = oCanvas.getContext('2d');
// 获取音频数据
let dataArr = this.recorder.getRecordAnalyseData();
let bufferLength = dataArr.length;
let dataArray = this.recorder.getRecordAnalyseData();
let bufferLength = dataArray.length;
const sliceWidth = oCanvas.width * 1.0 / bufferLength;
let x = 0;
// 用requestAnimationFrame稳定60fps绘制
this.drawRecordId = requestAnimationFrame(this.drawRecord);
// 填充背景色
ctx.fillStyle = 'rgb(200, 200, 200)';
ctx.fillStyle = this.waveBgColor;
ctx.fillRect(0, 0, oCanvas.width, oCanvas.height);
// 设定波形绘制颜色
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgb(0, 0, 0)';
ctx.strokeStyle = this.waveColor;
ctx.beginPath();
for (var i = 0; i < bufferLength; i++) {
Expand All @@ -113,8 +230,18 @@ export default {
ctx.lineTo(oCanvas.width, oCanvas.height / 2);
ctx.stroke();
}
}
},
}
</script>

<style></style>
<style module>
.recordRoot {
position: relative;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
</style>
Loading

0 comments on commit cb31af1

Please sign in to comment.