Unable to recover audio from Amazon Connect via kinesis video client in boto3 in Python

1.1k views Asked by At

I'm trying to get an audio file from kinesis video stream in Python in AWS-Lambda instance.

To get the audio i'm using this snippet of code:

 def download_stream(self, streamARM, ms_start_timestamp):
        tmpfile = os.path.join('/tmp', str(uuid.uuid4()) + '.mkv')

        logger.debug("get_data_endpoint", tmpfile=tmpfile, streamARM=streamARM, ms_start_timestamp=ms_start_timestamp)
        response = self._kinesisvideo_client.get_data_endpoint(
           StreamARN=streamARM,
           APIName='GET_MEDIA')

        data_endpoint = response['DataEndpoint']
        logger.debug("get_data_endpoint", endpoint_url=data_endpoint)
        video_client = boto3.client('kinesis-video-media', endpoint_url=data_endpoint)
        stream = video_client.get_media(
           StreamARN=streamARM,
           StartSelector={'StartSelectorType': 'EARLIEST'})

        time.sleep(1)
        logger.debug("stream", stream=stream)
        streamingBody = stream['Payload']

        # This write a mkv chunk, seems corrupted
        with open(tmpfile, 'w+b') as f:
            f.write(streamingBody.read())

        logger.debug("recorded_file", tmpfile=tmpfile)
        return True, tmpfile

To consume it you just need a valid streamARM created by Amazon connect when you call start streaming and stop streaming, the relevant Amazon connect integration is this:

Amazon connect integration

After calling call center, and process the stream in an AWS Lambda, I can get a file foo.flv. According to Amazon Kinesis Video Streams PUT_MEDIA documentation it is a Matroska (MKV) container format with a track with audio in AAC format.

Using OpenSource tools like MKVToolNix, GStreamer and vlc I cannot play the file to listen the audio and I cannot figure why not. If I force the file as a wav (without decoding) I listen the recorded audio very noisy (the info is there). The payload parsed contain AWS tags and some info, mkvinfo test_03s_current.mkv gives as output:

+ EBML head
|+ EBML version: 1
|+ EBML read version: 1
|+ Maximum EBML ID length: 4
|+ Maximum EBML size length: 8
|+ Document type: matroska
|+ Document type version: 2
|+ Document type read version: 2
+ Segment: size unknown
|+ Tags
| + Tag
|  + Simple
|   + Name: ContactId
|   + String: b1e0f302-2d60-4dcf-98af-77ef3baa0b0b
|+ Tags
| + Tag
|  + Simple
|   + Name: InstanceId
|   + String: f1f87e8c-ae31-4f00-86dd-ea630fcd9fe5
|+ Tags
| + Tag
|  + Simple
|   + Name: MimeType
|   + String: audio/L16;rate=8000;channels=1;
|+ Tags
| + Tag
|  + Simple
|   + Name: AUDIO_FROM_CUSTOMER
|   + String: 1
|+ Segment information
| + Segment UID: 0xc0 0x54 0x2a 0xab 0xba 0x4e 0xf8 0xf6 0xc7 0x16 0x9e 0x73 0x11 0x08 0xdb 0x04
| + Timestamp scale: 1000000
| + Title: Kinesis Video SDK
| + Multiplexing application: Kinesis Video SDK 1.0.0 JNI 2.0
| + Writing application: Kinesis Video SDK 1.0.0 JNI 2.0
|+ Tracks
| + Track
|  + Track number: 1 (track ID for mkvmerge & mkvextract: 0)
|  + Track UID: 1
|  + Track type: audio
|  + Name: AUDIO_FROM_CUSTOMER
|  + Codec ID: A_AAC
|  + Codec's private data: size 2
|+ Tags
| + Tag
|  + Simple
|   + Name: AWS_KINESISVIDEO_FRAGMENT_NUMBER
|   + String: 91343852333181432392682062632260670078128844116
|  + Simple
|   + Name: AWS_KINESISVIDEO_SERVER_TIMESTAMP
|   + String: 1603184119.798
|  + Simple
|   + Name: AWS_KINESISVIDEO_PRODUCER_TIMESTAMP
|   + String: 1603184119.671
|+ Cluster

Theorically (this GStreamer pipeline works with a valid mkv file with track 0 audio) shall work, because it works:

gst-launch-1.0 filesrc location=test.mkv ! queue ! matroskademux name=dmux dmux.audio_0 ! queue ! aacparse ! faad ! audioconvert ! alsasink

You can generate a pulse to test it using GStreamer with the command: gst-launch-1.0 -v audiotestsrc num-buffers=100 ! audioconvert ! voaacenc ! matroskamux ! filesink location=foo.mkv

GStreamer seems to be a good candidate because it have a wrapper to Python, in this issue in stream parser library lherman-cs explains how the binary format shall arrive.

Using mkvextract test_03s_current.mkv tracks 0:audio.aac I'm be able to generate the aac file (It detect Container format: raw AAC file with ADTS headers) but it doesn't work neither.

How can I parse the MKV chunks to generate one or more AAC/WAV files correctly without use dirty hacks?

0

There are 0 answers