302 lines
11 KiB
Vue
302 lines
11 KiB
Vue
<template>
|
||
<view class="test-page">
|
||
<view class="header">🎵 MP3录音测试</view>
|
||
|
||
<view class="tip-box">
|
||
<text>测试MP3格式录音(如果这个也失败,说明不是格式问题)</text>
|
||
</view>
|
||
|
||
<view class="card">
|
||
<view class="card-title">📱 设备信息</view>
|
||
<view class="info">{{ deviceInfo }}</view>
|
||
</view>
|
||
|
||
<view class="card">
|
||
<button @click="testMP3Record" :disabled="testing" class="btn-primary">
|
||
{{ testing ? '录音中...' : '测试MP3录音(3秒)' }}
|
||
</button>
|
||
<view class="result">{{ result }}</view>
|
||
</view>
|
||
|
||
<view class="card">
|
||
<view class="card-title">📋 日志</view>
|
||
<view class="log-box">
|
||
<text v-for="(log, index) in logs" :key="index" class="log-line">{{ log }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data() {
|
||
return {
|
||
deviceInfo: '',
|
||
testing: false,
|
||
result: '未测试',
|
||
logs: [],
|
||
recorder: null
|
||
}
|
||
},
|
||
onLoad() {
|
||
this.getDeviceInfo()
|
||
this.checkPermission()
|
||
},
|
||
methods: {
|
||
log(msg) {
|
||
const time = new Date().toLocaleTimeString()
|
||
this.logs.push(`[${time}] ${msg}`)
|
||
console.log(msg)
|
||
},
|
||
|
||
getDeviceInfo() {
|
||
// #ifdef APP-PLUS
|
||
this.deviceInfo = `${plus.os.name} ${plus.os.version} (${plus.device.model})`
|
||
this.log(`设备: ${this.deviceInfo}`)
|
||
// #endif
|
||
},
|
||
|
||
checkPermission() {
|
||
// #ifdef APP-PLUS
|
||
const result = plus.android.checkPermission('android.permission.RECORD_AUDIO')
|
||
this.log(`权限状态: ${result === 1 ? '已授权' : '未授权'}`)
|
||
|
||
if (result !== 1) {
|
||
plus.android.requestPermissions(['android.permission.RECORD_AUDIO'], (res) => {
|
||
this.log('权限请求结果: ' + JSON.stringify(res))
|
||
})
|
||
}
|
||
// #endif
|
||
},
|
||
|
||
testMP3Record() {
|
||
this.testing = true
|
||
this.result = '测试中...'
|
||
this.log('=== 开始MP3录音测试 ===')
|
||
|
||
// #ifdef APP-PLUS
|
||
try {
|
||
// 方法1:使用MediaRecorder原生API
|
||
this.testNativeMP3()
|
||
} catch (e) {
|
||
this.log(`错误: ${e.message}`)
|
||
this.result = `❌ ${e.message}`
|
||
this.testing = false
|
||
}
|
||
// #endif
|
||
},
|
||
|
||
// 使用Android原生MediaRecorder录制MP3
|
||
testNativeMP3() {
|
||
// #ifdef APP-PLUS
|
||
try {
|
||
this.log('使用原生MediaRecorder (AAC格式,可作为MP3替代)')
|
||
|
||
const MediaRecorder = plus.android.importClass('android.media.MediaRecorder')
|
||
const recorder = new MediaRecorder()
|
||
|
||
const timestamp = Date.now()
|
||
const fileName = 'test_mp3_' + timestamp + '.m4a' // AAC格式
|
||
|
||
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, (fs) => {
|
||
fs.root.getFile(fileName, {create: true}, (fileEntry) => {
|
||
const filePath = fileEntry.fullPath
|
||
this.log(`文件路径: ${filePath}`)
|
||
|
||
try {
|
||
// 配置录音器(AAC编码,接近MP3质量)
|
||
recorder.setAudioSource(MediaRecorder.AudioSource.MIC)
|
||
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
|
||
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
|
||
recorder.setAudioSamplingRate(16000)
|
||
recorder.setAudioEncodingBitRate(96000)
|
||
recorder.setOutputFile(filePath)
|
||
|
||
this.log('准备录音...')
|
||
recorder.prepare()
|
||
|
||
this.log('开始录音...')
|
||
recorder.start()
|
||
|
||
this.result = '✓ 录音中...(3秒)'
|
||
|
||
// 3秒后停止
|
||
setTimeout(() => {
|
||
try {
|
||
this.log('停止录音...')
|
||
|
||
// 先停止
|
||
try {
|
||
recorder.stop()
|
||
} catch (e) {
|
||
this.log('停止时出错(可忽略): ' + e.message)
|
||
}
|
||
|
||
// 再释放
|
||
try {
|
||
recorder.release()
|
||
} catch (e) {
|
||
this.log('释放时出错(可忽略): ' + e.message)
|
||
}
|
||
|
||
this.log('检查文件...')
|
||
|
||
// 检查文件
|
||
setTimeout(() => {
|
||
plus.io.resolveLocalFileSystemURL(filePath, (entry) => {
|
||
entry.file((file) => {
|
||
const sizeKB = (file.size / 1024).toFixed(2)
|
||
this.log(`文件大小: ${file.size} bytes (${sizeKB}KB)`)
|
||
|
||
if (file.size > 1000) {
|
||
this.result = `✅ 成功!\n格式: AAC (类MP3)\n大小: ${sizeKB}KB\n\n录音功能正常!`
|
||
this.log('✅ 测试成功!')
|
||
} else if (file.size > 100) {
|
||
this.result = `⚠️ 部分成功\n文件较小: ${sizeKB}KB\n可能录音质量差`
|
||
this.log('⚠️ 文件较小')
|
||
} else {
|
||
this.result = `❌ 失败\n文件过小: ${file.size}字节\n\n说明:不是格式问题\n是设备录音功能异常`
|
||
this.log('❌ 文件过小,录音失败')
|
||
this.log('结论: 所有格式都失败,不是格式问题')
|
||
}
|
||
|
||
this.testing = false
|
||
}, (err) => {
|
||
this.log('获取文件信息失败: ' + JSON.stringify(err))
|
||
this.result = '❌ 获取文件信息失败'
|
||
this.testing = false
|
||
})
|
||
}, (err) => {
|
||
this.log('文件不存在: ' + JSON.stringify(err))
|
||
this.result = '❌ 文件不存在'
|
||
this.testing = false
|
||
})
|
||
}, 500)
|
||
|
||
} catch (e) {
|
||
this.log('停止录音失败: ' + e.message)
|
||
this.result = `❌ 停止失败: ${e.message}`
|
||
this.testing = false
|
||
}
|
||
}, 3000)
|
||
|
||
} catch (e) {
|
||
this.log('启动录音失败: ' + e.message)
|
||
this.result = `❌ 启动失败: ${e.message}`
|
||
this.testing = false
|
||
}
|
||
}, (err) => {
|
||
this.log('创建文件失败: ' + JSON.stringify(err))
|
||
this.result = '❌ 创建文件失败'
|
||
this.testing = false
|
||
})
|
||
}, (err) => {
|
||
this.log('文件系统错误: ' + JSON.stringify(err))
|
||
this.result = '❌ 文件系统错误'
|
||
this.testing = false
|
||
})
|
||
|
||
} catch (e) {
|
||
this.log('异常: ' + e.message)
|
||
this.result = `❌ 异常: ${e.message}`
|
||
this.testing = false
|
||
}
|
||
// #endif
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.test-page {
|
||
min-height: 100vh;
|
||
background: #f5f7fa;
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.header {
|
||
text-align: center;
|
||
font-size: 40rpx;
|
||
font-weight: bold;
|
||
padding: 30rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.tip-box {
|
||
background: #fff9e6;
|
||
border-left: 4rpx solid #ffc107;
|
||
padding: 20rpx;
|
||
margin-bottom: 20rpx;
|
||
border-radius: 8rpx;
|
||
font-size: 26rpx;
|
||
color: #856404;
|
||
}
|
||
|
||
.card {
|
||
background: #fff;
|
||
border-radius: 16rpx;
|
||
padding: 30rpx;
|
||
margin-bottom: 20rpx;
|
||
box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.card-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
margin-bottom: 20rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.info {
|
||
padding: 15rpx;
|
||
background: #f5f5f5;
|
||
border-radius: 8rpx;
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.btn-primary {
|
||
width: 100%;
|
||
padding: 30rpx;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: #fff;
|
||
border: none;
|
||
border-radius: 12rpx;
|
||
font-size: 32rpx;
|
||
box-shadow: 0 4rpx 15rpx rgba(102, 126, 234, 0.4);
|
||
}
|
||
|
||
button:disabled {
|
||
background: #ccc;
|
||
color: #999;
|
||
box-shadow: none;
|
||
}
|
||
|
||
.result {
|
||
margin-top: 20rpx;
|
||
padding: 20rpx;
|
||
background: #f5f5f5;
|
||
border-radius: 8rpx;
|
||
font-size: 28rpx;
|
||
min-height: 100rpx;
|
||
white-space: pre-line;
|
||
color: #333;
|
||
}
|
||
|
||
.log-box {
|
||
max-height: 400rpx;
|
||
overflow-y: auto;
|
||
background: #2d2d2d;
|
||
border-radius: 8rpx;
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.log-line {
|
||
display: block;
|
||
font-size: 24rpx;
|
||
color: #0f0;
|
||
font-family: monospace;
|
||
line-height: 1.8;
|
||
}
|
||
</style>
|