web-dev-qa-db-fra.com

AWS Lambda création de vignettes vidéo

Je veux créer des vignettes à partir de vidéos téléchargées sur S3, je sais comment le créer avec Node.js et ffmpeg. 

Selon cet article du forum je peux ajouter des bibliothèques:

ImageMagick est la seule bibliothèque externe actuellement fournie par Par défaut, mais vous pouvez inclure toutes les dépendances supplémentaires dans le fichier .zip fichier que vous fournissez lorsque vous créez une fonction Lambda. Notez que si cela est une bibliothèque ou un exécutable natif, vous devrez vous assurer qu'il fonctionne sur Amazon Linux.

Mais comment puis-je mettre du binaire statique ffmpeg sur aws lambda?

Et comment puis-je appeler depuis Node.js ce binaire statique (ffmpeg) avec AWS Lambda?

Je suis novice avec Amazon AWS et Linux

Quelqu'un peut-il m'aider?

21
Jesus

Le processus décrit par Naveen est correct, mais il dissimule un détail qui peut être très pénible - notamment le fichier binaire ffmpeg dans le zip et son accès au sein de votre fonction lambda.

Je viens de traverser ça, ça a marché comme ça:

  1. Incluez le binaire statique ffmpeg dans votre paquet de fonction lambda compressé (j'ai une tâche gulp pour la copier dans le /dist chaque fois qu'elle est créée)
  2. Lorsque votre fonction est appelée, déplacez le binaire vers un /tmp/ dir et un chmod pour vous donner l'accès. (Mise à jour février 2017: il a été signalé que cela n'était plus nécessaire, à propos des réponses de @loretoparisi et de @allen).
  3. mettez à jour votre PATH pour inclure l'exécutable ffmpeg (j'ai utilisé fluent-ffmpeg qui vous permet de définir deux env vars pour gérer cela plus facilement. 

Faites-moi savoir si plus de détails sont nécessaires, je peux mettre à jour cette réponse.

La copie et chmod (étape 2) n’est évidemment pas idéale… aimerions savoir si quelqu'un a trouvé un meilleur moyen de gérer cela, ou si cela est typique de ce style d'architecture.

(2ème mise à jour, l'écrire avant la première mise à jour b/c c'est plus pertinent):

L'étape copy + chmod n'est plus nécessaire, comme l'a souligné @Allen - j'exécute ffmpeg dans les fonctions Lambda directement à partir de/var/task/sans aucun problème à ce stade. Assurez-vous de chmod 755 quels que soient les fichiers binaires avant de les télécharger sur Lambda (comme l'a souligné @Allen).

Je n'utilise plus fluent-ffmpeg pour faire le travail. Au lieu de cela, je mets à jour le PATH pour inclure le process.env['LAMBDA_TASK_ROOT'] et exécute des scripts bash simples.

Au sommet de votre fonction Lambda:

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

Pour un exemple qui utilise ffmpeg: lambda-pngs-to-mp4 .

Pour une multitude de composants lambda utiles: lambduh .

La mise à jour ci-dessous laissée à la postérité, mais n'est plus nécessaire:

MISE À JOUR AVEC PLUS DE DÉTAIL:

J'ai téléchargé le binaire statique ffmpeg ici . Amazon recommande de démarrer un EC2 et de créer un binaire pour votre utilisation, car cet environnement sera le même que les conditions sur lesquelles Lambda est exécuté. Probablement une bonne idée, mais plus de travail, et ce téléchargement statique a fonctionné pour moi.

J'ai extrait uniquement le binaire ffmpeg dans le dossier /dist de mon projet à archiver.

Lorsque vous transférez votre fichier Zip sur lambda, il se trouve à /var/task/. Pour une raison quelconque, j'ai rencontré des problèmes d'accès en essayant d'utiliser le fichier binaire à cet emplacement, et d'autres problèmes en essayant de modifier les autorisations sur le fichier. Une solution rapide consiste à déplacer le fichier binaire vers les autorisations /tmp/ et chmod.

Dans Node, vous pouvez exécuter Shell via un child_process. Ce que j'ai fait ressemble à ceci:

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
    }
  }
)

