node.js - nodejs - AWS Lambda haciendo miniaturas de video
lambda node js (7)
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?
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
.
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í:
- 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) -
Cuando se llame a su función, mueva el binario a(Actualización de febrero de 2017: se informa que esto ya no es necesario, re:/tmp/
dir ychmod
para tener acceso@loretoparisi
y las respuestas de@allen
). - 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.
Obviamente, la copia y el chmod (paso 2) 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 arquitectura.
(La 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 siguiente actualización se dejó para la posteridad, pero ya no es necesaria:
ACTUALIZACIÓN CON MÁS DETALLE:
Descargué el binario ffmpeg estático here . Amazon recomienda iniciar un EC2 y crear un binario para su uso allí, ya que el entorno será el mismo que el de Lambda. Probablemente sea una buena idea, pero más trabajo, y esta descarga estática funcionó para mí.
Solo coloqué el binario ffmpeg
en la carpeta /dist
-archiving de mi proyecto.
Cuando subes tu zip a lambda, vive en /var/task/
. Por la razón 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 / descarado auto-plug: estoy trabajando en un conjunto de módulos para facilitar la creación de funciones Lambda a partir de módulos Lambduh bajo el nombre de 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.
En el momento en que escribo, como se describió anteriormente, ya no es necesario copiar los 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://.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 confirmed 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 de lambda (la máquina) que está bien descrito en Explorando el entorno del Tiempo de ejecución de Lambda .
No estoy seguro de qué biblioteca de modo personalizado usaría para la tarea ffmpeg; Sin embargo los pasos a seguir para lograrlo son los mismos.
- Cree un directorio separado para su proyecto lambda
- Ejecute
npm install <package name>
dentro de ese directorio (esto colocaría automáticamente los node_modules y los archivos apropiados) - Cree el archivo
index.js
en el directorio del proyecto lambda, luego use elrequire(<package-name>)
y realice su tarea principal para la creación de miniaturas de videos - 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.
- El resto de las configuraciones siguen el mismo proceso, como el rol de ejecución IAM, las especificaciones de Trigger, Memory y Timeout, etc.
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ás usando Windows 10, usa el shell de Ubuntu Bash para crear el paquete.
He creado una plantilla de función Node.js específicamente para este propósito here . Le permite implementar uno o más archivos binarios en Lambda, luego ejecutar un comando de shell arbitrario y capturar la salida.
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;
})
Creé un repositorio de GitHub que hace exactamente esto (además de cambiar el tamaño del video al mismo tiempo). La respuesta de Russ Matney fue extremadamente útil para hacer ejecutable el archivo FFmpeg.