Как проанализировать основной результат из пользовательского навыка alexa в JSON

#ios #swift #alexa #alexa-skill #alexa-app

#iOS #swift #alexa #alexa-навык #alexa-приложение

Вопрос:

Я смог настроить пользовательский навык Alexa и вызвать его из своего приложения для IOS. Когда я тестирую навык в симуляторе консоли Alexa, я вижу вывод JSON, и я хочу получить его из своего приложения для IOS, однако у меня проблема с тем, как его проанализировать. Мой код IOS работает нормально, так как я слышу текстовый ответ от моего пользовательского навыка.

Вот пример вывода JSON, который я хочу получить / проанализировать

     {
        "body": {
            "version": "1.0",
            "response": {
                "outputSpeech": {
                    "type": "SSML",
                    "ssml": "<speak>Hello this is a custom skill</speak>"
                },
                "type": "_DEFAULT_RESPONSE"
            },
            "sessionAttributes": {},
            "userAgent": "ask-node/2.9.0 Node/v10.23.1 sample/hello-world/v1.2"
        }
    }
    
 

Вот код для публикации записи

 func postRecording(authToken:String, jsonData:String, audioData: Data) {
        var request = URLRequest(url: URL(string: EVENTS_ENDPOINT)!)
        //request.cachePolicy = NSURLRequest.CachePolicy.ReloadIgnoringCacheData
        request.httpShouldHandleCookies = false
        request.timeoutInterval = 60
        request.httpMethod = "POST"
        request.setValue("Bearer (authToken)", forHTTPHeaderField: "Authorization")
        
        let boundry = NSUUID().uuidString
        let contentType = "multipart/form-data; boundary=(boundry)"
        
        request.setValue(contentType, forHTTPHeaderField: "Content-Type")
        
        var bodyData = Data()
        
        bodyData.append("--(boundry)rn".data(using: String.Encoding.utf8)!)
        bodyData.append("Content-Disposition: form-data; name="metadata"rn".data(using: String.Encoding.utf8)!)
        bodyData.append("Content-Type: application/json; charset=UTF-8rnrn".data(using: String.Encoding.utf8)!)
        bodyData.append(jsonData.data(using: String.Encoding.utf8)!)
        bodyData.append("rn".data(using: String.Encoding.utf8)!)
        
        bodyData.append("--(boundry)rn".data(using: String.Encoding.utf8)!)
        bodyData.append("Content-Disposition: form-data; name="audio"rn".data(using: String.Encoding.utf8)!)
        bodyData.append("Content-Type: audio/L16; rate=16000; channels=1rnrn".data(using: String.Encoding.utf8)!)
        bodyData.append(audioData)
        bodyData.append("rn".data(using: String.Encoding.utf8)!)
        
        bodyData.append("--(boundry)--rn".data(using: String.Encoding.utf8)!)
        
        session.uploadTask(with: request, from: bodyData, completionHandler: { (data:Data?, response:URLResponse?, error:Error?) -> Void in
            if (error != nil) {
                print("Send audio error: (String(describing: error?.localizedDescription))")
            } else {
                let res = response as! HTTPURLResponse
                if (res.statusCode >= 200 amp;amp; res.statusCode <= 299) {
                    if let contentTypeHeader = res.allHeaderFields["Content-Type"] {
                        let boundary = self.extractBoundary(contentTypeHeader: contentTypeHeader as! String)
                        let directives = self.extractDirectives(data: data!, boundary: boundary)
                        self.directiveHandler?(directives)
                    } else {
                        print("Content type in response is empty")
                    }
                }
            }
        }).resume()
    }

