You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Expo React Native中播放OpenAI TTS API音频遇问题求助

解决Expo中直接播放OpenAI TTS API音频Blob的问题

问题场景

使用Expo开发React Native应用时,调用OpenAI TTS API将文本转为音频后,希望直接播放Blob响应而不本地保存文件。已成功获取正确的Blob,但使用expo-av播放时触发错误:

Error: The AVPlayerItem instance has failed with the error code -1002 and domain "NSURLErrorDomain"

错误原因

错误码-1002对应NSURLErrorUnsupportedURL,因为iOS原生AVPlayer(expo-av的底层依赖)不支持URL.createObjectURL生成的Blob URL,导致无法加载音频资源。

解决方案

将Blob转换为Base64格式的Data URI,expo-av的Audio.Sound支持直接加载Data URI形式的音频源。

修改后的完整代码

import { Audio } from 'expo-av';

const convertTextToSpeech = async (textToConvert) => {
    const apiKey = 'myKey';
    const url = 'https://api.openai.com/v1/audio/speech';

    try {
        const response = await fetch(url, {
            method: 'POST',
            headers: {
                'Authorization': `Bearer ${apiKey}`,
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                model: 'tts-1',
                input: textToConvert,
                voice: 'alloy',
                language: 'da',
            })
        });

        if (!response.ok) {
            throw new Error(`请求失败: ${response.status}`);
        }

        const blob = await response.blob();
        await playSound(blob);
    } catch (error) {
        console.error('请求或播放出错:', error);
    }
};

async function playSound(blob) {
    // 将Blob转换为Base64
    const base64 = await new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onloadend = () => resolve(reader.result.split(',')[1]);
        reader.onerror = reject;
        reader.readAsDataURL(blob);
    });

    // 构建Data URI
    const audioUri = `data:${blob.type};base64,${base64}`;

    // 加载并播放音频
    const { sound, status } = await Audio.Sound.createAsync(
        { uri: audioUri },
        { shouldPlay: false }
    );

    try {
        await sound.playAsync();
        // 监听播放结束,清理资源
        sound.setOnPlaybackStatusUpdate((status) => {
            if (status.didJustFinish) {
                sound.unloadAsync();
            }
        });
    } catch (playError) {
        console.error('播放失败:', playError);
        await sound.unloadAsync();
    }
}

关键修改点

  • 替换URL.createObjectURL为Blob转Base64的逻辑,生成Data URI适配expo-av的加载要求
  • 添加音频播放结束后的资源卸载逻辑,避免内存泄漏
  • 统一使用async/await语法,提升代码可读性和错误处理能力

内容的提问来源于stack exchange,提问作者Christoffer Nielsen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 08:32:50