如何使用HTML5 Audio API播放从XMLHTTPRequest返回的音频 [英] How do I play audio returned from an XMLHTTPRequest using the HTML5 Audio API

查看:471
本文介绍了如何使用HTML5 Audio API播放从XMLHTTPRequest返回的音频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在向服务器端api发出AJAX请求时,我无法播放音频。

I'm failing to be able to play audio when making an "AJAX" request to my server side api.

我有后端Node.js代码,它使用IBM的Watson Text-to-Speech服务来提供来自文本的音频:

I have backend Node.js code that's using IBM's Watson Text-to-Speech service to serve audio from text:

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);
};

我有客户端代码来处理:

I have client side code to handle that:

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。

The backend returns the audio that I expect, but my success method, playAudio, is never called. Instead, handleError is always called and the error object is always null.

任何人都可以解释我做错了什么以及如何纠正这个问题?非常感谢。

Could anyone explain what I'm doing wrong and how to correct this? It would be greatly appreciated.

谢谢。

注意:URL中的字符串test变为后端的文本参数和最终在synthesizeAndRender的选项变量中。

NOTE: The string "test" in the URL becomes a text param on the backend and and ends up in the options variable in synthesizeAndRender.

推荐答案

不幸的是,与Chrome的HTML5音频实现不同,Chrome的网络音频不支持audio / ogg; codecs = opus ,这是您的请求在此处使用的内容。您需要将格式设置为 audio / wav 才能使其生效。为了确保它传递给服务器请求,我建议将它放在查询字符串中( accept = audio / wav ,urlencoded)。

Unfortunately, unlike Chrome's HTML5 Audio implementation, Chrome's Web Audio doesn't support audio/ogg;codecs=opus, which is what your request uses here. You need to set the format to audio/wav for this to work. To be sure it's passed through to the server request, I suggest putting it in the query string (accept=audio/wav, urlencoded).

您只是想播放音频,还是需要访问Web Audio API进行音频转换?如果您只需要播放音频,我可以向您展示如何使用HTML5音频API(而非Web音频API)轻松播放。使用HTML5 Audio,您可以使用以下技术对其进行流式传输,您可以使用最佳的 audio / ogg; codecs = opus 格式。

Are you just looking to play the audio, or do you need access to the Web Audio API for audio transformation? If you just need to play the audio, I can show you how to easily play this with the HTML5 Audio API (not the Web Audio one). And with HTML5 Audio, you can stream it using the technique below, and you can use the optimal audio/ogg;codecs=opus format.

这就像动态设置音频元素的来源一样简单,通过以下方式从DOM查询:

It's as simple as dynamically setting the source of your audio element, queried from the DOM via something like this:

(以HTML格式)

<audio id="myAudioElement" />

(在你的JS中)

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

您还可以通过XMLHttpRequest设置音频元素的来源,但不会获得流式传输。但由于您可以使用POST方法,因此您不限于GET请求的文本长度(对于此API,大约6KB)。要在xhr中设置它,您可以从blob响应中创建数据uri:

Your can also set the audio element's source via an XMLHttpRequest, but you won't get the streaming. But since you can use a POST method, you're not limited to the text length of a GET request (for this API, ~6KB). To set it in xhr, you create a data uri from a blob response:

    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流式传输的方法,该API目前仅适用于Chrome和IE(无Firefox或Safari)。这是我正在尝试的方法。如果我成功,我会在这里更新。

As you can see, with XMLHttpRequest, you have to wait until the data are fully loaded to play. There may be a way to stream from XMLHttpRequest using the very new Media Source Extensions API, which is currently available only in Chrome and IE (no Firefox or Safari). This is an approach I'm currently experimenting with. I'll update here if I'm successful.

这篇关于如何使用HTML5 Audio API播放从XMLHTTPRequest返回的音频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