Реагировать нативно. Двоичная строка MP3 (Uint8Array(9549)) для потоковой передачи или файла

Я пытаюсь воспроизвести аудиофайл в формате двоичной строки, который возвращает Amazon Polly. Для этого я использую «React-native-fetch-blob» и читаю поток, но просто продолжаю получать ошибки от моста, говоря: «Недопустимое сообщение данных — все должно быть длиной: 8». Это происходит, когда я пытаюсь открыть поток: ifstream.open()

Это код:

//polly config
const params = {
    LexiconNames: [], 
    OutputFormat: "mp3", 
    SampleRate: "8000", 
    Text: "All Gaul is divided into three parts", 
    TextType: "text", 
    VoiceId: "Joanna"
};

Polly.synthesizeSpeech(params, function(err, data) {
    let _data = "";
    RNFetchBlob.fs.readStream(
        // file path
        data.AudioStream,
        // encoding, should be one of `base64`, `utf8`, `ascii`
        'ascii'
    )
    .then((ifstream) => {
        ifstream.open()
        ifstream.onData((chunk) => {
            _data += chunk
        })
        ifstream.onError((err) => {
            console.log('oops', err.toString())
        })
        ifstream.onEnd(() => {  
            //pasing _data to streaming player or normal audio player
            ReactNativeAudioStreaming.play(_data, {showIniOSMediaCenter: true, showInAndroidNotifications: true});
        })  
    })
}); 

Еще одно решение, которое я также пробовал, — сохранить поток в файл, чтобы загрузить его позже, но у меня были похожие ошибки. RNFetchBlob.fs.createFile("myfile.mp3", dataG.AudioStream, 'ascii');

Заранее огромное спасибо


person rubelux    schedule 04.08.2017    source источник
comment
Где определяется _data? Можете ли вы указать полный путь к аудиофайлу в вопросе?   -  person guest271314    schedule 04.08.2017
comment
Почему вы запрашиваете Blob, если вы ожидаете прочитать поток Uint8Array порциями?   -  person guest271314    schedule 04.08.2017
comment
@guest271314, спасибо за помощь.   -  person rubelux    schedule 05.08.2017
comment
Не волнуйтесь. У вас нет опыта использования react-native, amazon-polly или react-native-fetch-blob, хотя вы пробовали fetch() и ReadableStream и различные методы преобразования текста в речь в браузере Как использовать Web Speech API в chromium?, Как создать или преобразовать текст в аудио в браузере хрома?, Как захватить сгенерированный звук из вызова window.speechSynthesis.speak()?   -  person guest271314    schedule 05.08.2017
comment
Я только что добавил весь недостающий код, включая функцию AWS Polly. Что касается запроса Blob, я не совсем уверен, я хотел бы просто сделать Uint8Array формат, совместимый с проигрывателем реакции. Может быть, поместить все куски в один массив и сохранить в файл. идеи?   -  person rubelux    schedule 05.08.2017
comment
Вы можете использовать Response.arrayBuffer() при вызове fetch(), а затем передать буфер массива в new Uint8Array(), хотя, опять же, у вас нет опыта использования реакции   -  person guest271314    schedule 05.08.2017
comment
Кто-нибудь решил это еще? Я использую react-native-video и имею ту же проблему.....   -  person Shawn    schedule 08.04.2020


Ответы (2)


Вы можете использовать fetch() для запроса одного или нескольких медиа-ресурсов, вернуть Response.body.getReader() из .then(), чтобы получить ReadableStream ответа. Прочитайте значения Uint8Array, возвращенные как поток, как прочитанные с помощью метода .read() из ReadableStream, добавьте к значению SourceBuffer из MediaSource для потоковой передачи мультимедиа в HTMLMediaElement.

Например, для последовательного вывода звука двух запрошенных аудиоресурсов

window.addEventListener("load", () => {

  const audio = document.createElement("audio");

  audio.controls = "controls";

  document.body.appendChild(audio);

  audio.addEventListener("canplay", e => {
    audio.play();
  });

  const words = ["hello", "world"];

  const mediaSource = new MediaSource();

  const mimeCodec = "audio/mpeg";

  const mediaType = ".mp3";

  const url = "https://ssl.gstatic.com/dictionary/static/sounds/de/0/";

  Promise.all(
      words.map(word =>
        fetch(`https://query.yahooapis.com/v1/public/yql?q=select * from data.uri where url="${url}${word}${mediaType}"&format=json&callback=`)
        .then(response => response.json())
        .then(({
            query: {
              results: {
                url
              }
            }
          }) =>
          fetch(url).then(response => response.body.getReader())
          .then(readers => readers)
        )
      )
    )
    .then(readers => {

      audio.src = URL.createObjectURL(mediaSource);
      mediaSource.addEventListener("sourceopen", sourceOpen);

      async function sourceOpen() {
        var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
        // set `sourceBuffer` `.mode` to `"sequence"`
        sourceBuffer.mode = "segments";

        const processStream = ({
          done,
          value
        }) => {
          if (done) {
            return;
          }
          // append chunk of stream to `sourceBuffer`
          sourceBuffer.appendBuffer(value);
        }
        // at `sourceBuffer` `updateend` call `reader.read()`,
        // to read next chunk of stream, append chunk to 
        // `sourceBuffer`
        for (let [index, reader] of Object.entries(readers)) {
          sourceBuffer.addEventListener("updateend", function() {
            reader.read().then(processStream);
          });

          let stream = await reader.read().then(processStream)
            .then(() => reader.closed)
            .then(() => "done reading stream " + index);

          console.log(stream);
        }

      }
    })
}) 

plnkr http://plnkr.co/edit/9zHwmcdG3UKYMghD0w3q?p=preview

person guest271314    schedule 04.08.2017
comment
К сожалению, этот код не будет работать на React Native из-за отсутствия SourceBuffer и поддержки Uint8Array. - person rubelux; 05.08.2017
comment
@ user2956369 Зачем вам нужно использовать React Native? - person guest271314; 05.08.2017
comment
Этот код представляет собой нативное мобильное приложение, которое React Native компилирует в пакет JS, это не стандартный JS. - person rubelux; 05.08.2017