jsonmongodbaws-lambdapython-requestsmediainfo

Attribute error when sending json with Requests from mediainfo AWS Lambda


I m trying to send video metadata to MongoDB Atlas from an s3 bucket with media info as an AWS Lambda in Python 3.7. It works when I hardcode the data, but I receive either an object key error or an attribute error. I tried importing json and using json.loads() and json.dumps() and receive errors. Here's the code,

import boto3
from botocore.client import Config
from botocore.exceptions import ClientError
import json
import xmltodict
import subprocess
import os
import uuid
import requests
import json

# Generate a presigned URL for S3 Object
def get_presigned_url(expiration, objBucket, objKey):
    s3 = boto3.client('s3', 'us-east-1', config=Config(s3={'addressing_style': 'virtual'}))
    Params={
        'Bucket': objBucket,
        'Key': objKey
    }
    print ('CORE:: Media Evaluator:: Bucket Name: ' + objBucket)
    print ('CORE:: Media Evaluator:: Object Key: ' + objKey)
    try:
        response = s3.generate_presigned_url('get_object', Params, ExpiresIn=expiration)
        print('this is the response !!!!!!!!!', response)
    except ClientError as e:
        print (e)
        raise
        return None
    return response

# Get MD5 from S3 Object Tag
def get_md5_from_objectTag(objBucket, objKey):
    s3 = boto3.client('s3', 'us-east-1', config=Config(s3={'addressing_style': 'virtual'}))
    response = s3.get_object_tagging(
        Bucket=objBucket,
        Key=objKey
    )
    for tag in response['TagSet']:
        if tag['Key'] == 'MD5':
            md5 = tag['Value']
    return md5

# Evaluate the media using MediaInfo
def get_mediainfo(presignedURL):
    print("presignedURL !!!!!!!!!!!!!", presignedURL)
    try:
        output = subprocess.check_output(['./mediainfo', '--full', '--output=JSON', presignedURL], shell=False, stderr=subprocess.STDOUT)
        #  subprocess.check_output(["./mediainfo", "--full", "--output=JSON", presignedURL], stdin=None, stderr=subprocess.STDOUT, shell=True)    
        print("this si the output !!!!!!!!!!!!!!!!!", output) 
        json_output = json.loads(output)
        print("this is the JOSN output!!!!!!", json_output)
        # Prepare the short media analysis JSON
        json_track = json_output['media']
        for f in json_track['track']:
            if f['@type'] == 'General':
                wrapper = f['Format']
            
            if f['@type'] == 'Video':
                wrapperType = f['Format_Profile']
                codec = f['Format']
                bitRate = f['BitRate']
                #frameRate = f['FrameRate']
                #som = f['TimeCode_FirstFrame']
                width = f['Width']
                height = f['Height']
                #framecount = f['FrameCount']
            #if f['@type'] == 'Other' and f['Type'] == 'Time code':
                #som = f['TimeCode_FirstFrame']
        mediaResult = {
            "Wrapper": wrapper + wrapperType,
            "Codec": codec,
            "BitRate": bitRate,
            #"FrameRate": frameRate,
            #"SOM": som,
            "Resolution": width + 'X' + height,
            #"FrameCount": framecount
        }
    except Exception as e:
        print (e)
        raise
        return None
    return mediaResult

def lambda_handler(event, context):
    print("this is the event !!!!!!!!!!!!!!!", event)
    bucketName = event['bucketName']
    objectName = event['objectKey']
    signed_url = get_presigned_url(3600, bucketName, objectName)
    print ('CORE:: Media Evaluator:: Presigned URL: ' + signed_url)
    mediaAnalysis = get_mediainfo(signed_url)
    print('CORE:: Media Evaluator:: Parsed Media Analysis: ' + json.dumps(mediaAnalysis, indent=4))
    #md5 = get_md5_from_objectTag(bucketName, objectName)
    #print('CORE:: Media Evaluator:: MD5 Value from Object Tag: ' + md5)
    ingestData = {
        "MediaEvaluation": mediaAnalysis,
        #"MD5": md5,
        "AssetID": objectName.partition(".")[0],
        "AssetUID": uuid.uuid4().hex,
        "Bucket": bucketName,
        "ObjectKey": objectName
    } 
    print('this is ingestData !!!!!!!!!!!!!!!!!!!!!!!', ingestData)
    print('this is mediaAnalysis !!!!!!!!!!!!!!!!!!!!!!!', mediaAnalysis)

    #ingestDataJson = json.dumps(ingestData)
    #mediaAnalysisJson = json.dumps(mediaAnalysis)

    dataNotFake = { 's3url': ingestData.Bucket + '.s3.amazonaws.com/' + ingestData.objectKey, 
 'Codec': mediaAnalysis.Codec, 'resolution': mediaAnalysis.Resolution}

    r = requests.post(url ='<mongobdAtlasUrlConnectStringHere>', data = dataNotFake)
    
    return ingestData

