2
votes

Comment optimiser les images téléchargées par l'utilisateur et également les images existantes sur le serveur dans Meteor

Actuellement, mon groupe exécute une application meteor avec des centaines de milliers d'images qui sont toutes de très grande taille. Nous aurions dû le faire il y a longtemps, mais nous avons besoin d'un moyen de les optimiser pour faciliter les temps de chargement. Je recherche une solution pour pouvoir enregistrer l'image dans plusieurs tailles lorsque l'utilisateur la télécharge à partir de notre application (par exemple, taille réelle, moyenne, miniature) et également faire pivoter automatiquement et permettre à l'utilisateur de faire pivoter. Nous utilisons Amazon S3 pour héberger toutes nos images. Nous avons également besoin d'un moyen de convertir toutes les images existantes dans ces formats de taille du côté serveur.

J'ai essayé de mettre en œuvre quelque chose il y a quelque temps et cela n'a pas réussi. J'ai configuré imagemagick sur notre serveur mais j'ai eu du mal à le faire fonctionner en production car l'image était enregistrée temporairement sur la mémoire du serveur pour être traitée, mais cela provoquait des plantages en raison de la quantité limitée de mémoire. J'ai peu d'expérience avec ce genre de choses.

Ma deuxième pensée a été d'utiliser le canevas HTML pour redimensionner les images. Cela fonctionnerait, je pense, pour les images nouvellement téléchargées. Mais je recherche toujours un moyen de traiter les images existantes.

J'ai considéré:

  • Peut-être qu'AWS a un moyen intégré de les traiter. Cela ne me dérangerait pas de le faire de cette façon.
  • Une sorte de package Meteor / node qui peut vous aider.
  • Configuration d'un autre serveur uniquement pour traiter les images.
  • Utilisation d'un traitement d'image tiers.

Si quelqu'un pouvait me donner des conseils pour que je puisse lancer le bal, ce serait très utile!


0 commentaires

3 Réponses :


2
votes

libvips peut redimensionner les images sans utiliser de mémoire ou de disque --- les pixels sont diffusés via le système par petits morceaux, le décodage et le recodage s'effectuant en même temps.

Par exemple, avec une image JPG de 10 000 x 10 000 pixels, je vois:

$ /usr/bin/time -f %M:%e convert wtc.jpg -resize 5000x5000 x.jpg
1263232:2.02

Ceci est un 4 cœurs, 8 fils i7. Il utilise 98 Mo de mémoire et prend 0,65 s de temps réel. Il existe un chapitre dans la documentation présentant vipsthumbnail .

À titre de comparaison, avec ImageMagick 6, je vois:

$ vipsheader wtc.jpg 
wtc.jpg: 9372x9372 uchar, 3 bands, srgb, jpegload
$ /usr/bin/time -f %M:%e vipsthumbnail wtc.jpg -s 5000x5000 -o x.jpg
98720:0.65

1,3 Go de mémoire et cela prend 2 secondes de temps réel - environ 10 fois plus de mémoire et 3 fois plus lent .

Parce que vipsthumbnail utilise si peu de mémoire, vous pouvez le combiner avec GNU parallèle sans avoir besoin d'un serveur avec beaucoup, beaucoup de Go de mémoire. Sur cet i7, je peux utilement en exécuter quatre à la fois et obtenir une accélération d'environ 4x, donc peut-être 12 fois plus rapide qu'ImageMagick dans son ensemble.

sharp est une liaison de nœuds populaire pour libvips , ce qui pourrait être plus pratique. Il existe également des liaisons pour Python, Ruby, PHP, Go, Lua, etc. etc.

