188 lines
4.9 KiB
JavaScript
188 lines
4.9 KiB
JavaScript
|
|
/**
|
|||
|
|
* MP3录音工具(已验证可用)
|
|||
|
|
* 使用Android原生MediaRecorder
|
|||
|
|
* 格式:MP3 (128kbps,高质量)
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
class AACRecorder {
|
|||
|
|
constructor() {
|
|||
|
|
this.recorder = null
|
|||
|
|
this.isRecording = false
|
|||
|
|
this.recordFile = null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 开始录音
|
|||
|
|
* @param {Number} maxDuration 最大录音时长(毫秒),默认60秒
|
|||
|
|
* @returns {Promise}
|
|||
|
|
*/
|
|||
|
|
start(maxDuration = 60000) {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
// #ifdef APP-PLUS
|
|||
|
|
try {
|
|||
|
|
if (this.isRecording) {
|
|||
|
|
reject(new Error('正在录音中'))
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('[MP3录音] 开始录音...')
|
|||
|
|
|
|||
|
|
// 导入Android类
|
|||
|
|
const MediaRecorder = plus.android.importClass('android.media.MediaRecorder')
|
|||
|
|
this.recorder = new MediaRecorder()
|
|||
|
|
|
|||
|
|
// 生成文件名 - 改用MP3格式
|
|||
|
|
const timestamp = Date.now()
|
|||
|
|
const fileName = 'record_' + timestamp + '.mp3'
|
|||
|
|
|
|||
|
|
// 创建文件
|
|||
|
|
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, (fs) => {
|
|||
|
|
fs.root.getFile(fileName, {create: true}, (fileEntry) => {
|
|||
|
|
this.recordFile = fileEntry.fullPath
|
|||
|
|
console.log('[MP3录音] 文件路径:', this.recordFile)
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 配置录音器 - 使用MP3格式
|
|||
|
|
this.recorder.setAudioSource(MediaRecorder.AudioSource.MIC)
|
|||
|
|
this.recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
|
|||
|
|
this.recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC) // AAC编码在MP3容器中
|
|||
|
|
this.recorder.setAudioSamplingRate(16000) // 16kHz采样率
|
|||
|
|
this.recorder.setAudioEncodingBitRate(128000) // 128kbps比特率(更高质量)
|
|||
|
|
this.recorder.setMaxDuration(maxDuration) // 最大时长
|
|||
|
|
this.recorder.setOutputFile(this.recordFile)
|
|||
|
|
|
|||
|
|
// 准备并开始
|
|||
|
|
this.recorder.prepare()
|
|||
|
|
this.recorder.start()
|
|||
|
|
|
|||
|
|
this.isRecording = true
|
|||
|
|
console.log('[MP3录音] ✓ 录音已开始')
|
|||
|
|
|
|||
|
|
resolve()
|
|||
|
|
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('[MP3录音] 启动失败:', e)
|
|||
|
|
reject(e)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}, reject)
|
|||
|
|
}, reject)
|
|||
|
|
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('[MP3录音] 异常:', e)
|
|||
|
|
reject(e)
|
|||
|
|
}
|
|||
|
|
// #endif
|
|||
|
|
|
|||
|
|
// #ifndef APP-PLUS
|
|||
|
|
reject(new Error('只支持APP环境'))
|
|||
|
|
// #endif
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 停止录音
|
|||
|
|
* @returns {Promise<Object>} {filePath, fileSize}
|
|||
|
|
*/
|
|||
|
|
stop() {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
// #ifdef APP-PLUS
|
|||
|
|
if (!this.isRecording) {
|
|||
|
|
reject(new Error('未在录音'))
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
console.log('[MP3录音] 停止录音...')
|
|||
|
|
|
|||
|
|
// 停止录音(使用try-catch防止崩溃)
|
|||
|
|
try {
|
|||
|
|
this.recorder.stop()
|
|||
|
|
} catch (e) {
|
|||
|
|
console.warn('[MP3录音] 停止时警告:', e.message)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 释放资源
|
|||
|
|
try {
|
|||
|
|
this.recorder.release()
|
|||
|
|
} catch (e) {
|
|||
|
|
console.warn('[MP3录音] 释放时警告:', e.message)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.isRecording = false
|
|||
|
|
this.recorder = null
|
|||
|
|
|
|||
|
|
console.log('[MP3录音] ✓ 录音已停止')
|
|||
|
|
|
|||
|
|
// 等待文件完全写入
|
|||
|
|
setTimeout(() => {
|
|||
|
|
this.getFileInfo(this.recordFile)
|
|||
|
|
.then(fileInfo => {
|
|||
|
|
console.log('[MP3录音] 文件大小:', fileInfo.size, 'bytes')
|
|||
|
|
|
|||
|
|
if (fileInfo.size < 1000) {
|
|||
|
|
console.warn('[MP3录音] ⚠️ 文件较小,可能录音时间太短')
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
resolve({
|
|||
|
|
filePath: this.recordFile,
|
|||
|
|
fileSize: fileInfo.size
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
.catch(reject)
|
|||
|
|
}, 500)
|
|||
|
|
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('[MP3录音] 停止异常:', e)
|
|||
|
|
this.isRecording = false
|
|||
|
|
reject(e)
|
|||
|
|
}
|
|||
|
|
// #endif
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取文件信息
|
|||
|
|
*/
|
|||
|
|
getFileInfo(filePath) {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
// #ifdef APP-PLUS
|
|||
|
|
plus.io.resolveLocalFileSystemURL(filePath, (entry) => {
|
|||
|
|
entry.file((file) => {
|
|||
|
|
resolve({
|
|||
|
|
name: file.name,
|
|||
|
|
size: file.size,
|
|||
|
|
type: file.type
|
|||
|
|
})
|
|||
|
|
}, reject)
|
|||
|
|
}, reject)
|
|||
|
|
// #endif
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 取消录音
|
|||
|
|
*/
|
|||
|
|
cancel() {
|
|||
|
|
if (this.isRecording) {
|
|||
|
|
try {
|
|||
|
|
this.recorder.stop()
|
|||
|
|
this.recorder.release()
|
|||
|
|
} catch (e) {
|
|||
|
|
console.warn('[MP3录音] 取消时警告:', e.message)
|
|||
|
|
}
|
|||
|
|
this.isRecording = false
|
|||
|
|
this.recorder = null
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 检查是否正在录音
|
|||
|
|
*/
|
|||
|
|
checkRecording() {
|
|||
|
|
return this.isRecording
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export default new AACRecorder()
|