ruby-on-rails 法拉第请求接收音频blob

oxcyiej7  于 2023-03-04  发布在  Ruby
关注(0)|答案(1)|浏览(120)

我有一个React前端和一个Ruby on Rails后端。我使用了一个第三方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 => {
    //. . .
    }

但是,我似乎无法在后端正确配置Faraday POST请求(它通过对/voice-api-proxy的POST请求触发)。
这是我目前的尝试:

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

我知道这里有一些多余的配置,因为我在玩一些不同的选项...请随意忽略所有这些。
同样,我的主要目标只是返回与成功的前端请求相同类型的响应。
我认为问题是如何设置法拉第来处理斑点...
谢谢你的帮助。

4smxwvx5

4smxwvx51#

我意识到我还可以使用responseType:API代理调用的“blob'...”
这里是后端

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);
   });
}

相关问题