what I am sending the Lambda is,

{
  "bucketName": "<s3-bucket-name>",
  "objectKey": "<video-file-name>"
}

edit: the initial response

{
  "errorMessage": "'str' object has no attribute 'Bucket'",
  "errorType": "AttributeError",
  "stackTrace": [
    "  File \"/var/task/mediaEvaluator.py\", line 107, in lambda_handler\n    dataNotFake = { 's3url': ingestDataJson.Bucket + '.s3.amazonaws.com/' + ingestDataJson.objectKey, 'Codec': mediaAnalysisJson.Codec, 'resolution': mediaAnalysisJson.Resolution}\n"
  ]
}

and, then the logs

7c4Uwzk422qMqIJfcFOZr6kwDasq3AEIy%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FARAAGgw2MTYwODIzMjAyOTEiDHJGza1WClZUa%2BZKEyqwAWPyeYiNirreNeRtXlelQjCxUnEj3HMZiMF2UlPLpzwY3RRNo5LBpieIuIRUm7HtbWqXp19lDsUBHiGSoZqmNW5i5EN5nTPe6c6LNdKYFXYutvd4X1dsVEij8srY0DW%2FjBpiZxGt3DlhLWiDtoA8EjgXEe4JcpvU6Z9EpJeotjFhBzfe%2BM7xoPYE%2BoYS4ipx0nyntPQ4Qia1Cdh9LBwsHbcPL59JeI27lVmkggCFevZXMLqPzIEGOuABHPLi%2B3fu1bxwoDJYaA0HOwnAbF%2FncPMWpIR9NATDHyq%2B6BbaOxFAygyNXC%2FAjjqCEOezv1yfZ0VCMAP9i0Wi%2BBqgL8s4Qbuwk1PdgSfZdwqxrSOynSeX6s7Z5au9QYn%2BY%2F5upVr%2F5dt6Q8veRAWuqEQx4muzEix0jorBm4j1KAmuTYfv3A71Hv9YfhMmbR6h4XZv1U8nQpqNJNIJ%2FC%2BBBbRuXDWMhbfnK6IiXw9e3VWqQa7Esjj0WqHgOZ1wWGLZvqqy5Re%2Bm%2BF9eFdE%2F3mUv516aeU31eZ0gkHxnZGZ6HY%3D&Expires=1613960653', 'track': [{'@type': 'General', 'ID': '1', 'VideoCount': '1', 'MenuCount': '1', 'FileExtension': 'mpg?AWSAccessKeyId=ASIAY64K6FOR54JVBB5W&Signature=b16%2BkSWWYrrZvBlYA5tvs7DsqO4%3D&x-amz-security-token=IQoJb3JpZ2luX2VjEML%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCXVzLWVhc3QtMSJHMEUCIQCyP7t3a9Y6%2F4brzVhIOH5GEMpkargZlHCnX55tbiJKwQIgdBNqAwljhCiLZbf%2F7c4Uwzk422qMqIJfcFOZr6kwDasq3AEIy%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FARAAGgw2MTYwODIzMjAyOTEiDHJGza1WClZUa%2BZKEyqwAWPyeYiNirreNeRtXlelQjCxUnEj3HMZiMF2UlPLpzwY3RRNo5LBpieIuIRUm7HtbWqXp19lDsUBHiGSoZqmNW5i5EN5nTPe6c6LNdKYFXYutvd4X1dsVEij8srY0DW%2FjBpiZxGt3DlhLWiDtoA8EjgXEe4JcpvU6Z9EpJeotjFhBzfe%2BM7xoPYE%2BoYS4ipx0nyntPQ4Qia1Cdh9LBwsHbcPL59JeI27lVmkggCFevZXMLqPzIEGOuABHPLi%2B3fu1bxwoDJYaA0HOwnAbF%2FncPMWpIR9NATDHyq%2B6BbaOxFAygyNXC%2FAjjqCEOezv1yfZ0VCMAP9i0Wi%2BBqgL8s4Qbuwk1PdgSfZdwqxrSOynSeX6s7Z5au9QYn%2BY%2F5upVr%2F5dt6Q8veRAWuqEQx4muzEix0jorBm4j1KAmuTYfv3A71Hv9YfhMmbR6h4XZv1U8nQpqNJNIJ%2FC%2BBBbRuXDWMhbfnK6IiXw9e3VWqQa7Esjj0WqHgOZ1wWGLZvqqy5Re%2Bm%2BF9eFdE%2F3mUv516aeU31eZ0gkHxnZGZ6HY%3D&Expires=1613960653', 'Format': 'MPEG-TS', 'FileSize': '102004664', 'Duration': '200.236328125', 'OverallBitRate_Mode': 'CBR', 'OverallBitRate': '4075040', 'StreamSize': '7646822', 'extra': {'OverallBitRate_Precision_Min': '4075030', 'OverallBitRate_Precision_Max': '4075051', 'FileExtension_Invalid': 'ts m2t m2s m4t m4s tmf ts tp trp ty'}}, {'@type': 'Video', 'StreamOrder': '0-0', 'ID': '481', 'MenuID': '1', 'Format': 'AVC', 'Format_Profile': 'Main', 'Format_Level': '4.1', 'Format_Settings_CABAC': 'Yes', 'Format_Settings_RefFrames': '1', 'Format_Settings_GOP': 'M=1, N=15', 'CodecID': '27', 'Duration': '194.867', 'BitRate': '3873733', 'Width': '1280', 'Height': '720', 'Sampled_Width': '1280', 'Sampled_Height': '720', 'PixelAspectRatio': '1.000', 'DisplayAspectRatio': '1.778', 'ColorSpace': 'YUV', 'ChromaSubsampling': '4:2:0', 'BitDepth': '8', 'ScanType': 'Progressive', 'Delay': '10.000000', 'StreamSize': '94357842'}, {'@type': 'Menu', 'StreamOrder': '0', 'ID': '480', 'MenuID': '1', 'Format': 'AVC / KLV', 'Duration': '200.236328125', 'Delay': '0.001107222', 'List_StreamKind': '1 / ', 'List_StreamPos': '0 / ', 'extra': {'pointer_field': '0', 'section_length': '55'}}]}}
CORE:: Media Evaluator:: Parsed Media Analysis: {
    "Wrapper": "MPEG-TSMain",
    "Codec": "AVC",
    "BitRate": "3873733",
    "Resolution": "1280X720"
}
this is ingestData !!!!!!!!!!!!!!!!!!!!!!! {'MediaEvaluation': {'Wrapper': 'MPEG-TSMain', 'Codec': 'AVC', 'BitRate': '3873733', 'Resolution': '1280X720'}, 'AssetID': 'Day Flight', 'AssetUID': 'cb0651e1151f41a5a890425d41bda3cb', 'Bucket': 'video-uploads-94viwznlhm88', 'ObjectKey': 'Day Flight.mpg'}
this is mediaAnalysis !!!!!!!!!!!!!!!!!!!!!!! {'Wrapper': 'MPEG-TSMain', 'Codec': 'AVC', 'BitRate': '3873733', 'Resolution': '1280X720'}
[ERROR] AttributeError: 'str' object has no attribute 'Bucket'
Traceback (most recent call last):
  File "/var/task/mediaEvaluator.py", line 107, in lambda_handler
    dataNotFake = { 's3url': ingestDataJson.Bucket + '.s3.amazonaws.com/' + ingestDataJson.objectKey, 'Codec': mediaAnalysisJson.Codec, 'resolution': mediaAnalysisJson.Resolution}