Cela devrait vous donner un binaire ffmpeg exécutable dans votre fonction lambda - mais vous devez tout de même vous assurer qu'il se trouve sur votre $ PATH. 

J'ai abandonné fluent-ffmpeg et utilisé noeud pour lancer des commandes ffmpeg au lieu de lancer un script bash depuis noeud. Pour moi, je devais donc ajouter /tmp/ à mon chemin en haut de la fonction lambda:

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

Si vous utilisez fluent-ffmpeg, vous pouvez définir le chemin d'accès à ffmpeg via:

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

Auto-prise quelque peu liée/sans vergogne: je travaille sur un ensemble de modules pour faciliter la création de fonctions Lambda à partir de modules composables sous le nom Lambduh . Cela pourrait vous faire gagner du temps. Un exemple rapide: gérer ce scénario avec lambduh-execute serait aussi simple que:

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

promises est un tableau de promesses à exécuter.

37
Russ Matney

J'ai créé un GitHub repo qui fait exactement cela (ainsi que redimensionne la vidéo en même temps). La réponse de Russ Matney a été extrêmement utile pour rendre le fichier FFmpeg exécutable.

6
BKH

Je ne sais pas quelle bibliothèque de mode personnalisé vous utiliseriez pour la tâche ffmpeg; néanmoins, les étapes à suivre sont les mêmes.

  1. Créez un répertoire séparé pour votre projet lambda 
  2. Exécutez npm install <package name> dans ce répertoire (ceci mettrait automatiquement en place les modules et les fichiers appropriés)
  3. Créez le fichier index.js dans le répertoire du projet lambda, puis utilisez la fonction require(<package-name>) et effectuez votre tâche principale pour la création de vignettes vidéo. 
  4. Une fois que vous avez terminé, vous pouvez compresser le dossier du projet lambda et le télécharger en tant que console de gestion AWS, puis configurer le fichier d'index et le gestionnaire.
  5. Le reste des configurations suit le même processus que les spécifications de rôle d'exécution IAM, de déclencheur, de mémoire et de délai d'attente, etc.
2
Naveen Vijay

Je travaille avec cela sans le déplacer vers /tmp. J'ai exécuté chmod 755 sur mon exécutable et ensuite cela a fonctionné! J'ai eu des problèmes lorsque je l'ai précédemment défini à chmod 777.

2
Allen

Au moment où j'écris, comme décrit ci-dessus, il n'est plus nécessaire de copier les fichiers binaires du dossier en cours, c'est-à-dire le dossier var/task ou process.env['LAMBDA_TASK_ROOT'] dans le dossier /tmp

chmod 755 dist/ff*

si vous y avez vos binaires ffmpeg et ffprobe.

En passant, auparavant, ma solution à 2 cents qui perdait 2 jours de temps était la suivante:

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

      }

aidé par le bon module lambduh:

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

Comme décrit ici et confirmé par l'auteur du module, ceci peut être considéré comme inutile, en passant, il est intéressant de bien comprendre l'environnement d'exécution lambda (la machine) qui est bien décrit dans Exploring the Lambda Runtime environnement .

2
loretoparisi

Je viens juste de passer en revue les problèmes décrits ci-dessus et je me suis retrouvé avec le même concept de déplacement de mes scripts nécessitant une exécution dans le répertoire/tmp. 

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

Le code que j'ai utilisé est ci-dessous avec des promesses:

.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;
  })
0
codin

Pour que le fichier binaire soit directement exécutable sur AWS Lambda (sans devoir copier au préalable dans/tmp et chmod), vous devez vous assurer que le fichier binaire dispose des droits d'exécution lorsqu'il est ajouté au fichier Zip.

Cela pose problème sous Windows car Windows ne reconnaît pas les fichiers binaires Linux. Si vous utilisez Windows 10, utilisez le shell Ubuntu Bash pour créer le paquet.

J'ai créé un modèle de fonction Node.js spécialement à cet effet ici . Il vous permet de déployer un ou plusieurs fichiers binaires sur Lambda, puis d'exécuter une commande shell arbitraire et de capturer la sortie.

0
Hai Phan