React Native Expo中的音频Blob无法正常工作

svmlkihl  于 12个月前  发布在  React
关注(0)|答案(1)|浏览(99)

我正在对Eleven Labs API进行API调用,然后访问数据以获取以下blob:

{"_data": {"__collector": {}, "blobId": "C3F1259A-B9CD-40D9-AB28-6551593AFB4C", "name": "21m00Tcm4TlvDq8ikWAM.mp3", "offset": 0, "size": 15464, "type": "audio/mpeg"}}

然后我使用Blob-av播放blob:

const triggerTextToSpeech = async () => {
        try {
            const labsResponse = await elevenLabsToSpeech("Hello!");

            if (labsResponse) {
                const sound = new Audio.Sound();

                console.log(labsResponse.data);
                console.log("speech loaded");

                await sound.loadAsync(labsResponse.data);

                await sound.playAsync();
            } else {
                console.log(
                    "Text-to-speech failed: The API response did not contain the audio data."
                );
            }
        } catch (error) {
            console.log("Text-to-speech failed: " + error);
        }
    };

然而,我总是得到“无法从空播放源加载AV资产”的提示。我不太明白为什么,因为我在等待实验室的React是真实的,然后再继续。
如果有帮助的话。下面是我正在进行的API调用:

export async function elevenLabsToSpeech(message: string) {
    const url =
        "https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM?optimize_streaming_latency=0";

    const headers = {
        accept: "audio/mpeg",
        "xi-api-key": "removed",
        "Content-Type": "application/json",
    };

    const data = {
        text: message,
        model_id: "eleven_multilingual_v1",
        voice_settings: {
            stability: 0,
            similarity_boost: 0,
        },
    };

    try {
        const audioResponse = await axios.post(url, data, { headers, responseType: "blob" });

        return audioResponse;
    } catch (error) {
        console.error(error);
    }
}

以下是来自API的完整响应:

{
  "config": {
    "adapter": "xhr",
    "data": "{\"text\":\"Hello!\",\"model_id\":\"eleven_multilingual_v1\",\"voice_settings\":{\"stability\":0,\"similarity_boost\":0}}",
    "env": {
      "Blob": "[Function Blob]",
      "FormData": "[Function FormData]"
    },
    "headers": "[Object]",
    "maxBodyLength": -1,
    "maxContentLength": -1,
    "method": "post",
    "responseType": "blob",
    "timeout": 0,
    "transformRequest": "[Function transformRequest]",
    "transformResponse": "[Function transformResponse]",
    "transitional": {
      "clarifyTimeoutError": false,
      "forcedJSONParsing": true,
      "silentJSONParsing": true
    },
    "url": "https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM?optimize_streaming_latency=0",
    "validateStatus": "[Function validateStatus]",
    "xsrfCookieName": "XSRF-TOKEN",
    "xsrfHeaderName": "X-XSRF-TOKEN"
  },
  "data": {
    "_data": {
      "__collector": "[Object]",
      "blobId": "C581B55D-2DEE-4F1F-9DD9-697410C47B49",
      "name": "21m00Tcm4TlvDq8ikWAM.mp3",
      "offset": 0,
      "size": 14628,
      "type": "audio/mpeg"
    }
  },
  "headers": {
    "access-control-allow-headers": "*",
    "access-control-allow-methods": "POST, OPTIONS, DELETE, GET",
    "access-control-allow-origin": "*",
    "access-control-expose-headers": "request-id, history-item-id",
    "alt-svc": "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000",
    "content-length": "14628",
    "content-type": "audio/mpeg",
    "date": "Sun, 24 Sep 2023 17:47:47 GMT",
    "history-item-id": "JiQpbUIpMEd7CISACwFC",
    "request-id": "Z0nf4ZDhNYNkdVFGKmyk",
    "server": "uvicorn",
    "via": "1.1 google"
  },
  "request": {
    "DONE": 4,
    "HEADERS_RECEIVED": 2,
    "LOADING": 3,
    "OPENED": 1,
    "UNSENT": 0,
    "_aborted": false,
    "_cachedResponse": {
      "_data": "[Object]"
    },
    "_hasError": false,
    "_headers": {
      "accept": "audio/mpeg",
      "content-type": "application/json",
      "xi-api-key": "removed"
    },
    "_incrementalEvents": false,
    "_lowerCaseResponseHeaders": {
      "access-control-allow-headers": "*",
      "access-control-allow-methods": "POST, OPTIONS, DELETE, GET",
      "access-control-allow-origin": "*",
      "access-control-expose-headers": "request-id, history-item-id",
      "alt-svc": "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000",
      "content-length": "14628",
      "content-type": "audio/mpeg",
      "date": "Sun, 24 Sep 2023 17:47:47 GMT",
      "history-item-id": "JiQpbUIpMEd7CISACwFC",
      "request-id": "Z0nf4ZDhNYNkdVFGKmyk",
      "server": "uvicorn",
      "via": "1.1 google"
    },
    "_method": "POST",
    "_perfKey": "network_XMLHttpRequest_https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM?optimize_streaming_latency=0",
    "_performanceLogger": {
      "_closed": false,
      "_extras": "[Object]",
      "_isLoggingForWebPerformance": false,
      "_pointExtras": "[Object]",
      "_points": "[Object]",
      "_timespans": "[Object]"
    },
    "_requestId": null,
    "_response": {
      "blobId": "C581B55D-2DEE-4F1F-9DD9-697410C47B49",
      "name": "21m00Tcm4TlvDq8ikWAM.mp3",
      "offset": 0,
      "size": 14628,
      "type": "audio/mpeg"
    },
    "_responseType": "blob",
    "_sent": true,
    "_subscriptions": [],
    "_timedOut": false,
    "_trackingName": "unknown",
    "_url": "https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM?optimize_streaming_latency=0",
    "readyState": 4,
    "responseHeaders": {
      "Access-Control-Allow-Origin": "*",
      "Alt-Svc": "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000",
      "Content-Length": "14628",
      "Content-Type": "audio/mpeg",
      "Date": "Sun, 24 Sep 2023 17:47:47 GMT",
      "Server": "uvicorn",
      "Via": "1.1 google",
      "access-control-allow-headers": "*",
      "access-control-allow-methods": "POST, OPTIONS, DELETE, GET",
      "access-control-expose-headers": "request-id, history-item-id",
      "history-item-id": "JiQpbUIpMEd7CISACwFC",
      "request-id": "Z0nf4ZDhNYNkdVFGKmyk"
    },
    "responseURL": "https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM?optimize_streaming_latency=0",
    "status": 200,
    "timeout": 0,
    "upload": {},
    "withCredentials": true
  },
  "status": 200,
  "statusText": "undefined"
}
mo49yndu

