法拉第请求接收音频 blob

问题描述 投票:0回答:1

我有一个带有 Ruby on Rails 后端的 React 前端。我正在使用将文本转换为语音的第 3 方 API。您提交文本,它会发回一个音频文件给您。

我可以这样让它在前端工作:

const handleClick = () => {
    axios.post('theUrlForThePost', {
        text: 'Test Message',
        voice_settings: {
          stability: 0.5,
          similarity_boost: 1
        }
      },
    {
        headers: {
            'accept': 'audio/mpeg',
            'xi-api-key': `<<HIDDEN>>`,
            'Content-Type': 'application/json'
        },
        responseType: 'blob'
    })
    .then(response => {
        const url = window.URL.createObjectURL(new Blob([response.data]));
        const audio = new Audio(url);
        audio.play();
        console.log('audio played')
      })
   .catch(error => {
     console.log(error);
   });
}

但是,我喜欢在后端发生请求,以确保我的 API 密钥安全。所以在前端我想:

axios.post(`${BASE_URL}/voice-api-proxy`)
    .then(response => {
    //. . .
    }

但是,我似乎无法在后端正确配置法拉第 POST 请求(它通过对 /voice-api-proxy 的发布请求触发)。

这是我目前的尝试:

conn = Faraday.new(
            url: 'theBaseURLOfThePost',
            headers: { 
                'Content-Type': 'application/json', 
                'xi-api-key': api_key,
                'Accept': 'audio/mpeg',
            }
        ) do |faraday|
            faraday.use Faraday::Response::RaiseError, raise_error: false
            faraday.response :detect_content_type
            faraday.response :logger
            faraday.response :json, content_type: /\bjson$/
            faraday.response :xml, content_type: /\bxml$/
            faraday.response :blob, content_type: %r{\b(audio|video|image)/.*\b}
            faraday.adapter Faraday.default_adapter
        end
            
        response = conn.post('thePostPathOfTheURL') do |req|
            req.body = {
                text: 'Test Message',
                voice_settings: {
                    stability: 0.5,
                    similarity_boost: 1
                }
            }.to_json
        end
        
        if response.success?
            send_data response.body, type: 'audio/mpeg', disposition: 'inline'
          else
            render json: { error: 'Error occurred' }, status: :unprocessable_entity
        end
        
        rescue Faraday::Error => e
          render json: { error: e.message }, status: :unprocessable_entity

我知道这里有一些多余的配置,因为我正在尝试一些不同的选项......请随意忽略所有这些。

同样,我的主要目标只是返回与我成功的前端请求相同的响应。

我认为这个问题与如何设置法拉第来处理斑点有关......

感谢您的帮助。

reactjs ruby-on-rails ruby rest blob
1个回答
0
投票

我意识到我也可以使用 responseType: 'blob' 我的 API 代理调用...

这里是后端

def proxy
       conn = Faraday.new(url: "theUrlForThePost") do |faraday|
            faraday.headers["accept"] = "audio/mpeg"
            faraday.headers["Content-Type"] = "application/json"
            faraday.headers["xi-api-key"] = api_key
        end
          
          response = conn.post do |req|
            req.body = {
              text: 'Test Message',
              voice_settings: {
                stability: 0.5,
                similarity_boost: 1
              }
            }.to_json
          end
          
        render json: response.body
end

前端:

const proxyPost = () => {
    axios.post(`${BASE_URL}/voice-api-proxy`, {
        // request body
    }, {
    responseType: 'blob'
    }).then(response => {
        const binaryData = response.data
        const blob = new Blob([binaryData], { type: 'audio/mpeg' });
        const audioURL = URL.createObjectURL(blob);
        const audio = new Audio(audioURL);
        audio.play(); 
    })
   .catch(error => {
     console.log(error);
   });
}
© www.soinside.com 2019 - 2024. All rights reserved.