Загрузите файл, но установите Content-Type

Я заставил Watson Speech-to-Text работать в Интернете. Теперь я пытаюсь сделать это, реагируя на родной, но получаю ошибки при загрузке файла.

Я использую HTTPS Watson API. Мне нужно установить Content-Type, иначе Watson вернет ответ об ошибке. Однако в системе react-native, чтобы загрузка файла работала, нам, кажется, нужно установить 'Content-Type' в 'multipart/form-data'. Есть ли способ загрузить файл в react-native при установке Content-Type на 'audio/aac'?

Если я установил 'Content-Type': 'multipart/form-data', Watson API выдает ошибку:

{
    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
}

Тело ответа:

{
   "code_description": "Bad Request", 
   "code": 400, 
   "error": "No JSON object could be decoded"
}

Вот мой код (полный код здесь - 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}"`);
}

Вот скриншот ошибки, которую я получаю, когда устанавливаю 'Content-Type': 'audio/aac':


person Noitidart    schedule 22.05.2017    source источник


Ответы (2)


Согласно документации для составных запросов запрос должен быть:

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"

Таким образом, content-type должно быть multipart/form-data, вы можете указать aac как "part_content_type": "audio/aac".

Ваша большая проблема заключается в том, что audio/aac не поддерживается форматы. Возможно, вам понадобится другой кодек.

person Nikolay Shmyrev    schedule 22.05.2017
comment
Ой, блин. Большое спасибо, @Nikolay! Постараюсь найти конвертер. Похоже, что какие-либо аудиоформаты iOS или Android не поддерживаются Bluemix. Кодировки, поддерживаемые на iOS: lpcm, ima4, aac, MAC3, MAC6, ulaw, alaw, mp1, mp2, alac, amr Кодировки, поддерживаемые на Android: aac, aac_eld, amr_nb, amr_wb, he_aac, vorbis. Единственное общее между ними было aac, поэтому я использовал это, ха-ха - person Noitidart; 22.05.2017
comment
Привет, @Noitidart, служба Watson STT поддерживает некоторые из этих кодеков, например, ulaw для iOS или vorbis для Android. См. Эту ссылку: ibm.com/watson/developercloud /doc/speech-to-text/input.html - person Daniel Bolanos; 23.05.2017
comment
@DanielBolanos, черт возьми, круто !!! Большое спасибо за то, что поделился этим со мной, Даниэль! Я думал, что ни один из них не поддерживается, поэтому искал повсюду, как конвертировать из AAC. Попробую их и расскажу, как это происходит! :) - person Noitidart; 24.05.2017
comment
@DanielBolanos У меня было забавное времяпрепровождение на Android, кажется, есть два типа vorbis: ogg и webm. Я не могу понять, какой из них мне дает Android. Вы знаете случайно? Я знаю, что Google Chrome предоставляет версию webm, и это не работает с watson - stackoverflow.com/q/44127061/1828637 - person Noitidart; 27.05.2017
comment
Привет, @Noitidart! Служба IBM Watson STT поддерживает vorbis внутри контейнеров webm и ogg, поэтому webm + vorbis должен работать, если это не работает для вас, какую ошибку вы получите? Из документации (ibm.com/watson/developercloud/ doc / speech-to-text / index.html): Аудиоформаты: транскрибирует свободный аудиокодек без потерь (FLAC), линейную 16-битную импульсно-кодовую модуляцию (PCM), формат аудиофайла формы волны (WAV), Ogg формат с кодеком Opus или Vorbis, формат Web Media (WebM) с кодеком Opus или Vorbis, аудиоданные mu-law (или u-law) или базовый звук. - person Daniel Bolanos; 30.05.2017
comment
Спасибо, Дэниел, это странно, если он поддерживается, почему он не будет работать в Chrome. По умолчанию он дает webm + vorbis, как я думал. На Android я сразу бросился загружать в IBM, у меня все еще есть проблемы с записью, я должен исправить это перед загрузкой, ха-ха - person Noitidart; 30.05.2017

Большое спасибо DanielBolanos и NikolayShmyrev, это решение, которое я использовал:

Этот код предназначен для iOS, поэтому я записал звук как blah.ulaw, НО part_content_type - это aduio/mulaw;rate=22050, это очень важно использовать mulaw, даже если файл ext равен ulaw. Интересное замечание: мне не удалось воспроизвести файл blah.ulaw на рабочем столе macOS.

Также обратите внимание, что вы НЕ ДОЛЖНЫ устанавливать Content-Type на multipart/form-data, это уничтожит boundary.

Также Bluemix требует, чтобы в параметре part_content_type была указана скорость для 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
});
person Noitidart    schedule 26.05.2017