guoyu/fronted_uniapp/pages/mp3-record-test.vue
2025-12-10 22:53:20 +08:00

302 lines
11 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>