question

johnemiller71 avatar image
johnemiller71 asked ·

AVS on IOS: "Invalid Audio Format" or "Bad Request" for any recognition upload

I'm about ready to give up on trying to get the AVS recognizer endpoint to ingest a voice upload from IOS (using https://avs-alexa-na.amazon.com/v20160207/events).

I'm 3 full, long days into this and have tried everything detailed in the documentation and these forums. No matter how I attempt to do an upload of audio from IOS to AVS, I get HTTP 400 "Invalid Audio Format" or "Bad Request". Part of this stems from the poor documentation - specifically, what should be the actual content-type for the audio upload? Is it "Content-Type: audio/L16; rate=16000; channels=1\r\n\r\n" or "Content-Type: application/octet-stream"??? The guidance given in these forums deviates from the AVS docs which only creates more confusion and in the case of IOS, most of the guidance is so old that it's within the context of the old /v1/ API. To streamline, I'll preemptively answer the following:

1. Yes, the audio file is linear PCM, 16.0kHz sample rate, 1 channel, 16 bits.

2. Yes, I have verified my audio files over, and over (and over) using Audacity. The raw data import works and the samples play just fine.

An example request below:

--37FCE86A-97C0-4801-8C25-F3D9E021D56F

Content-Disposition: form-data; name="metadata"

Content-Type: application/json; charset=UTF-8

{

"context" : [

{

"payload" : {

"playerActivity" : "IDLE",

"token" : "Atza|Tasdf8asd8f8f81ef8asd8fa9sdfasdvcasd0f0dfa8sdf7asdf6tasd6fas8df8asdf9as98dfasdf",

"offsetInMilliseconds" : "0"

},

"header" : {

"name" : "PlaybackState",

"namespace" : "AudioPlayer"

}

},

{

"payload" : {

"allAlerts" : [],

"activeAlerts" : []

},

"header" : {

"name" : "AlertsState",

"namespace" : "Alerts"

}

},

{

"payload" : {

"volume" : 0,

"muted" : false

},

"header" : {

"name" : "VolumeState",

"namespace" : "Speaker"

}

}

],

"event" : {

"payload" : {

"locale" : "en-us",

"profile" : "CLOSE_TALK",

"format" : "AUDIO_L16_RATE_16000_CHANNELS_1"

},

"header" : {

"namespace" : "SpeechRecognizer",

"name" : "Recognize",

"messageId" : "09E9CCCD-F6B3-4E32-8E24-AD5841FFB7E6",

"dialogRequestId" : "BF14C1C1-F5BB-46B1-875D-4D162E844569"

}

}

}

--37FCE86A-97C0-4801-8C25-F3D9E021D56F

Content-Disposition: form-data; name="audio"

Content-Type: application/octet-stream

[REDACTED AUDIO DATA]

--37FCE86A-97C0-4801-8C25-F3D9E021D56F--

No matter what I do, the response is:

{"header":{"namespace":"System","name":"Exception","messageId":"a22720a1-a3c5-4024-9d40-6557f1e7954d"},"payload":{"code":"INVALID_REQUEST_EXCEPTION","description":"Bad Request"}}

or

{"header":{"namespace":"System","name":"Exception","messageId":"a22720a1-a3c5-4024-9d40-6557f1e7954d"},"payload":{"code":"INVALID_REQUEST_EXCEPTION","description":"Invalid audio format"}}

Depending upon whether I use Content-Type: application/octet-stream or audio/L16

Any guidance would be greatly appreciated. Thanks!

alexa voice serviceaudiouploadios
2 comments
10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

There's one obvious issue that I see: the PlaybackState token should NOT be your access token. It's the token that represents the most recently played Play directive. If you look at the documentation, you'll see that every play directive comes with a token. That's what should be in that field. If you have not yet received a Play directive, that field should be "".

0 Likes 0 ·

Eric - not 100% sure, but I just removed the playback context and I *think* I'm getting an actual response from the AVS service now. I think that may have been it. Will let you know once I've spent the time to fully verify. Thanks much!

0 Likes 0 ·
Eric@Amazon avatar image
Eric@Amazon answered ·

Solution (copied from comment above): the PlaybackState token should NOT be your access token. It's the token that represents the most recently played Play directive. If you look at the documentation, you'll see that every play directive comes with a token. That's what should be in that field. If you have not yet received a Play directive, that field should be "".

10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

newuser-d68aaa5d-46aa-4d59-9e7a-8cf90eb6c1fd avatar image
newuser-d68aaa5d-46aa-4d59-9e7a-8cf90eb6c1fd answered ·

Hi,

Even i'm getting Bad Request error. This is how im using it:

URL : https://avs-alexa-na.amazon.com/v20160207/events

Content-Disposition: form-data; name="metadata"

Content-Type: application/json; charset=UTF-8

JSON:

{"context":[{"header":{"namespace":"AudioPlayer","name":"PlaybackState"},"payload":{"playerActivity":"IDLE","token":"","offsetInMilliseconds":"0"}},{"header":{"namespace":"Alerts","name":"AlertsState"},"payload":{"allAlerts":[{"scheduledTime":"2015-10-30T22:34:51+00:00","token":"","type":"ALARM"}],"activeAlerts":[]}}],"event":{"header":{"namespace":"SpeechRecognizer","messageId":"messageId-123","dialogRequestId":"dialogRequestId-321","name":"Recognize"},"payload":{"locale":"en-us","format":"AUDIO_L16_RATE_16000_CHANNELS_1","profile":"CLOSE_TALK"}}}

Content-Disposition: form-data; name="audio"

Content-Type: application/octet-stream

ERROR:

