我有一个带有 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
我知道这里有一些多余的配置,因为我正在尝试一些不同的选项......请随意忽略所有这些。
同样,我的主要目标只是返回与我成功的前端请求相同的响应。
我认为这个问题与如何设置法拉第来处理斑点有关......
感谢您的帮助。
我意识到我也可以使用 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);
});
}