END RequestId: bfcf3bb8-d709-44c5-9e42-8c7a6a31a879
REPORT RequestId: bfcf3bb8-d709-44c5-9e42-8c7a6a31a879  Duration: 6679.29 ms    Billed Duration: 6680 ms    Memory Size: 128 MB Max Memory Used: 104 MB Init Duration: 382.19 ms

Solution

  • I think here

    dataNotFake = { 's3url': ingestData.Bucket + '.s3.amazonaws.com/' + ingestData.objectKey,

    considering these

    ingestData = {'MediaEvaluation': {'Wrapper': 'MPEG-TSMain',
      'Codec': 'AVC',
      'BitRate': '3873733',
      'Resolution': '1280X720'},
     'AssetID': 'Day Flight',
     'AssetUID': 'cb0651e1151f41a5a890425d41bda3cb',
     'Bucket': 'video-uploads-94viwznlhm88',
     'ObjectKey': 'Day Flight.mpg'}
    
    
    mediaAnalysis = {
    'Wrapper': 'MPEG-TSMain', 'Codec': 'AVC', 'BitRate': '3873733', 'Resolution': '1280X720'}
    

    You should use something like this

    dataNotFake = { 
    's3url': f'{ingestData["Bucket"]}.s3.amazonaws.com/{ingestData["ObjectKey"]}', 
    'Codec': mediaAnalysis['Codec'],
    'resolution': mediaAnalysis['Resolution']
    }