func extractDirectives(data: Data, boundary: String) -> [DirectiveData] {
        var directives = [DirectiveData]()
        
        let innerBoundry = "--(boundary)".data(using: String.Encoding.utf8)!
        let endBoundry = "--(boundary)--".data(using: String.Encoding.utf8)!
        let contentTypeApplicationJson = "Content-Type: application/json; charset=UTF-8".data(using: String.Encoding.utf8)!
        let contentTypeAudio = "Content-Type: application/octet-stream".data(using: String.Encoding.utf8)!
        let headerEnd = "rnrn".data(using: String.Encoding.utf8)!
        
        var startIndex = 0
        while (true) {
            let firstAppearance = data.range(of: innerBoundry, in: startIndex..<(data.count))
            if (firstAppearance == nil) {
                break
            }
            var secondAppearance = data.range(of: innerBoundry, in: (firstAppearance?.upperBound)!..<(data.count))
            if (secondAppearance == nil) {
                secondAppearance = data.range(of: endBoundry, in: (firstAppearance?.upperBound)!..<(data.count))
                if (secondAppearance == nil) {
                    break
                }
            } else {
                startIndex = (secondAppearance?.lowerBound)!
            }
            let subdata = data.subdata(in: (firstAppearance?.upperBound)!..<(secondAppearance?.lowerBound)!)
            var contentType = subdata.range(of: contentTypeApplicationJson)
            if (contentType != nil) {
                let headerRange = subdata.range(of: headerEnd)
                var directiveData = String(data: subdata.subdata(in: (headerRange?.upperBound)!..<subdata.count), encoding: String.Encoding.utf8) ?? "Directive data is not String"
                directiveData = directiveData.replacingOccurrences(of: "rn", with: "")
                directives.append(DirectiveData(contentType: "application/json", data: directiveData.data(using: String.Encoding.utf8)!))
                print("Directive: (directiveData)")
            }
            contentType = subdata.range(of: contentTypeAudio)
            if (contentType != nil) {
                let headerRange = subdata.range(of: headerEnd)
                let audioData = subdata.subdata(in: (headerRange?.upperBound)!..<subdata.count)
                directives.append(DirectiveData(contentType: "application/octet-stream", data: audioData))
                print("Audio data")
            }
        }
        return directives
    }
 

Мой текущий код возвращает только этот пример ответа

 {
    "header": {
        "namespace": "SpeechSynthesizer",
        "name": "Speak",
        "messageId": "35601dca-413f-4788-93ed-305e04328d0e",
        "dialogRequestId": "db933fd9-3766-407d-99f6-2b33d9c814e6",
        "keys": {
            "isBlocking": true,
            "channel": "audio"
        }
    },
    "payload": {
        "format": "AUDIO_MPEG",
        "token": "amzn1.as-ct.v1.ThirdPartySdkSpeechlet#ACRI#ValidatedSpeakDirective_amzn1.ask.skill.5718d3ec-b56a-4a5a-bd61-fdd4ab501fc2_ca3ae40b-52cd-4be9-b831-98e975a57e5a_VoiceInitiated#ACRI#[[ENCRYPTED_WITH_AlexaServiceKeyMasterUtil]]AAAAAAAAAAAHT6zrrzQh3EDQVwUGrjOpUAAAAAAAAACFZJ/VU0i9/OCY89UvtcV9X0291NLF7L7nE4irlDAGaph7NlUpgq0Ps31s8OflwHh/9wr3vp5Py Gz 2Lgd8N6fPXWxPHp8 E6R8sLiRh9Cg==",
     
    }
}
 

Ответ №1:

Если я правильно читаю, вы не получите такого ответа.

Похоже, у вас есть устройство AVS, отправляющее аудио в голосовую службу Alexa.

Отправляемый вами звук принимается службой, преобразуется в намерение и данные и отправляется вашему навыку.

Ответ, который вы ищете с помощью тегов «speak», отправляется ASK SDK из вашего навыка в Alexa.

Alexa преобразует его в аудио и отправляет аудио вашему клиенту AVS, но не отправляет копию прямого вывода из вашей команды skill, которая его создала. Вы просто не можете разобрать его из ответа.

Комментарии:

1. Можно ли настроить ответ Alexa (JSON) и отправить его моему клиенту AVS? @LetMyPeopleCode

2. Прошло некоторое время с тех пор, как я работал с API-интерфейсами AVS, но ознакомьтесь с этой страницей документации для директивы SpeechSynthesizer. Если ваше приложение получает это, вы можете найти текстовое содержимое в свойстве «заголовок»… developer.amazon.com/en-US/docs/alexa/alexa-voice-service /…

3. Я могу получить доступ к SpeechSnythesize. Директива Speak, однако я не вижу свойство caption. Я был бы очень признателен, если бы вы могли помочь мне с этой проблемой. Прошло несколько дней с тех пор, как я застрял с этим. @LetMyPeopleCode

4. Каков ваш вариант использования. Зачем вам нужна эта информация и что вы собираетесь с ней делать?

5. Я хочу воспроизводить музыку (классифицированную по жанру) в своем пользовательском приложении с помощью Alexa. Я хочу получить конкретный жанр, произнесенный пользователем, например. пользователь говорит, играйте музыку 80-х. Если у меня есть это значение в качестве ответа JSON от Alexa, я могу просто программно воспроизводить музыку в своем пользовательском приложении. Это правильный подход? @LetMyPeopleCode