10

サーバー側の API に対して「AJAX」リクエストを行うと、オーディオを再生できません。

IBM の Watson Text-to-Speech サービスを使用してテキストから音声を提供するバックエンド Node.js コードがあります。

var render = function(request, response) {
    var options = {
        text: request.params.text,
        voice: 'VoiceEnUsMichael',
        accept: 'audio/ogg; codecs=opus'
    };

    synthesizeAndRender(options, request, response);
};

var synthesizeAndRender = function(options, request, response) {
    var synthesizedSpeech = textToSpeech.synthesize(options);

    synthesizedSpeech.on('response', function(eventResponse) {
        if(request.params.text.download) {
            var contentDisposition = 'attachment; filename=transcript.ogg';

            eventResponse.headers['content-disposition'] = contentDisposition;
        }
    });

    synthesizedSpeech.pipe(response);
};

私はそれを処理するためのクライアント側のコードを持っています:

var xhr = new XMLHttpRequest(),
    audioContext = new AudioContext(),
    source = audioContext.createBufferSource();

module.controllers.TextToSpeechController = {
    fetch: function() {
        xhr.onload = function() {
            var playAudio = function(buffer) {
                source.buffer = buffer;
                source.connect(audioContext.destination);

                source.start(0);
            };

            // TODO: Handle properly (exiquio)
            // NOTE: error is being received
            var handleError = function(error) {
                console.log('An audio decoding error occurred');
            }

            audioContext
                .decodeAudioData(xhr.response, playAudio, handleError);
        };
        xhr.onerror = function() { console.log('An error occurred'); };

        var urlBase = 'http://localhost:3001/api/v1/text_to_speech/';
        var url = [
            urlBase,
            'test',
        ].join('');

        xhr.open('GET', encodeURI(url), true);
        xhr.setRequestHeader('x-access-token', Application.token);
        xhr.responseType = 'arraybuffer';
        xhr.send();
    }
}

バックエンドは期待どおりの音声を返しますが、成功メソッドの playAudio は呼び出されません。代わりに、handleError が常に呼び出され、エラー オブジェクトは常に null です。

私が間違っていることと、これを修正する方法を誰かが説明できますか? それは大歓迎です。

ありがとう。

注: URL の文字列「test」は、バックエンドでテキスト パラメータになり、synthesizeAndRender のオプション変数になります。

4

1 に答える 1

14

残念ながら、Chrome の HTML5 Audio 実装とは異なり、Chrome の Web Audioは audio/ogg;codecs=opus をサポートしていません。これは、リクエストでここで使用されているものです。これを機能させるには、フォーマットを に設定する必要がありますaudio/wav。確実にサーバー リクエストに渡されるように、クエリ文字列 ( accept=audio/wav, urlencoded) に入れることをお勧めします。

オーディオを再生したいだけですか、それともオーディオ変換のために Web Audio API にアクセスする必要がありますか? オーディオを再生するだけの場合は、HTML5 Audio API (Web Audio API ではありません) を使用して簡単に再生する方法を紹介します。そして、HTML5 オーディオでは、以下の手法を使用してストリーミングでき、最適なaudio/ogg;codecs=opus形式を使用できます。

次のような方法で DOM からクエリを実行して、audio 要素のソースを動的に設定するのと同じくらい簡単です。

(HTML)

<audio id="myAudioElement" />

(あなたのJSで)

var audio = document.getElementById('myAudioElement') || new Audio();
audio.src = yourUrl;

XMLHttpRequest を介して audio 要素のソースを設定することもできますが、ストリーミングは取得できません。ただし、POST メソッドを使用できるため、GET 要求のテキストの長さに制限されません (この API の場合、最大 6KB)。xhr で設定するには、blob 応答からデータ uri を作成します。

    xhr.open('POST', encodeURI(url), true);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.responseType = 'blob';
    xhr.onload = function(evt) {
      var blob = new Blob([xhr.response], {type: 'audio/ogg'});
      var objectUrl = URL.createObjectURL(blob);
      audio.src = objectUrl;
      // Release resource when it's loaded
      audio.onload = function(evt) {
        URL.revokeObjectURL(objectUrl);
      };
      audio.play();
    };
    var data = JSON.stringify({text: yourTextToSynthesize});
    xhr.send(data);

ご覧のとおり、XMLHttpRequest では、データが完全に読み込まれて再生されるまで待つ必要があります。非常に新しい Media Source Extensions API を使用して、XMLHttpRequest からストリーミングする方法があるかもしれません。これは現在、Chrome と IE でのみ利用できます (Firefox や Safari では利用できません)。これは私が現在実験しているアプローチです。成功したらここで更新します。

于 2015-05-25T20:35:20.890 に答える