TTS文件生成
This commit is contained in:
parent
28677fe08c
commit
4d71363fad
|
|
@ -1397,80 +1397,134 @@
|
||||||
console.log('✅ 音频数据解码完成,大小:', bytes.length, 'bytes')
|
console.log('✅ 音频数据解码完成,大小:', bytes.length, 'bytes')
|
||||||
|
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
// APP 环境 - 简化实现
|
// APP 环境 - 使用 plus.io 写入文件
|
||||||
console.log('📱 APP 环境,保存并播放音频')
|
console.log('📱 APP 环境,保存音频文件')
|
||||||
|
console.log('📊 音频数据大小:', bytes.length, 'bytes')
|
||||||
|
|
||||||
const fileName = `ai_voice_${Date.now()}.mp3`
|
const fileName = `ai_voice_${Date.now()}.mp3`
|
||||||
const filePath = `_doc/${fileName}`
|
|
||||||
|
|
||||||
// 使用 plus.io 保存文件
|
// 使用 plus.io 保存文件
|
||||||
plus.io.resolveLocalFileSystemURL('_doc/', (entry) => {
|
plus.io.resolveLocalFileSystemURL('_doc/', (docEntry) => {
|
||||||
console.log('✅ 获取 _doc 目录成功')
|
console.log('✅ 获取 _doc 目录成功')
|
||||||
|
|
||||||
entry.getFile(fileName, {create: true}, (fileEntry) => {
|
docEntry.getFile(fileName, {create: true, exclusive: false}, (fileEntry) => {
|
||||||
console.log('✅ 创建文件成功:', fileName)
|
console.log('✅ 文件对象创建成功')
|
||||||
|
console.log('📁 文件路径:', fileEntry.fullPath)
|
||||||
|
|
||||||
|
// 创建 FileWriter
|
||||||
fileEntry.createWriter((writer) => {
|
fileEntry.createWriter((writer) => {
|
||||||
writer.onwrite = () => {
|
console.log('✅ FileWriter 创建成功')
|
||||||
console.log('✅ 文件写入成功')
|
|
||||||
console.log('📁 文件路径:', fileEntry.fullPath)
|
|
||||||
|
|
||||||
// 播放音频
|
// 设置写入完成事件
|
||||||
console.log('🎵 创建音频上下文...')
|
writer.onwriteend = function(evt) {
|
||||||
const audioContext = uni.createInnerAudioContext()
|
console.log('✅✅✅ 文件写入完成!')
|
||||||
|
|
||||||
// 使用完整路径
|
// 验证文件大小
|
||||||
const fullPath = fileEntry.fullPath
|
fileEntry.file((file) => {
|
||||||
console.log('🎵 设置音频源:', fullPath)
|
console.log('📊 文件大小:', file.size, 'bytes')
|
||||||
audioContext.src = fullPath
|
|
||||||
audioContext.autoplay = true
|
|
||||||
|
|
||||||
audioContext.onPlay(() => {
|
if (file.size === 0) {
|
||||||
console.log('🔊 AI 语音开始播放')
|
console.error('❌ 文件大小为 0')
|
||||||
})
|
uni.showToast({
|
||||||
|
title: '文件保存失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
audioContext.onEnded(() => {
|
// 获取文件 URL
|
||||||
console.log('✅ AI 语音播放完成')
|
const audioUrl = fileEntry.toLocalURL()
|
||||||
// 清理
|
console.log('🎵 准备播放,URL:', audioUrl)
|
||||||
audioContext.destroy()
|
|
||||||
fileEntry.remove(() => {
|
// 使用 plus.audio 播放
|
||||||
console.log('🗑️ 临时文件已清理')
|
console.log('🎵 创建播放器...')
|
||||||
|
const player = plus.audio.createPlayer(audioUrl)
|
||||||
|
|
||||||
|
player.play(() => {
|
||||||
|
console.log('🔊🔊🔊 AI 语音开始播放!')
|
||||||
|
uni.showToast({
|
||||||
|
title: 'AI 正在说话',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 1000
|
||||||
|
})
|
||||||
|
}, (e) => {
|
||||||
|
console.error('❌ plus.audio 播放失败:', e)
|
||||||
|
console.error('错误详情:', JSON.stringify(e))
|
||||||
|
|
||||||
|
// 如果 plus.audio 失败,尝试 uni.createInnerAudioContext
|
||||||
|
console.log('🔄 尝试使用 InnerAudioContext')
|
||||||
|
const ctx = uni.createInnerAudioContext()
|
||||||
|
ctx.src = audioUrl
|
||||||
|
ctx.autoplay = true
|
||||||
|
|
||||||
|
ctx.onPlay(() => {
|
||||||
|
console.log('🔊 InnerAudioContext 播放成功')
|
||||||
|
uni.showToast({
|
||||||
|
title: 'AI 正在说话',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx.onError((err) => {
|
||||||
|
console.error('❌ InnerAudioContext 也失败:', err)
|
||||||
|
uni.showToast({
|
||||||
|
title: '播放失败',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 3000
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx.onEnded(() => {
|
||||||
|
console.log('✅ 播放完成')
|
||||||
|
ctx.destroy()
|
||||||
|
// 清理文件
|
||||||
|
fileEntry.remove(() => console.log('🗑️ 文件已清理'))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
audioContext.onError((error) => {
|
player.addEventListener('ended', () => {
|
||||||
console.error('❌ 播放失败:', error)
|
console.log('✅ 播放完成')
|
||||||
console.error('错误详情:', JSON.stringify(error))
|
player.close()
|
||||||
uni.showToast({
|
// 清理文件
|
||||||
title: '播放失败',
|
fileEntry.remove(() => console.log('🗑️ 文件已清理'))
|
||||||
icon: 'none'
|
|
||||||
})
|
})
|
||||||
audioContext.destroy()
|
|
||||||
|
player.addEventListener('error', (e) => {
|
||||||
|
console.error('❌ 播放错误:', e)
|
||||||
|
player.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
}, (error) => {
|
||||||
|
console.error('❌ 获取文件信息失败:', error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.onerror = (error) => {
|
// 设置写入错误事件
|
||||||
console.error('❌ 文件写入失败:', error)
|
writer.onerror = function(e) {
|
||||||
|
console.error('❌❌❌ 文件写入失败!')
|
||||||
|
console.error('错误对象:', e)
|
||||||
|
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '文件保存失败',
|
title: '文件保存失败',
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 写入数据
|
// 直接写入 Uint8Array
|
||||||
console.log('📝 开始写入文件...')
|
console.log('📝 开始写入二进制数据...')
|
||||||
const blob = new Blob([bytes.buffer], {type: 'audio/mp3'})
|
console.log('📝 数据大小:', bytes.length, 'bytes')
|
||||||
writer.write(blob)
|
writer.write(bytes)
|
||||||
|
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
console.error('❌ 创建 writer 失败:', error)
|
console.error('❌ 创建 FileWriter 失败:', error)
|
||||||
})
|
})
|
||||||
|
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
console.error('❌ 创建文件失败:', error)
|
console.error('❌ 创建文件失败:', error)
|
||||||
console.error('错误详情:', JSON.stringify(error))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
console.error('❌ 获取文件系统失败:', error)
|
console.error('❌ 获取文件系统失败:', error)
|
||||||
console.error('错误详情:', JSON.stringify(error))
|
|
||||||
})
|
})
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user