UserInfo={NSLocalizedDescription=AVS error: 400 - {"header":{"namespace":"System","name":"Exception","messageId":"846e18a4-cb70-48b5-8998-e703203b98b7"},"payload":{"code":"INVALID_REQUEST_EXCEPTION","description":"Bad Request"}}}

Kindly suggest

10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

swh avatar image
swh answered ·

Hello NewUser-d68a,

It looks like your request is valid JSON, but the context array is missing entries for the Speaker.VolumeState and SpeechSynthesizer.SpeechState ( see: https://developer.amazon.com/public/solutions/alexa/alexa-voice-service/reference/speechrecognizer#recognize ). That may be the whole of your problem. I also do not see any multi-part boundaries in your text - perhaps you just omitted it to focus on the JSON? If after fixing these issues you are still getting an error response, please forward logs from a recent run showing both the data you have sent and the error sent back from AVS - including the header values so that we can see the x-amzn-requestid value.

-SWH

10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

lim avatar image
lim answered ·

Hi,

Even i'm getting Bad Request error. This is how im using it:

#pragma mark - NSURLSession Post Method

- (void)configPostRequestSendData:(NSData *)sendData {

NSString *urlStr = [NSStringstringWithFormat:@"%@/v20160207/events",kBaseUrl];

NSURL *url = [NSURLURLWithString:urlStr];

NSMutableURLRequest *request = [NSMutableURLRequestrequestWithURL:url

cachePolicy:NSURLRequestUseProtocolCachePolicy

timeoutInterval:30.0];

request.cachePolicy = NSURLRequestReloadIgnoringCacheData;

request.HTTPShouldHandleCookies = NO;

[request setHTTPMethod:@"POST"];

//分割线内容

//NSString *boundary = @"AaB03x";

NSString *boundary = [[NSUUIDUUID] UUIDString];

//设置http请求头

[request setValue:[NSStringstringWithFormat:@"Bearer %@",self.userModel.userToken] forHTTPHeaderField:@"Authorization"];

[request setValue:[NSStringstringWithFormat:@"multipart/form-data; boundary=%@", boundary] forHTTPHeaderField:@"Content-Type"];

//Message

NSMutableData *bodyData = [[NSMutableDataalloc] initWithData:[[NSStringstringWithFormat:@"\r\n--%@\r\n",boundary] 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]];

NSDictionary *requestBodyDictionary = @{

@"event":@{

@"header": @{

@"namespace": @"SpeechRecognizer",

@"name": @"Recognize",

@"messageId":self.messageId,

@"dialogRequestId": @"dialogRequestId-321"

}

},

@"payload": @{

@"profile": @"CLOSE_TALK",

@"format": @"AUDIO_L16_RATE_16000_CHANNELS_1",

@"token" :self.userModel.userToken

}

};

NSString *jsonStr = [self jsonPrettyStringEncoded:requestBodyDictionary];

[bodyData appendData:[jsonStr dataUsingEncoding:NSUTF8StringEncoding]];

//Audio

[bodyData appendData:[[NSStringstringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];

[bodyData appendData:[@"Content-Disposition: form-data; name=\"audio\"\r\n"dataUsingEncoding:NSUTF8StringEncoding]];

[bodyData appendData:[@"Content-Type: application/octet-stream\r\n\r\n"dataUsingEncoding:NSUTF8StringEncoding]];

//麦克风数据

[bodyData appendData:[NSData dataWithData:sendData]];

//结束分割线 --AaB03x--

[bodyData appendData:[[NSStringstringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];

[request setHTTPBody:bodyData];

NSURLSession *session = [NSURLSessionsharedSession];

NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:bodyData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

self.statusCode = [(NSHTTPURLResponse *)response statusCode];

NSString *codeDescription = [NSHTTPURLResponselocalizedStringForStatusCode:self.statusCode];

NSLog(@"codeDescription ====>%@",codeDescription);

if (data.length != 0) {

id jsonStr = [self jsonValueDecoded:data];

NSLog(@"didReceiveData jsonStr===>%@", jsonStr);

}

NSLog(@"didReceiveResponse....code = %ld \n response.debugDescription ===%@\n response.description == %@\n ", self.statusCode, response.debugDescription, response.description);

}];

[uploadTask resume];

}

ERROR:

[AONIHomeVC.m:529] codeDescription ====>bad request

[AONIHomeVC.m:532] didReceiveData jsonStr===>{

header = {

messageId = "0cab7b3f-bbf5-45bb-bc90-b0b7831f97db";

name = Exception;

namespace = System;

};

payload = {

code = "INVALID_REQUEST_EXCEPTION";

description = "Bad Request";

};

}

[AONIHomeVC.m:535] didReceiveResponse....code = 400

response.debugDescription ===<NSHTTPURLResponse: 0x1c0238680> { URL: https://avs-alexa-fe.amazon.com/v20160207/events } { Status Code: 400, Headers {

"Access-Control-Allow-Origin" = (

"*"

);

"Content-Type" = (

"application/json; charset=UTF-8"

);

"access-control-allow-headers" = (

"authorization,x-amz-access-token"

);

"x-amzn-requestid" = (

"02b91ffffe899224-000023d6-0002f4ab-cd8e583a94ab43eb-152dc6cf-1"

);

} }

response.description == <NSHTTPURLResponse: 0x1c0238680> { URL: https://avs-alexa-fe.amazon.com/v20160207/events } { Status Code: 400, Headers {

"Access-Control-Allow-Origin" = (

"*"

);

"Content-Type" = (

"application/json; charset=UTF-8"

);

"access-control-allow-headers" = (

"authorization,x-amz-access-token"

);

"x-amzn-requestid" = (

"02b91ffffe899224-000023d6-0002f4ab-cd8e583a94ab43eb-152dc6cf-1"

);

} }

Kindly suggest

10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.