import { ref, onMounted, onUnmounted } from "vue"
import Taro from "@tarojs/taro"
import { openVoice } from "@/utils/synthesis.js"
// 初始化音频 切割
export function useAudioPlayer() {
const textAyy = ref([])
const currentAudioIndex = ref(0)
const totalAudioChunks = ref(0)
const isPlaying = ref(false)
const isPaused = ref(false)
const originalContent = ref("")
let audioContext = null
onMounted(() => {
audioContext = Taro.createInnerAudioContext({
mixWithOther: true,
obeyMuteSwitch: false, // 忽略静音开关
})
audioContext.onEnded(() => {
console.log("播放结束", currentAudioIndex.value)
if (
isPlaying.value &&
currentAudioIndex.value < totalAudioChunks.value - 1
) {
currentAudioIndex.value++
speakText(textAyy.value[currentAudioIndex.value])
} else {
isPlaying.value = false
isPaused.value = false
currentAudioIndex.value = 0
}
})
})
onUnmounted(() => {
if (audioContext) {
audioContext.destroy()
}
})
const splitStringByLength = async (str, maxSize, chunkSize) => {
// 将字符串按照指定大小分割成多个片段
const totalLength = str.length
if (totalLength <= maxSize) {
return [str]
}
const chunks = []
let start = 0
while (start < totalLength) {
let end = Math.min(start + chunkSize, totalLength)
const chunk = str.substring(start, end)
const res = await openVoice(chunk, null)
console.log("语音合成结果", res)
chunks.push(res.url)
start = end
}
return chunks
}
const speakText = async (text) => {
console.log("文字转语音", text)
if (isPlaying.value) {
audioContext.src = text
audioContext.play()
}
}
const prepareAudio = async (content) => {
if (content !== originalContent.value) {
console.log("准备新的音频内容")
Taro.showLoading({ title: "准备中", mask: true })
try {
textAyy.value = await splitStringByLength(content, 100, 100)
console.log("音频片段准备完成", textAyy.value)
totalAudioChunks.value = textAyy.value.length
originalContent.value = content
} catch (error) {
console.error("音频准备失败:", error)
Taro.showToast({ title: "语音合成失败", icon: "none" })
throw error
} finally {
Taro.hideLoading()
}
} else {
console.log("使用现有的音频内容")
}
}
const toggleAudio = async (content) => {
if (!audioContext) return
if (isPaused.value) {
console.log("继续播放")
// 如果当前暂停,恢复播放
audioContext.play()
isPaused.value = false
} else if (!isPlaying.value) {
console.log("开始播放")
// 如果当前没有播放,开始新的播放
if (textAyy.value.length === 0) {
// 如果还没有准备好音频,先准备
await prepareAudio(content)
}
currentAudioIndex.value = 0
isPlaying.value = true
isPaused.value = false
await speakText(textAyy.value[0])
} else {
console.log("暂停播放")
// 如果当前正在播放,暂停
audioContext.pause()
isPaused.value = true
}
isPlaying.value = !isPaused.value
}
const stopAudio = () => {
if (audioContext) {
audioContext.stop()
}
}
return {
toggleAudio,
isPlaying,
isPaused,
stopAudio,
prepareAudio,
}
}