【问题标题】:How to use the Watson Text2Speech REST API in a cordova App?如何在 cordova 应用程序中使用 Watson Text2Speech REST API?
【发布时间】:2017-02-07 08:25:45
【问题描述】:

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

API 的documentation 讲述了命令行curl界面, 但是对于 Web 或混合应用程序使用 javascriptHTTP 调用 没有具体示例。

在我的情况下,我想在 Cordova 移动 APP 中使用 Watson Text2Speech,为此我要建立一个工厂。

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

谁能帮忙?

看起来像这样:

.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 合成

【问题讨论】:

    标签: javascript rest cordova ibm-cloud ibm-watson


    【解决方案1】:

    我也尝试过类似的方法:

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

    我会收到这个错误:

    跨域请求被阻止:同源策略不允许读取 远程资源在 https://stream.watsonplatform.net/text-to-speech/api/v1/synthesize。 (原因:CORS 标头中缺少令牌“访问控制允许标头” 来自 CORS 预检通道的“Access-Control-Allow-Headers”)。

    当我删除“Access-Control-Allow-Headers”标题中的“access-control-allow-headers”条目时,行为是相同的......

    在邮递员中运行相同的工作正常。

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

    【讨论】:

    • Access-Controll-* 标头属于响应,而不是请求。
    • CORS 问题的原因是您处于开发模式。直接在设备上进行测试应该可以工作。有很多方法可以解决这个问题,例如在 ionic 中设置代理,在浏览器中禁用 cors。这是一个很好的参考:blog.ionic.io/handling-cors-issues-in-ionic
    • @Sebstian 请参阅ibm.com/watson/developercloud/doc/getting_started/… 我会说这取决于内部用于 watson 服务的开发模型。原因是允许 Postman 和 CURL 调用,而 Web 或移动应用程序的其他请求则不允许。因此,您不能从移动应用程序或 Web 应用程序直接使用 REST API。同样的情况是使用 Watson IoT。这就是我在 Angular Web App github.com/thomassuedbroecker/… 中使用节点框架的原因。
    【解决方案2】:

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

    【讨论】:

    • 这是我的 config.xml 条目并且 允许所有,所以 stream.watsonplatform.net*.watsonplatform.net 应该不是问题 :thinking_face::disappointed: Extract config.xml
    【解决方案3】:

    我想直接从服务代理获取令牌。

    目前看来,为了与 text2speech 服务 进行通信,我需要一个额外的 server app,例如在 Node.JS Server,它为 cordova 应用程序 客户端提供 token

    服务器令牌应用程序的示例代码可在文档中找到。

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

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

    因此,您可以直接从移动应用程序或 Web 应用程序使用 REST API。同样的情况是使用 Watson IoT。 这就是为什么我通过 Browserify Sample GitHub Project: browserfied-ibmiotf-webapplication 在 Angular Web App 中使用节点框架的原因@

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

    @感谢 Rene 和 Andrew 为我指明了这个方向。

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

    @Thanks 感谢 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);
                                  });
                            };
    

    【讨论】:

    • 令牌实际上来自 DataPower 边缘路由器(蓝色步骤 3),但您在这里的想法是正确的 - 客户端使用仍然需要服务器来生成令牌。
    • @Thomas.Thanks 这对节点 js 非常有帮助...我在邮递员中以某种不可读的格式收到 RIFF **** 的响应..当我们触发它时如何进行下载邮递员打来电话
    猜你喜欢
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 2016-10-29
    • 2018-10-28
    • 2011-12-30
    • 1970-01-01
    • 2017-10-11
    • 2016-03-15
    相关资源
    最近更新 更多