# AWS Application Composer

En Noviembre pasado se realizó el AWS re:Invent 2022 el máximo evento de AWS que se realizó en Las Vegas, Nevada que nos proporcionó una gran cantidad de anuncios, nuevos servicios y actualizaciones.

## AWS Application Composer

Uno de esos servicios nuevos llamo mi atencion: AWS Application Composer ([https://docs.aws.amazon.com/application-composer/latest/dg/what-is-composer.html](https://docs.aws.amazon.com/application-composer/latest/dg/what-is-composer.html) ), un servicio que permite desde una interfaz Drag-and-Drop arrastrar y soltar distintos servicios asi como interconectarlos para poder crear una arquitectura cloud serverless, entregando el código en cloudformation.

De esta manera podemos concentrarnos en diseñar nuestra arquitectura y  dejar que Application Composer construya cómo se logra,  sin necesidad de ser un experto en AWS CloudFormation.

Podemos usarlo creando un proyecto de cero o cargando uno ya existente, en ambos casos tenemos 2 modos disponibles: conectados o no conectados,si elegimos el estado conectado los cambios que hagamos en las fuentes se verán reflejados en AWS Application Composer y viceversa, los cambios realizados en AWS Application Composer se reflejarán en el código fuente de nuestra aplicación.

Después de diseñar la aplicación serverless con AWS Application Composer, podemos usar cualquier servicio compatible con AWS CloudFormation para la implementación.

En mi caso, utilice: AWS SAM, que me permite realizar depuración y pruebas locales, así como ayudarme con el empaquetado y despliegue de mi aplicación.

![](https://lh6.googleusercontent.com/wOQaIedRWga2j1jZVsLDhUShR6a79bghkU7KRU5CclIxLy8RzXkF_vcD7p-XGlXNMKel2pipzhCPo0-pdVRsw7JoiOGJXw9-6sAENzWDmAK6VrwIXwHJ1WGzAzr10sE5MSET60xnpyO-YlkpsrGSG_xxdrtInXxtoWbdm-r_h01zCNKgGjfumAgM-kv8Fw align="left")

La aplicación que desarrollé es un servicio de procesamiento de video. Para ello emplee un servicio que me ayuda con esta tarea que es  AWS Elemental MediaConvert ([https://aws.amazon.com/es/mediaconvert/](https://aws.amazon.com/es/mediaconvert/)) que funciona tomando un video como entrada y, transcodificando el video a una o más versiones diferentes y luego coloca estas versiones en otro bucket S3.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673890114060/4c5e6722-120f-4d97-977b-987937760890.png align="center")

Para hacer la aplicación serverless, utilice un bucket S3 en donde se cargan los archivos a procesar, cada vez que se detectaba el evento cuando se cargaba un video al bucket, éste se enviaba a una cola SQS que era consumida por una función Lambda (está basada en NodeJS versión 18) que se encarga de llamar a AWS Elemental MediaConvert para el procesamiento del video.

## **Manos a la obra!**

### **1-  Configuración de AWS CLI**

Necesitamos configurar AWS CLI en nuestro entorno local.

[http://docs.aws.amazon.com/cli/latest/userguide/installing.html](http://docs.aws.amazon.com/cli/latest/userguide/installing.html)

Tenemos que tener nuestras credenciales de seguridad (`Access keys`)

[https://docs.aws.amazon.com/IAM/latest/UserGuide/id\_credentials\_access-keys.html#Using\_CreateAccessKey\_CLIAPI](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_CreateAccessKey_CLIAPI)

Luego ejecutamos desde una terminal en su sistema:

aws configure

La CLI de AWS solicita varias cosas:

Las credenciales de usuario (`Access keys`)

La región que usaremos: `us-east-1`

El formato de salida predeterminado:  `json`.

### 2 - Obtener el endpoint de la API de MediaConvert

Para ello iremos al panel del AWS Elemental MediaConvert  y luego iremos al menú lateral izquierdo en la sección Account, este endpoint lo usaremos para una variable de entorno de nuestra función lambda

![](https://lh4.googleusercontent.com/K9uXOYIAuMyyDYe0XS4k3MZE36PicTfmv8E3wkb1TOCsICCVgeo7Ul4tGLS4z5kXzHtDkg3Eo_4PJ_s3hm6trQAQ_h5cMbHatRzfKDQCUG6ocj2Vu2vGShijbR6XBYzOQ7Qp-PLaa2BQ5lmZOCySBI2K8DzIG0-TiyLr3LkcNsd4c-qhd_NWTytzP3geVQ align="left")

### 3- Crear un rol: media-convert-role

Necesitamos crear un rol para nuestra función lambda, MediaConvert necesita tener acceso a S3, así como a API Gateway. Sin esta función, MediaConvert simplemente no se ejecutará cuando intente invocarlo desde Lambda.

Iremos al panel **IAM** y luego a **Roles**, haremos clic en **Crear ro**l

![](https://lh4.googleusercontent.com/x7r5pDRrkeOR0OH7ygA_fkd_RzIAlWNquUgLcI5v4RRsyQc2u5gR62ipvQaNTw-AjgnH3J946y7hScX5u_wj2MHLAFHpwFMEjUvXdYY7l3b6jthPK1QNYI5gvB4ETo7Iv8Fipn8yQdj6j22QsqBvAtD23nOg2fXfDFd-Vj3hhEGRIdN79kRW43f0mFOiFg align="left")

Seleccionamos AWS Service y luego en el select buscamos **MediaConvert**, clic en el botón **Siguiente**

![](https://lh4.googleusercontent.com/xtbqNXI0cDhhACRmg3kEvEIPksxXnahZpilfK9NMnEiUEdGlMRmVTi0VhemuL63FKnCee49zreNDsc7p1JinK_P66gx9MbH4wYn7V4nsZ5hDTfI0C_qt-AaboAxjU30AfDjo7LW78jVRTJkX81hpLVkIinZ1r2kYOl5D0oawF_xrVUHjw_rPUeIBQsBt7Q align="left")

AWS ya ha predefinido qué políticas necesita para este rol.

Elegimos **Siguiente**

Establecemos el nombre

Asigne a su función el nombre *media-convert-role* y luego haga clic en **Crear rol**.

![](https://lh4.googleusercontent.com/Q8iJQOlski9lzPCI_eQsxLqMshY820IKmZznZLmUFIgt9igRDZ_RIsMv_M4W1PzhmncdBC_o5wKtNZqJq4nL9A8H3IqSC5TAU39krgR2svDAnU9rCVDHIpnHD3nRvFIWUJDJeMxFyID5ZX2dHEZCLcYfZ4wPvTAuk_UwN8B_1EqTeVIZ_HBYLJb_4KTw9g align="left")

Necesitaremos el ARN del rol para una variable de entorno de nuestra función lambda.

![](https://lh4.googleusercontent.com/SoPqPCWa6bCzuJTdCQYuT9xIeRtmUtk6X2ZSjZeItWNIYo13SM9OwKYUGF-fEq1mao2q5xBALnBMqW9zT-FI29NXJ5tBfz_DSBcsqDwOwXtcKg1cXVeCTS6GRfCiw59QRxfIGqu-DSix_G80wN-GrQtu9F3zBaQuHtRY6NIsRvenJPAD-2T-vYyHGze8lg align="left")

### 4 - Bucket de carga de videos a procesar

Desde AWS Application Composer tenemos el primer bucket que es donde se cargaran los videos a procesar, el nombre de este bucket por defecto es el nombre de nuestra pila o stack junto con el número de nuestra cuenta de AWS:

`BucketName: !Sub ${AWS::StackName}-bucket-${AWS::AccountId}`

Lo podemos encontrar en la pestaña Template o bien desde nuestras fuentes en template.yaml  y buscar dentro de recursos a nuestro Bucket, podemos cambiarlo a otro nombre de nuestra preferencia.

![](https://lh6.googleusercontent.com/-DduNt9BfRKJhkymkI9PLAf-kDHK14p6H8CLXJck6gr9I_3arLGKRd70d24fOxUoG1xT8FtK1e2F8Qwl_-4vdMgq-iXGe1yJhmg1T5IR6ZO_bixlpu-ZcCmyeAsP39e92qZ4RB5MGb11fW7Ol8T5H8-iKbKWmCTGEzahsvfZbKbPDuOqNRfn76pB6RuqeA align="left")

### 5- Nuestra cola SQS

Cada vez que un video se cargue al bucket S3 definido en el paso 4, este evento es enviado a una cola SQS que se creará cuando despleguemos nuestro proyecto.

### 6- La función Lambda

En el caso de nuestra función Lambda podemos indicar varios parámetros dentro de AWS Application Composer, seleccionando el elemento y luego la opción ***Details*** que mostrará más opciones en el lateral derecho de la pantalla

![](https://lh5.googleusercontent.com/g1uP_Xhry9X8hivI8jt45fzPXckLDDsUgZO4UQfJobuzkEbBctAe30oOvWdcCKkLTK-tb_mDwkpYJuo_c4uj0ese_mZWixkfkvtFSOH1tviJbOH5VWgzauA7bS4Y-ExiX_-DJ04UkgBCpnTybwvDK1RLslP20JqzBnLemv0XnfUmOQmy5A-KuqMymfitsQ align="left")

Podemos especificar el runtime de nuestra Lambda, así como la ubicación del código de nuestra función (***src/Function***) y el método que se ejecuta cuando nuestra función es invocada (`index.handler`)

![](https://lh6.googleusercontent.com/5Gw5CHrk5ud_DZ90WfUTPru-MesZe2aGGuMpBjSdXxTHSvhPg_KqZYsNUR5Lb7ntmdDJ7wFI3Bzhm24vp7KA5NVzNGIpYSVk_KYOv6h3YBjuADkaB2MLeT5vZvJmn0pJEGlRYS-Mgpba-3gRtd6zB4e1wMjTAS3EDc46pNgSquhM1G-KLCv6iFFv9emKqw align="left")

También podemos especificar otros valores desde esta pantalla, como es el caso de las políticas de permisos:

`Version: '2012-10-17'`

`Statement:`

`- Effect: Allow`

`Action:`

`- iam:GetRole`

`- iam:PassRole`

`- mediaconvert:*`

`Resource: arn:aws:iam::619747668685:role/media-convert-role`

![](https://lh6.googleusercontent.com/EkEQ3OJ7PkkcdVQBQ923agLbtfzGn1X7dYnC89qlU9n0aAkrFbebJwJ6KzJyi0wgRgMc1RcNZZiNgD1ESMSNPqLLRfcnUtEeAMKFophUGeS9EJLcAbbb1msKU5JH0jrI3BvDdlx1awxtYxEe4C353xqJ6dhMoVggEVW6ySFPtM1k-D6oUZxbFK8AawceCA align="left")

Y también las variables de entorno que necesitamos especificar:

* `MEDIA_ENDPOINT: el endpoint de mediaConvert`
    
* `MEDIA_ROLE: el ARN del rol previamente creado`
    
* `TRANSCODED_VIDEO_BUCKET:  el nombre de nuestro bucket de salida donde almacenaremos los videos procesador por MediaConvert`
    

![](https://lh3.googleusercontent.com/SEjgH4nQaLaRGOc3Si_MB0zO02Sp3X-xRqzSBjQcss0gRbho6EUKN9YBO_bm3SQYrmcE0fPuj6Ym1zsGjF4h7HlYpyhbHeh2uqfsT72qRTzLX8yl4Rfpo3jYv18h-eOVv5s6geO0YNpc0o2FUKX3DYHkhz7r63ypkdaJnuy1btqjel04mdl5JvSSCC2epA align="left")

Todas las modificaciones que hagamos desde AWS Application Composer las veremos reflejadas en nuestro archivo local `template.yaml`

![](https://lh3.googleusercontent.com/YTjRENP8B_WILBZVs1Cf-DVnq1aBCrLEdxm_WLX7yCEBx5wWMVwDRvjk5PZZaByroAEojLT7DbaZ9vvX1b3BQ5B4LOSgcwJoFnDOG-nVPqEmmbXMl4ZY22EXcv13z36VJ7iv4I5MM2gMMUBH41-ybzuURf-HjyfqsqReJ0yMQDErxzhutl9_2C1xuvwkMQ align="left")

También debemos definir nuestro rol para la función lambda: `aws-sam-lambda-role`

![](https://lh4.googleusercontent.com/IuMQTLjUSrK6FFwmux9Q2REmqd6IASRze1MlOwy_zIHB3WpmGXQVn3lghzb0wLMwfw4O2Gw5KbSv74aSXwV28Y26yym3xZad784zcSda_OCrD05dgm5jV-tsfaOF4uuUGkk2KtU1IvfZUkMaDfHLlI71VVAanyckhVJIszRBPLjnvcxdK3YjlNv6Y5qaFA align="left")

El cual haremos referencia  en nuestro archivo local `template.yaml`

![](https://lh6.googleusercontent.com/CCGib4AbaA0aIy_nVXfu2K7vcbjunPNA_3ZBz2oYeJNXUNLfYs3fg6swkVtGGDn4Nceqe4TRXNMAOlCQNsqMga0GJ22Aj1pnZTCaBEFszdpbCoTObJ9g49cS9DL9H-KNLRYgWB1RXDTab7SHV_v5IKbcwo-8gj-pF1ZXjohVHU5bzja6wmBeDnLg0mKAgw align="left")

El código fuente de la función lambda es:

```javascript
'use strict';

const AWS = require('aws-sdk')

// Obtiene el valor de la variable de entorno MEDIA_ENDPOINT que está configurada en template.yml
const mediaConvert = new AWS.MediaConvert({
    endpoint: process.env.MEDIA_ENDPOINT
});
// Obtiene el nombre del bucket donde se enviaran los videos procesados de la variable de entorno TRANSCODED_VIDEO_BUCKET que está configurada en template.yml
const outputBucketName = process.env.TRANSCODED_VIDEO_BUCKET;

exports.handler = async (event) => {

    const s3Event = JSON.parse(event.Records[0].body)

    try {
        const key = s3Event.Records[0].s3.object.key;
        const sourceKey = decodeURIComponent(key.replace(/\+/g, ' '));
        const outputKey = sourceKey.split('.')[0];

        // Establece la ubicación del video de entrada para la definición de trabajo de MediaConvert
        const input = 's3://' + s3Event.Records[0].s3.bucket.name + '/' + key;

        // Create S3 service object
        const outputBucket = new AWS.S3({apiVersion: '2006-03-01'});

        // Create the parameters for calling createBucket
        var bucketParams = {
          Bucket : outputBucketName
        };

        // call S3 to create the bucket
        outputBucket.createBucket(bucketParams, function(err, data) {
          if (err) {
            console.log("Error", err);
          } else {
            console.log("Success", data.Location);
          }
        });

        // Establece el bucket de salida para los nuevos archivos de video
        const output = 's3://' + outputBucketName + '/' + outputKey + '/';


        const job = {
          //  Obtiene el ARN del rol MediaConvert que se especifica en template.yml
            "Role": process.env.MEDIA_ROLE,
            "Settings": {
                "Inputs": [{
                    "FileInput": input,
                    // Especifica el selector de audio para la definición de trabajo de MediaConvert. De manera predeterminada, nombrará una sola pista de audio en el video.
                    "AudioSelectors": {
                        "Audio Selector 1": {
                            "SelectorType": "TRACK",
                            "Tracks": [1]
                        }
                    }
                }],
                "OutputGroups": [{
                    "Name": "File Group",
                    "Outputs": [{
                        "Preset": "System-Generic_Hd_Mp4_Avc_Aac_16x9_1920x1080p_24Hz_6Mbps",
                        "Extension": "mp4",
                        "NameModifier": "_16x9_1920x1080p_24Hz_6Mbps"
                    }, {
                        "Preset": "System-Generic_Hd_Mp4_Avc_Aac_16x9_1280x720p_24Hz_4.5Mbps",
                        "Extension": "mp4",
                        "NameModifier": "_16x9_1280x720p_24Hz_4.5Mbps"
                    }, {
                        "Preset": "System-Generic_Sd_Mp4_Avc_Aac_4x3_640x480p_24Hz_1.5Mbps",
                        "Extension": "mp4",
                        "NameModifier": "_4x3_640x480p_24Hz_1.5Mbps"
                    }],
                    "OutputGroupSettings": {
                        "Type": "FILE_GROUP_SETTINGS",
                        "FileGroupSettings": {
                            "Destination": output
                        }
                    }
                }]
            }
        };

        const mediaConvertResult = await mediaConvert.createJob(job).promise();
        console.log('mediaConvertResult ' , mediaConvertResult);

    } catch (error) {
        console.error(error);
    }
};
```

Nuestra función lambda utiliza AWS SDK por lo que necesitamos agregar dicha dependencia dentro de nuestro `package.json.`

```json
{
  "name": "function",
  "version": "1.0.0",
  "devDependencies": {
    "aws-sdk": "^2.1270.0"
  }
}
```

Y luego de ello ejecutar `npm i`  dentro de la carpeta donde su ubica este archivo  ***src/Function/***  y debemos agregar unas líneas a nuestro `template.yaml.`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673227134706/4cf134c8-9053-491e-ab47-901ae0650eb4.png align="center")

Quedando finalmente así:

```yaml
Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub ${AWS::StackName}-alfalfita-cloud-bucket-${AWS::AccountId}
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: aws:kms
              KMSMasterKeyID: alias/aws/s3
      PublicAccessBlockConfiguration:
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      NotificationConfiguration:
        QueueConfigurations:
          - Event: s3:ObjectCreated:*
            Queue: !GetAtt Queue.Arn
          - Event: s3:ObjectRemoved:*
            Queue: !GetAtt Queue.Arn
    DependsOn:
      - BucketToQueuePermission
  BucketBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref Bucket
      PolicyDocument:
        Id: RequireEncryptionInTransit
        Version: '2012-10-17'
        Statement:
          - Principal: '*'
            Action: '*'
            Effect: Deny
            Resource:
              - !GetAtt Bucket.Arn
              - !Sub ${Bucket.Arn}/*
            Condition:
              Bool:
                aws:SecureTransport: 'false'
  Queue:
    Type: AWS::SQS::Queue
  BucketToQueuePermission:
    Type: AWS::SQS::QueuePolicy
    Properties:
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: s3.amazonaws.com
            Action: sqs:SendMessage
            Resource: !GetAtt Queue.Arn
            Condition:
              ArnEquals:
                aws:SourceArn: !Sub arn:${AWS::Partition}:s3:::${AWS::StackName}-alfalfita-cloud-bucket-${AWS::AccountId}
      Queues:
        - !Ref Queue
  Function:
    Type: AWS::Serverless::Function
    Properties:
      Description: !Sub
        - Stack ${AWS::StackName} Function ${ResourceName}
        - ResourceName: Function
      CodeUri: src/Function
      Handler: index.handler
      Role: arn:aws:iam::619747668685:role/aws-sam-lambda-role
      Runtime: nodejs18.x
      MemorySize: 3008
      Timeout: 30
      Tracing: Active
      Events:
        Queue:
          Type: SQS
          Properties:
            Queue: !GetAtt Queue.Arn
            BatchSize: 1
      Environment:
        Variables:
          MEDIA_ENDPOINT: https://lxlxpswfb.mediaconvert.us-east-1.amazonaws.com
          MEDIA_ROLE: arn:aws:iam::619747668685:role/media-convert-role
          TRANSCODED_VIDEO_BUCKET: serverless-video-transcoded-alfalfita-cloud-06122022
      Policies:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action:
              - iam:GetRole
              - iam:PassRole
              - mediaconvert:*
            Resource: arn:aws:iam::619747668685:role/media-convert-role
    Metadata:
      BuildProperties:
        UseNpmCi: true
  FunctionLogGroup:
    Type: AWS::Logs::LogGroup
    DeletionPolicy: Retain
    Properties:
      LogGroupName: !Sub /aws/lambda/${Function}
Transform: AWS::Serverless-2016-10-31
```

![](https://lh6.googleusercontent.com/7BVK2-bF10-6imZ_PkJXtKlffk19Py-4pIQ0Fvw9WiuOD6dV0Lr4e7Hiwshb0_BwmUuB_OapiA-WyOLfIuE3an1B1vAp1jbuXXIflKPppLAT1gxOSoD2n4ZGZ2B8FPvr8CFJzGLk79Z_MnK06dNzSW_QNsxRCGX3yrW0iUYadYGyCtOFJSoQuSvAH1i6Ng align="left")

Para más información:

[https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-using-build.html](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-using-build.html)

### 6 - Instalar AWS SAM CLI

Para prepararnos para desplegar nuestra aplicación en la nube, necesitamos un servicio compatible con Cloudformation para la implementación, en este caso AWS SAM, la  documentación para la instalación la podemos encontrar en:

[https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)

Una vez instalado AWS SAM CLI podemos usarlo desde la terminal, con los diversos comandos que proporciona

![](https://lh3.googleusercontent.com/I1SoCL1wdpFl3Bq7TMDTlDpqkJLWOJNs6Pokkqhj9nrrEfhMv3gUELGwv2n0y8MmXmtuevZ0wmRa18E_daSNtge_phMLbTDX739Fqvg-UBiCmbSdcfBltDE7vpUrNulF2aePhqqNHtaG1DU3aBoaQF8vlA_p7oNLrkMxF6pWyDZifF7m-qsb0fF8DavphA align="left")

Ejecutamos primero `sam-build`

![](https://lh4.googleusercontent.com/vL7Q4UUNc0zBLec5gCuiHCesdFAWmdT1uj1CIte9NK58XtQCw6bU6fyoc_b03lF-dKs4hOgOvOPOz1DalHJ-BD6On1IaTgBcDyKR6C6LN9IurrAW-XI0vcgLyy-zcpf8xZ0kgLXSrzkngJUJzn7SIa9B7MW4rodcsUm1ZvoooHDIRqZSCnoqYXmf6FPSlw align="left")

Y luego preparamos el despliegue guiado que nos permitirá establecer ciertos valores:

![](https://lh3.googleusercontent.com/rgFzh2SvLoRwCMr4bjPMcGLeTMTrqfVFjfiU__3SdzeNXIso1bvm6u5p0TleA7ryHJ9-a4NzJAvPpUcjC9Yq43W5eD9TdpESJZQA_mauG9ktV16-HKr6-71O4F55A0CCLPwmfikMcAyiiJnywgv0StUpfM--3si-1GA1vzSwJAhmbGMbp1_33kOBCuq63w align="left")

![](https://lh3.googleusercontent.com/nxG-WblI1szfo4XHjJRkSvyvWeqY7u3553i5i5ov_HL5SinadgOlKK3twe11tipLqXByIG_1nhuDmr0Z0UWCAwY1dZA2HbK6jyspSS-wU6_81RRHJXuZEG_lKd6EcCvBm-cCwX5hh0-W6RJr20t7d3cPS_pkRKicEIldhl0WQml-WPN-4GeI5N0SkXDKTQ align="left")

Confirmamos los cambios, y veremos como los recursos se irán creando:

![](https://lh6.googleusercontent.com/qWyrKvts2nn_rA9LOln6pfIN_jRz1NSyQ79Y8XGfoQCUVs_AXfEHMSlg6Xv60BGFoW_odVmDV4HJ6mR74U4OzwfAxv9cBKZVYkMwr_Lm_MrIew81OkSIDEiEjds7Sl-uCKsxUnABFHIRMsUZly26JjenBQ2lcnfyIekSDEYiJ64xEP2OFNmWZY875xkEbw align="left")

Confirmamos que la pila existe en el panel de CloudFormation

![](https://lh5.googleusercontent.com/_No5kzQKM9ipxv877AzcHfBVI0Adf1Oy3ZPFyL9YSZhK6O-CbpGIEtZ_chz-yvG20ihuyvoDEAk7SHosAiggjDKOQBWDnRs8nR0IOT_tkM3szI07jWfeO74wozrGrO0B-LE3jPNK-Qm9VaeUZtkevoHT7VwB06rWm9kCq5PSBFM5j-HJ6oFB-ngn37FMLQ align="left")

Ahora probamos nuestra función, subiendo un video al bucket S3

![](https://lh4.googleusercontent.com/fbu7ipj_WAyHTy_WtbvaNgEpWoqGtY3pfgIWkSlNuYetMVK-tK5MLTzkez30PwkixGDc75nRR3ey-XPUXx4jUEC23reXqAjcw9A1TbFrKPbXw9OXyOkuLUNd12zbCYUWPkLGTZJZYdUs1HVWSsRREZlw3YT6nqqWPzKsnxfrlb_cVl0YpN7ynmr7bZLvvg align="left")

![](https://lh5.googleusercontent.com/8Y25wnjJKOrBir91O2CSDNUmk0ASVpkxqnJu6fPC17WI2lBmIGC2Gl1ntc2ryMuUanHvwHeTcSXEMxEVw1ymChi5BsX1cDDnNa_LpuaSYUM2wBre5OGiSX1JmS4Z2Il9AsduLhty-gHmEEOtZ9-xMJuKqMs6NzvvE39dXQGZvNghsB3QkvGxcRfy6dGVhA align="left")

Veremos que tendremos un nuevo bucket donde encontraremos diversos formatos de nuestro video original

![](https://lh4.googleusercontent.com/PIHpEhP8nBTipXt9TVlCLiYRsyWGOFST3A4NBTVPpTxLWAck_o_j4Ije3codvDSYJEeXtxefX-TbdHJVqao_WZjwPbcuGyLUqmQrt4RHsUj7mswRTi8-G4-0VZ4IXSdw-nMOzyPu38rZBm5JytHXWzpds2qY2dPuwH3g50cwWgFDApSxR4ToNDxpGWLpWw align="left")

**AWS Elemental MediaConvert:** [https://docs.aws.amazon.com/mediaconvert/index.html](https://docs.aws.amazon.com/mediaconvert/index.html)

El repositorio con la solución lo encuentras en:

[https://github.com/alfalfita/decoder-video-with-sam-and-lambda](https://github.com/alfalfita/decoder-video-with-sam-and-lambda)
