问题
I got Watson Speech-to-Text working on the web. I am now trying to do it on react native but am getting errors on the file upload part.
I am using the HTTPS Watson API. I need to set the Content-Type
otherwise Watson returns a error response. However in react-native, for the file upload to work, we seem to need to set 'Content-Type'
to 'multipart/form-data'
. Is there anyway to upload a file in react-native while setting Content-Type to 'audio/aac'
?
The error Watson API gives me if I set 'Content-Type': 'multipart/form-data'
is:
{
type: "default",
status: 400,
ok: false,
statusText: undefined,
headers: Object,
url: "https://stream.watsonplatform.net/speech-to-text/api/v1/recognize?continuous=true",
_bodyInit: Blob,
_bodyBlob: Blob
}
The response body is:
{
"code_description": "Bad Request",
"code": 400,
"error": "No JSON object could be decoded"
}
Here is my code (full code is here - gist.github.com ):
const ext = 'aac';
const file_path = '/storage/emulated/0/Music/enter-the-book.aac';
data.append('file', {
uri: `file://${file_path}`,
name: `recording.${ext}`,
type: `audio/${ext}`
}, `recording.${ext}`);
const response = await fetch('https://stream.watsonplatform.net/speech-to-text/api/v1/recognize?continuous=true', {
method: 'POST',
headers: {
// 'Content-Type': `audio/${ext}`,
'Content-Type': 'multipart/form-data',
'X-Watson-Authorization-Token': token
},
body: data
});
console.log('watson-stt::getResults - response:', response);
if (response.status !== 200) {
const error = await response.text();
throw new Error(`Got bad response "status" (${response.status}) from Watson Speach to Text server, error: "${error}"`);
}
Here is a screenshot of the error I get when I set 'Content-Type': 'audio/aac'
:
回答1:
According to the documentation for multipart requests the request should be:
curl -X POST -u "{username}":"{password}"
--header "Transfer-Encoding: chunked"
--form metadata="{
\"part_content_type\":\"audio/flac\",
\"timestamps\":true,
\"continuous\":true}"
--form upload="@audio-file1.flac"
"https://stream.watsonplatform.net/speech-to-text/api/v1/recognize"
So the content-type
should be multipart/form-data
, you can specify aac as "part_content_type": "audio/aac"
.
The big problem you have is that audio/aac
is not in supported formats. You might probably need another codec.
回答2:
Thanks so much to DanielBolanos and NikolayShmyrev this is the solution I used:
This code is for iOS so I recorded the audio as blah.ulaw
BUT the part_content_type is aduio/mulaw;rate=22050
this is very important to use mulaw
even though file ext is ulaw
. An interesting note: I couldn't play the blah.ulaw
file on my macOS desktop.
Also note that you MUST NOT set Content-Type
to multipart/form-data
this will destroy the boundary
.
Also Bluemix requires rate in the part_content_type for mulaw
const body = new FormData();
let metadata = {
part_content_type: 'audio/mulaw;rate=22050' // and notice "mulaw" here, "ulaw" DOES NOT work here
};
body.append('metadata', JSON.stringify(metadata));
body.append('upload', {
uri: `file://${file_path}`,
name: `recording.ulaw`, // notice the use of "ulaw" here
type: `audio/ulaw` // and here it is also "ulaw"
});
const response = await fetch('https://stream.watsonplatform.net/speech-to-text/api/v1/recognize?continuous=true', {
method: 'POST',
headers: {
// 'Content-Type': 'multipart/form-data' // DO NOT SET THIS!! It destroys the boundary and messes up the request
'Authorization': `Basic ${btoa(`${USERNAME}:${PASSWORD}`)}`
},
body
});
来源:https://stackoverflow.com/questions/44106529/upload-a-file-but-set-content-type