微信小程序文字转语音播放字数限制【20003错误】

165 阅读1分钟
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,
  };
}