如何在 cordova 应用程序中使用 Watson Text2Speech REST API?

How to use the Watson Text2Speech REST API in a cordova App?

有很多示例:如何在 Node.JS 中使用 Watson 服务,但是如果您将 REST API 与 HTTP 调用一起使用,我 运行 会遇到授权问题。

API的documentation讲述了命令行curl界面, 但是没有针对 Web 或混合应用程序 使用 javascript.

HTTP 调用 的具体示例

在我的情况下,我想在 cordova 移动应用程序中使用 Watson Text2Speech,为此我将建立一个工厂。

我使用的 http 调用确实适用于其他 APIs,但是我在这里做错了什么? 缺少格式吗?

有人能帮忙吗?

看起来像这样:

.factory('GetSpeech', ['$http','$cordovaDialogs','$cordovaMedia','Base64', function($http,
                                                                                    $cordovaDialogs,
                                                                                    $cordovaMedia,
                                                                                    Base64){
  // http://ngcordova.com/docs/plugins/media/
  // https://www.ibm.com/watson/developercloud/doc/speech-to-text/input.shtml
  // https://www.npmjs.com/package/cordova-plugin-speech-recognition-feat-siri
  var watson_url = "https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize";
  var watson_token_url = "https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/text-to-speech/api";
  var watson_token = "";
  var username='YOUR_KEY';
  var password='YOUR_PW';
  var authdata = 'Basic ' + Base64.encode(username + ':' + password);
  console.log(">>> Watson - authdata: ",authdata);
  var the_get_header = "{'Authorization':'"+ authdata +"','Content-Type':'application/json'}";

  var message = "";

  var getSpeech_innner = function (){ $http({method: 'GET',
                                            url:  watson_token_url,
                                            headers: the_get_header
                                       }).then( function successCallback(response) {
                                           console.log(">>> GetToken  Success:",response);
                                           watson_token=response;
                                           var the_post_header = "{'X-Watson-Authorization-Token':'"+ watson_token +"','Content-Type':'application/json','Accept':'audio/wav'}";
                                           var the_post_text = JSON.stringify({ "text":"This is the first sentence of the paragraph. Here is another sentence. Finally, this is the last sentence."
                                                                              });
                                           $http({
                                              method: 'POST',
                                              url: watson_url,
                                              headers: the_post_header,
                                              data: the_post_text
                                            }).then(function successCallback(response) {
                                                // this callback will be called asynchronously
                                                // when the response is available
                                                console.log(">>> GetSpeech Success:",response);
                                                message = "Success: " + response;
                                                alert(message);
                                                return true;
                                                }, function errorCallback(response) {
                                                  // called asynchronously if an error occurs
                                                  // or server returns response with an error status.
                                                  console.log(">>> GetSpeech  Error:",response);
                                                  message = "Error: " + response;
                                                  alert(message);
                                                  return false;
                                                })
                                            }, function errorCallback(response) {
                                               console.log(">>> GetToken  Error:",response);
                                            });
                                      };
  return {
    getSpeech :  getSpeech_innner
  };

}])

注意:顺便说一句,在邮递员中,HTTP 调用工作正常。 GET TokenPOST 合成.

我试过类似的方法:

  $http({
    method: 'POST',
    url: tts_url,
    headers: {
          'Access-Control-Allow-Origin': '*',
          'Access-Control-Allow-Headers': 'access-control-allow-headers, Authorization',
          'content-type': 'application/json',
          'Authorization': 'Basic <base64(uid:password)>',
          'Accept': 'audio/wav'
          },
    data: {'\"text\"': '\"hello world\"' },
    output: 'hello_world.wav'
    }).then(function successCallback(response) {
      console.log(">>> Success:",response.status);
    }, function errorCallback(response) {
      console.log(">>> Error:", response.status);
  });

我会得到这个错误:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize. (Reason: missing token 'access-control-allow-headers' in CORS header 'Access-Control-Allow-Headers' from CORS preflight channel).

行为相同,当我删除 "Access-Control-Allow-Headers" header 中的 "access-control-allow-headers" 条目时...

运行 同样在 postman 中工作正常。

如何让我的 cordova 应用程序调用远程资源?

您是否已在 Cordova 应用程序中将 stream.watsonplatform.net 来源列入白名单?在我看来,域被阻止了。此处有关白名单的详细信息:https://cordova.apache.org/docs/en/latest/guide/appdev/whitelist/

根据我的情况,我想直接从 service broker 获取令牌。

目前看来,为了与text2speech service进行通信,我需要一个额外的server app,例如[= Node.JS Server 上的 74=],它为 cordova app 客户端提供 token .

文档中提供了 服务器令牌应用程序 的示例代码。

这在使用令牌主题的编程模型一章中有记录。 Watson Documentation Link

这与 watson 服务的开发模型有关。 原因是允许 Postman 和 CURL 调用,而 Web 或移动应用程序的其他请求不是有效来源。

因此您可以直接从移动应用程序或 Web 应用程序使用 REST API。同样的情况,是通过使用 Watson IoT。 这就是我使用 Browserify Sample GitHub Project: browserfied-ibmiotf-webapplication

在 Angular Web 应用程序中使用节点框架的原因

为了更好地理解 Watson API 文档中的一张图片。 这记录在使用令牌主题的编程模型一章中。 Watson Documentation Link

@感谢 Rene 和 Andrew 指出我的方向。

现在我有一个可以使用 Text2Speech 的 cordova 应用程序。 我在这个示例中没有使用 token,语音直接从 Node.JS 服务器提供给移动应用程序。

@感谢 Andrii,提供一些代码来做到这一点。

Node.JS 服务器:

app.get('/getText2SpeechOutput', function (req, res) {
    console.log(' -> text function called');

    console.log('     calling watson to synthesize -> ', req.header('synthesize-text'));

    var text_to_speech_l = new Text2speech({
        username: req.header('service-username'),
        password: req.header('service-password'),
    });

    var params = {
        text: req.header('synthesize-text'),
        voice: 'en-US_AllisonVoice',
        accept: 'audio/wav'
    };

    var tempaudio = text_to_speech_l.synthesize(params);
    console.log('     response received from Watson');
    var reader = new wav.Reader();

    reader.on('format', function (format) {

        console.log('     file read success');
        var writer = new wav.FileWriter('output.wav', {
                channels: 1,
                sampleRate: 22050,
                bitDepth: 16
            });

        reader.pipe(writer);

        console.log('     file write success');

        writer.pipe(res)

        console.log(' <- response provided');
    });

    tempaudio.pipe(reader);
})

Cordova 应用程序:

 var getSpeech_innner = function (thetext, callback){
                            //const fileTransfer = new FileTransfer();
                            var headers = {
                              "Authorization": authdata,
                              "Accept": "audio/wav",
                              "synthesize-text": thetext,
                              "service-username": username,
                              "service-password": password
                            };

                            var options = {
                              headers: headers,
                              replace: true
                            };

                            $cordovaFileTransfer.download(get_speech_url , cordova.file.dataDirectory + 'speech.wav', options, true).then(
                              function (FileEntry) {
                                console.debug('>>> Success', FileEntry);
                                var filePath = cordova.file.dataDirectory + 'speech.wav';
                                callback(filePath);
                              },
                              function (error) {
                                console.debug('>>> download failure', error);
                                callback(error);
                              });
                        };