Watson SpeechToText Java和javascript模型差异

时间:2016-09-18 19:47:46

标签: json spring-mvc speech-to-text ibm-watson

我正在使用Watson Java SDK将watson-speech.js javascript库与基于Spring的服务器集成。我正试图将WatsonSpeech.SpeechToText.recognizeMicrophone调用的输出发送到服务器而没有运气。 Speech java类似乎具有与客户端发送的json匹配的相应@SerializedName注释,但我从Jackson获得了UnrecognizedPropertyException个错误。

Unrecognized field "keywords_result" (class com.ibm.watson.developer_cloud.speech_to_text.v1.model.SpeechResults), not marked as ignorable (2 known properties: "resultIndex", "results"])

这是控制器方法:

    @RequestMapping(value = "/postWatsonRequest", method = RequestMethod.POST)
    @ResponseBody
    @ResponseStatus(value=HttpStatus.OK)
    public ResponseObject postWatsonRequest(@RequestBody SpeechResults speechResults) {
    ...
    }

我显然遗漏了一些东西。我是否需要在服务器端手动解压缩json(自定义反序列化器?)或将其格式化为客户端可接受的json字符串?

1 个答案:

答案 0 :(得分:3)

我发现这是一个错误,虽然我不确定这是否是最好的解决方案。这是任何有兴趣的人的完整代码。使其发挥作用的关键因素:

  • 您必须使用receive-jason事件来捕获完整的json结果。 data事件似乎仅返回最终文本
  • 结果数据必须包装在有效的json包装器中 - data:{message:data}(这是我的大错误)
  • 不要在ajax调用中包含contentType: 'application/json; charset=utf-8',,否则控制器将无法识别json数据
  • Watson Java SDK WebSocketManager从Watson收到okhttp3.ResponseBody,从中提取字符串。我认为这与javascript SDK收到的类似,所以我使用WebSocketManager中的相同代码将JSON.stringify字符串转换为控制器中的SpeechResults对象。

来自okhttp3.ResponseBody javadoc:

  

从源服务器到客户端应用程序的一次性流,包含响应主体的原始字节

Watson javascript

function listen(token) {
    stream = WatsonSpeech.SpeechToText.recognizeMicrophone({
        token: token,
        readableObjectMode: true,
        objectMode: true,
        word_confidence: true,
        format: false,
        keywords: keywordsArray,
        keywords_threshold : 0.5,
        continuous : false
        //interim_results : false
        //keepMicrophone: navigator.userAgent.indexOf('Firefox') > 0
    });

    stream.setEncoding('utf8');

    stream.on('error', function(err) {
        console.log(err);
        stream.stop();
    });

    stream.on('receive-json', function(msg) {
        console.log(msg);
        if (msg.state != 'listening') {
            if (msg.results[0].final) {
                console.log('receive-json: ' + msg);
                postResults(msg);               
                stream.stop();
            }
        }
    });
}

Ajax帖子

function postResults(results) {
    var data = JSON.stringify(results);
    console.log('stringify: ' + data);
    $.ajax({
        type: 'POST',
        url: appContextPath + '/postWatsonResult',
        dataType: 'json',
        data: {message:data}
    })
    .done(function(data) {
        console.log('done data: '+ data);
    })
    .fail(function(jqXHR, status, error) {
        var data = jqXHR.responseJSON;
        console.log('fail data: '+ data);
    });
}

Spring控制器

@RequestMapping(value = "/postWatsonResult", method = RequestMethod.POST)
@ResponseBody
@ResponseStatus(value=HttpStatus.OK)
public ResponseObject postWatsonResult(@RequestParam("message") String message, Locale locale) {
    logger.info("postWatsonRequest");
    JsonObject json = new JsonParser().parse(message).getAsJsonObject();
    SpeechResults results = null;
    if (json.has("results")) {
        results = GSON.fromJson(message, SpeechResults.class);
    }
    if (results != null) {
        logger.debug("results: " + results.getResults().get(0).getAlternatives().get(0).getTranscript());
    }

    return new ResponseObject();
}

我仍然认为应该可以某种方式使用@RequestBody SpeechResults speechResults所以我会继续玩这个,但至少我有一个有效的解决方案。