(avertissement: je suis l'un des mainteneurs de libvips, donc je ne suis pas très neutre) p>


1 commentaires

Merci. Cela semble être une très bonne option! Semble cocher toutes les cases. Nous allons essayer. Je veux voir quelles autres options peuvent se présenter avant de marquer cela comme la réponse. Ma plus grande préoccupation est le temps qu'il faudrait pour traiter les images existantes, même si je ne peux pas m'attendre à ce que ce soit rapide avec la quantité d'images que nous avons actuellement. ;)



0
votes

J'utilise https://www.imagemagick.org/ pour redimensionner, recadrer, faire pivoter mes images . cela fonctionne avec météore. Ce sera un bon point de départ à explorer. https://github.com/CollectionFS/Meteor-CollectionFS


2 commentaires

Omgabee a écrit dans la question, que imagemagick provoque des problèmes liés à la mémoire, en raison de la sauvegarde temporaire de copies d'images en mémoire.


Mon utilisation de l'image est limitée, je n'ai donc rencontré aucun problème jusqu'à présent.



1
votes

Je vois deux façons sur deux budgets complètement différents:

  1. Ce n'est pas une méthode que je recommande à moins que vous ne disposiez que de 1 à 2 Go ( https://transloadit.com/demos/file-importing/resize-all-images-in-an-s3-bucket/ )

  2. Liez votre S3 à un service Cloudinary et effectuez les transformations avec Cloudinary (vous ne l'aimerez pas ($$) pour le nombre d'images que vous avez).

  3. Dans AWS, j'espère que vous utilisez Cloudfront pour servir vos actifs. Indépendamment de la technologie de transformation, vous ferez principalement 2 choses:

    • Créez 1 fonction Lambda pour la transformation de tous les nouveaux actifs créés dans S3. Ce que je fais est de «surveiller» un compartiment S3 et toutes les nouvelles choses qui arrivent déclenchent ma fonction Lambda et je crée les actifs dans 2 autres dossiers et je me retrouve avec: full res, half res et thumb res. Dans Meteor, vous associez ensuite chaque taille à ce dont vous avez besoin. Le cas le plus courant est celui où vous avez une image de profil utilisateur dont vous avez besoin pour l'afficher sous forme d'en-tête complet, de liste ou de petit pouce dans une discussion.
    • Créez 1 bord Lambda (un peu plus $$ je crois) et attachez-le à votre bord Cloudfront pour répondre à tous les appels. Si le coût de stockage n'est pas trop élevé pour vous pour le volume actuel stocké, vous pouvez transformer vos images au fur et à mesure qu'elles sont demandées et remplacer les anciennes images plus grandes, plutôt que de les exécuter en masse en un seul processus.

Au lieu de Lambda Edge, vous pourriez probablement configurer une machine EC2 avec Node et exécuter une fonction pour parcourir tous vos actifs S3 et effectuer la transformation.

Quoi qu'il en soit, je pense que ce que vous voulez faire, c'est tout AWS, sans rapport avec votre Meteor. Une dernière chose à faire: optimiser les images avant leur téléchargement. Si vous utilisez React avec Meteor, je pourrais vous fournir les composants nécessaires, sinon je peux vous donner les composants et vous écrire la couche de vue Blaze ou tout autre élément que vous pouvez utiliser.

J'ai les fonctions de transformation Lambda dans production basée sur ImageMagic au cas où vous seriez intéressé à suivre cette voie. Je prévois également de "mettre à niveau" cette fonction pour utiliser Sharp (comme dans l'exemple) mais pour le moment elle se porte bien en production, je changerai quand j'aurai un peu de temps. Vérifiez cet exemple:

  Download the image from S3, transform, and upload to a different S3 bucket or folder.

  const dstKeyResizedHalf = `p-half/` + imageName
  s3.getObject({
    Bucket: srcBucket,
    Key: srcKey
  }).promise()
    .then(data => Sharp(data.Body)
      .jpeg({
        chromaSubsampling: '4:4:4',
        progressive: true
      })
      .resize(WEB_WIDTH_MAX)
      .toFormat('jpg')
      .toBuffer()
    )
    .then(buffer => s3.putObject({
      Body: buffer,
      Bucket: dstBucket,
      ContentType: 'image/jpg',
      Key: dstKeyResizedHalf,
      CacheControl: 'max-age=864000'
    }).promise())
    .catch(err => callback(err))
}


3 commentaires

Ceci est extrêmement utile. Je vous remercie. Je pense qu'après avoir lu les réponses et consulté certaines pages en ligne, Lambda est la voie à suivre. Le déclenchement de la fonction Lambda sur demande d'image pour les images plus anciennes est une solution brillante.


Si vous décidez d'utiliser Lambda, veuillez me le faire savoir et je vous fournirai les éléments nécessaires si vous en avez besoin.


Donc, je voulais mettre à jour à ce sujet. J'ai fini par emprunter la voie Lambda et cela fonctionne très bien. J'ai configuré une passerelle API pour déclencher la fonction Lambda. C'était le meilleur moyen pour moi afin que je puisse obtenir des commentaires sur mes applications et que la transformation d'image est terminée et réussie. J'ai également mis en place un processus cron pour transformer à nouveau les images existantes en utilisant la passerelle API. Cela fonctionne très bien jusqu'à présent. Alors, merci pour l'aide!