mo49yndu1#

我也遇到过ElevenLabs的问题,这是我的解决方案:

import { AVPlaybackStatusSuccess, Audio } from 'expo-av'
import ReactNativeBlobUtil from 'react-native-blob-util'


//-----------------------------
// Utils functions

// Fetch file as a blob, cache it and return the file path
async function fetchAudioFromElevenLabsAndReturnFilePath(
  text: string,
  apiKey: string,
  voiceSettings: string,
  voiceId: string,
): Promise<string> {
  const baseUrl = 'https://api.elevenlabs.io/v1/text-to-speech'
  const headers = {
    'Content-Type': 'application/json',
    'xi-api-key': apiKey,
  }

  const requestBody = {
    text,
    voice_settings: voiceSettings,
  }

  const response = await ReactNativeBlobUtil.config({
    // add this option that makes response data to be stored as a file,
    // this is much more performant.
    fileCache: true,
    appendExt: 'mp3',
  }).fetch(
    'POST',
    `${baseUrl}/${voiceId}`,
    headers,
    JSON.stringify(requestBody),
  )
  const { status } = response.respInfo

  if (status !== 200) {
    throw new Error(`HTTP error! status: ${status}`)
  }

  return response.path()
}

// wait for a sound to finish playing
const waitForDiJustFinishedPlaying = (sound: Audio.Sound) =>
  new Promise(resolve => {
    sound.setOnPlaybackStatusUpdate(
      (playbackStatus: AVPlaybackStatusSuccess) => {
        if (playbackStatus.didJustFinish) {
          resolve(null)
        }
      },
    )
  })

 

//-----------------------------
// Run the logic

const path = await fetchAudioFromElevenLabsAndReturnFilePath(...) // your params here

const { sound } = await Audio.Sound.createAsync(
  {
    uri: `file://${path}`,
  },
  {
    shouldPlay: true,
    progressUpdateIntervalMillis: 10, // to check for file finished playing
  },
)

await waitForDiJustFinishedPlaying(sound)

// Don't forget to clean the cache when you're done playing the file, it is not done automatically
ReactNativeBlobUtil.fs.unlink(path)
  • 编辑:我之前的回答提到使用base64,这不是正确的解决方案。此外,较新版本的iOS(17.0)无法播放base64音频文件。

相关问题