2017-04-19 2 views
1

私はしばらくの間、iOS Alexaアプリで作業していましたが、AVS APIへのストリームとしてマイクのオーディオを送信するのには苦労しています。v20160207にオーディオをストリーミングする方法iOSのAlexa Voice Service API

オーディオサンプルの録音に成功し、それを全体として送信して応答しました。

NSURLSession http/2接続でAVSにデータをストリームする方法を知りたいだけです。ここで

はコードである私が今やっているスニペット:

func sendData() { 
     let request = NSMutableURLRequest(URL: NSURL(string: "https://avs-alexa-na.amazon.com/v20160207/events")!) 
     request.setValue("Bearer \(Settings.Credentials.TOKEN)", forHTTPHeaderField: "authorization") 
     request.HTTPMethod = "POST" 

     let boundry = NSUUID().UUIDString 
     let contentType = "multipart/form-data; boundary=\(boundry)" 
     request.setValue(contentType, forHTTPHeaderField: "content-type") 

     let bodyData = NSMutableData() 

     let jsonData = "{\"context\":[{\"header\":{\"namespace\":\"Alerts\",\"name\":\"AlertsState\"},\"payload\":{\"allAlerts\":[],\"activeAlerts\":[]}},{\"header\":{\"namespace\":\"AudioPlayer\",\"name\":\"PlaybackState\"},\"payload\":{\"token\":\"\",\"offsetInMilliseconds\":0,\"playerActivity\":\"IDLE\"}},{\"header\":{\"namespace\":\"Speaker\",\"name\":\"VolumeState\"},\"payload\":{\"volume\":25,\"muted\":false}},{\"header\":{\"namespace\":\"SpeechSynthesizer\",\"name\":\"SpeechState\"},\"payload\":{\"token\":\"\",\"offsetInMilliseconds\":0,\"playerActivity\":\"FINISHED\"}}],\"event\":{\"header\":{\"namespace\":\"SpeechRecognizer\",\"name\":\"Recognize\",\"messageId\":\"messageId-123\",\"dialogRequestId\":\"dialogRequestId-321\"},\"payload\":{\"profile\":\"CLOSE_TALK\",\"format\":\"AUDIO_L16_RATE_16000_CHANNELS_1\"}}}" 

     bodyData.appendData("--\(boundry)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
     bodyData.appendData("Content-Disposition: form-data; name=\"metadata\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
     bodyData.appendData("Content-Type: application/json; charset=UTF-8\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
     bodyData.appendData(jsonData.dataUsingEncoding(NSUTF8StringEncoding)!) 
     bodyData.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 

     bodyData.appendData("--\(boundry)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 

     bodyData.appendData("Content-Disposition: form-data; name=\"audio\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
     //  bodyData.appendData("Content-Type: audio/L16; rate=16000; channels=1\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
     bodyData.appendData("Content-Type: application/octet-stream\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
     bodyData.appendData(audioData!) 
     bodyData.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 

     bodyData.appendData("--\(boundry)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
     session = NSURLSession.sharedSession() 
     session.configuration.timeoutIntervalForResource = 60000 
     session.configuration.timeoutIntervalForRequest = 60000 

     let upload = session.uploadTaskWithRequest(request, fromData: bodyData) { (data, response, error) in 
      print("done") 
      if(data?.length > 0) { 
       print("break") 
      } 
      if let httpResponse = response as? NSHTTPURLResponse { 
       if let responseData = data, let contentTypeHeader = httpResponse.allHeaderFields["Content-Type"] { 

        var boundry: String? 
        let ctbRange = contentTypeHeader.rangeOfString("boundary=.*?;", options: .RegularExpressionSearch) 
        if ctbRange.location != NSNotFound { 
         let boundryNSS = contentTypeHeader.substringWithRange(ctbRange) as NSString 
         boundry = boundryNSS.substringWithRange(NSRange(location: 9, length: boundryNSS.length - 10)) 
        } 

        if let b = boundry { 
         let parts = self.parseResponse(responseData, boundry: b) 
         print("got parts") 
//      self.sendSynchronize() 
         self.successHandler?(data: responseData, parts:self.parseResponse(responseData, boundry: b)) 
        } else { 
         print("something went wrong") 
         self.errorHandler?(error: NSError(domain: Settings.Error.ErrorDomain, code: Settings.Error.AVSResponseBorderParseErrorCode, userInfo: [NSLocalizedDescriptionKey : "Could not find boundry in AVS response"])) 
        } 
       } 
      } 
     } 

     upload.resume() 
    } 

この機能それはAmazonが:)

挨拶をストリーミングするために推奨していますサイズだからのオーディオデータのすべての320バイトと呼ばれます!

+0

幸い@tomwyckhuys?私も同じ問題で殴られた。私はまた、終わりの境界用語を削除しようとしました。 –

答えて

0

ダイアログリクエストの開始時に、send the JSON metadata headers only onceにする必要があります(マイクが開いて録音を開始した瞬間など)。

また、同じストリームに対してsendDataメソッドを呼び出すたびに、同じ境界値を使用することもできます。リクエスト全体に対して同じHTTP/2ストリームを使用します。つまり、これに対応するためにsendDataメソッドを「内側に」リファクタリングする必要があります。 uploadTask:withStreamedRequestを使用する例が参考になります(おそらく使用する必要があります)。

私はSwift HTTP/2 APIに精通していないので、継続フレームがあなたのために処理されるかどうか、またはあなた自身で管理する必要があるかどうかはわかりません。最高の運とこれが役立つことを願っています。

関連する問題