AWS Lambda haciendo miniaturas de video

Quiero hacer miniaturas de los videos subidos a S3, sé cómo hacerlo con Node.js y ffmpeg.

Según esta publicación del foro puedo agregar bibliotecas:

ImageMagick es la única biblioteca externa que actualmente se proporciona de forma predeterminada, pero puede incluir cualquier dependencia adicional en el archivo zip que proporciona cuando crea una función Lambda. Tenga en cuenta que si se trata de una biblioteca nativa o un ejecutable, deberá asegurarse de que se ejecuta en Amazon Linux.

Pero, ¿cómo puedo poner el binario estático ffmpeg en aws lambda?

¿Y cómo puedo llamar desde Node.js a este binario estático (ffmpeg) con AWS Lambda?

Soy novato con Amazon AWS y Linux

¿Alguien puede ayudarme?

El proceso descrito por Naveen es correcto, pero pasa por alto un detalle que puede ser bastante doloroso, incluido el binario ffmpeg en el zip y acceder a él dentro de la función lambda.

Acabo de pasar por esto, fue así:

  1. Incluya el binario estático ffmpeg en su paquete de funciones lambda comprimidas (tengo una tarea excelente para copiar esto en /dist cada vez que se construye)
  2. Cuando se llama a su función, mueva el binario a /tmp/ dir y chmod para tener acceso (Actualización de febrero de 2017: se informa que ya no es necesario, re: @loretoparisi y las respuestas de @allen ).
  3. actualice su PATH para incluir el ejecutable ffmpeg (utilicé fluent-ffmpeg que le permite configurar dos vars env para manejar eso más fácilmente.

Déjame saber si se necesitan más detalles, puedo actualizar esta respuesta.

La copia y el chmod (paso 2) obviamente no son ideales … me encantaría saber si alguien ha encontrado una mejor manera de manejar esto, o si esto es típico de este estilo de architecture.

(Segunda actualización, escribiéndola antes de la primera actualización b / c es más relevante):

El paso de copiar + chmod ya no es necesario, como señaló @Allen. Estoy ejecutando ffmpeg en las funciones Lambda directamente desde / var / task / sin ningún problema en este momento. Asegúrese de chmod 755 cualesquiera binarios antes de subirlos a Lambda (también como lo señaló @Allen).

Ya no uso fluent-ffmpeg para hacer el trabajo. Más bien, estoy actualizando el PATH para incluir el process.env['LAMBDA_TASK_ROOT'] y ejecutando scripts de bash simples.

En la parte superior de su función Lambda:

 process.env['PATH'] = process.env['PATH'] + "/" + process.env['LAMBDA_TASK_ROOT'] 

Para un ejemplo que usa ffmpeg: lambda-pngs-to-mp4 .

Para una gran cantidad de componentes lambda útiles: lambduh .

La actualización a continuación se dejó para la posteridad, pero ya no es necesaria:

ACTUALIZACIÓN CON MÁS DETALLE:

Descargué el binario ffmpeg estático aquí . Amazon recomienda iniciar un EC2 y crear un binario para su uso allí, porque ese entorno será el mismo que las condiciones en las que se ejecuta Lambda. Probablemente sea una buena idea, pero más trabajo, y esta descarga estática funcionó para mí.

Metí solo el binario ffmpeg en la carpeta /dist -archiving de mi proyecto.

Cuando subes tu zip a lambda, vive en /var/task/ . Por el motivo que sea, me encontré con problemas de acceso al intentar usar el binario en esa ubicación y más problemas al tratar de editar los permisos en el archivo allí. Una solución rápida es mover los permisos binarios a /tmp/ y chmod allí.

En Nodo, puede ejecutar shell a través de un child_process . Lo que hice se ve así:

 require('child_process').exec( 'cp /var/task/ffmpeg /tmp/.; chmod 755 /tmp/ffmpeg;', function (error, stdout, stderr) { if (error) { //handle error } else { console.log("stdout: " + stdout) console.log("stderr: " + stderr) //handle success } } ) 

Esto debería darle un binario ffmpeg ejecutable en su función lambda, pero aún debe asegurarse de que esté en su $ PATH.

Abandoné fluent-ffmpeg y usé node para lanzar comandos ffmpeg en favor de simplemente lanzar un script de bash desde el nodo, así que para mí, tuve que agregar /tmp/ a mi ruta en la parte superior de la función lambda:

process.env.PATH = process.env.PATH + ':/tmp/'

Si usa fluent-ffmpeg, puede establecer la ruta a ffmpeg a través de:

process.env['FFMPEG_PATH'] = '/tmp/ffmpeg';

Un poco relacionado / descaro de auto-conexión: estoy trabajando en un conjunto de módulos para facilitar la creación de funciones Lambda a partir de módulos compostables bajo el nombre Lambduh . Podría ahorrar algo de tiempo para juntar estas cosas. Un ejemplo rápido: manejar este escenario con lambduh-execute sería tan simple como:

 promises.push(execute({ shell: "cp /var/task/ffmpeg /tmp/.; chmod 755 /tmp/ffmpeg", }) 

Donde las promises es una serie de promesas para ser ejecutadas.

Creé un repository de GitHub que hace exactamente esto (y también cambia el tamaño del video al mismo tiempo). La respuesta de Russ Matney fue extremadamente útil para hacer ejecutable el archivo FFmpeg.

No estoy seguro de qué biblioteca de modo personalizado usaría para la tarea ffmpeg; Sin embargo los pasos a realizar son los mismos.

  1. Cree un directorio separado para su proyecto lambda
  2. Ejecute npm install dentro de ese directorio (esto colocaría automáticamente los node_modules y los archivos apropiados)
  3. Cree el archivo index.js en el directorio del proyecto lambda, luego use el require() y realice su tarea principal para la creación de miniaturas de video
  4. Una vez que haya terminado, puede comprimir la carpeta del proyecto lambda y cargarla. Soy la consola de administración de AWS y configurar el archivo de índice y el controlador.
  5. El rest de las configuraciones siguen el mismo proceso, como el rol de ejecución de IAM, el disparador, la memoria y las especificaciones de tiempo de espera, etc.

Conseguí este trabajo sin moverlo a /tmp . Corrí chmod 755 en mi ejecutable y luego funcionó! Tuve problemas cuando previamente lo puse a chmod 777 .

En el momento en que escribo, como se describió anteriormente, ya no es necesario copiar archivos binarios de la carpeta actual, es decir, la process.env['LAMBDA_TASK_ROOT'] var/task o el process.env['LAMBDA_TASK_ROOT'] a la carpeta /tmp . Así que solo hay que hacer.

chmod 755 dist/ff*

si tienes tus binarios ffmpeg y ffprobe allí.

Por cierto, anteriormente mi solución de 2 centavos que desperdició 2 días fue esta

 Configure : function(options, logger) { // default options this._options = { // Temporay files folder for caching and modified/downloaded binaries tempDir : '/tmp/', /** * Copy binaries to temp and fix permissions * default to false - since this is not longer necessary * @see http://stackoverflow.com/questions/27708573/aws-lambda-making-video-thumbnails/29001078#29001078 */ copyBinaries : false }; // override defaults for (var attrname in options) { this._options[attrname] = options[attrname]; } this.logger=logger; var self=this; // add temporary folder and task root folder to PATH process.env['PATH'] = process.env['PATH'] + ':/tmp/:' + process.env['LAMBDA_TASK_ROOT'] if(self._options.copyBinaries) { var result = {} execute(result, { shell: "cp ./ffmpeg /tmp/.; chmod 755 /tmp/ffmpeg", // copies an ffmpeg binary to /tmp/ and chmods permissions to run it logOutput: true }) .then(function(result) { return execute(result, { shell: "cp ./ffprobe /tmp/.; chmod 755 /tmp/ffprobe", // copies an ffmpeg binary to /tmp/ and chmods permissions to run it logOutput: true }) }) .then(function(result) { self.logger.info("LambdaAPIHelper.Configure done."); }) .fail(function(err) { self.logger.error("LambdaAPIHelper.Configure: error %s",err); }); } //copyBinaries } 

ayudado por el buen módulo lambduh :

 // lambuh & dependencies var Q = require('q'); var execute = require('lambduh-execute'); 

Como se describe aquí y confirmado por el autor del módulo ahora, esto puede considerarse no necesario, por cierto, es interesante tener una buena comprensión del entorno del tiempo de ejecución lambda (la máquina) que está bien descrito en Explorando el entorno del Tiempo de ejecución de Lambda .

Simplemente pasé por los mismos problemas descritos anteriormente y terminé moviéndome con el mismo concepto de mover mis scripts que requieren ejecución al directorio / tmp.

 var childProcess = require("child_process"); var Q = require('q'); 

El código que usé está abajo con promesas:

 .then(function(result) { console.log('Move shell ffmpeg shell script to executable state and location'); var def = Q.defer(); childProcess.exec("mkdir /tmp/bin; cp /var/task/bin/ffmpeg /tmp/bin/ffmpeg; chmod 755 /tmp/bin/ffmpeg", function (error, stdout, stderr) { if (error) { console.log("error: " + error) } else { def.resolve(result); } } ) return def.promise; }) 

Para que el binario sea ejecutable directamente en AWS Lambda (sin tener que copiar primero a / tmp y chmod), debe asegurarse de que el binario tenga permiso de ejecución cuando se agregue al archivo ZIP .

Esto es problemático en Windows porque Windows no reconoce los binarios de Linux. Si está utilizando Windows 10, use el shell de Ubuntu Bash para crear el paquete.

He creado una plantilla de función Node.js específicamente para este propósito aquí . Le permite implementar uno o más archivos binarios en Lambda, luego ejecutar un comando de shell arbitrario y capturar la salida.