136 lines
3.9 KiB
Plaintext
136 lines
3.9 KiB
Plaintext
---
|
|
title: "Process images using Sharp"
|
|
sidebarTitle: "Sharp image processing"
|
|
description: "This example demonstrates how to process images using the Sharp library with Trigger.dev."
|
|
---
|
|
|
|
import LocalDevelopment from "/snippets/local-development-extensions.mdx";
|
|
|
|
## Overview
|
|
|
|
This task optimizes and watermarks an image using the Sharp library, and then uploads the processed image to R2 storage.
|
|
|
|
## Adding build configurations
|
|
|
|
To use this example, you'll first need to add these build settings to your `trigger.config.ts` file:
|
|
|
|
```ts trigger.config.ts
|
|
import { defineConfig } from "@trigger.dev/sdk/v3";
|
|
|
|
export default defineConfig({
|
|
project: "<project ref>",
|
|
// Your other config settings...
|
|
build: {
|
|
// This is required to use the Sharp library
|
|
external: ["sharp"],
|
|
},
|
|
});
|
|
```
|
|
|
|
<Note>
|
|
Any packages that install or build a native binary should be added to external, as native binaries
|
|
cannot be bundled.
|
|
</Note>
|
|
|
|
## Key features
|
|
|
|
- Resizes and rotates an image
|
|
- Adds a watermark to the image
|
|
- Uploads the processed image to R2 storage
|
|
|
|
## Task code
|
|
|
|
```ts trigger/sharp-image-processing.ts
|
|
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
import { logger, task } from "@trigger.dev/sdk/v3";
|
|
import fs from "fs/promises";
|
|
import fetch from "node-fetch";
|
|
import os from "os";
|
|
import path from "path";
|
|
import sharp from "sharp";
|
|
|
|
// Initialize R2 client
|
|
const r2Client = new S3Client({
|
|
region: "auto",
|
|
endpoint: process.env.R2_ENDPOINT,
|
|
credentials: {
|
|
accessKeyId: process.env.R2_ACCESS_KEY_ID ?? "",
|
|
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY ?? "",
|
|
},
|
|
});
|
|
|
|
export const sharpProcessImage = task({
|
|
id: "sharp-process-image",
|
|
run: async (payload: { imageUrl: string; watermarkUrl: string }) => {
|
|
const { imageUrl, watermarkUrl } = payload;
|
|
|
|
// Generate temporary and output file names
|
|
const tempDirectory = os.tmpdir();
|
|
const outputPath = path.join(tempDirectory, `output_${Date.now()}.jpg`);
|
|
|
|
// Fetch the image and watermark
|
|
const [imageResponse, watermarkResponse] = await Promise.all([
|
|
fetch(imageUrl),
|
|
fetch(watermarkUrl),
|
|
]);
|
|
const imageBuffer = await imageResponse.arrayBuffer();
|
|
const watermarkBuffer = await watermarkResponse.arrayBuffer();
|
|
|
|
// Optimize the image using Sharp
|
|
await sharp(Buffer.from(imageBuffer))
|
|
.rotate(90) // Rotate the image by 90 degrees
|
|
.resize(800, 600) // Resize the image to 800x600
|
|
.composite([
|
|
{
|
|
input: Buffer.from(watermarkBuffer),
|
|
gravity: "southeast", // Position the watermark in the bottom-right corner
|
|
},
|
|
])
|
|
.toFormat("jpeg")
|
|
.toFile(outputPath);
|
|
|
|
// Log the output file path
|
|
logger.log(`Optimized image saved at: ${outputPath}`);
|
|
|
|
// Read the optimized image file
|
|
const optimizedImageBuffer = await fs.readFile(outputPath);
|
|
|
|
// Upload the optimized image to R2, replacing slashes with underscores
|
|
const r2Key = `processed-images/${path.basename(outputPath)}`;
|
|
|
|
const uploadParams = {
|
|
Bucket: process.env.R2_BUCKET,
|
|
Key: r2Key,
|
|
Body: optimizedImageBuffer,
|
|
};
|
|
|
|
// Upload the image to R2 and get the URL
|
|
await r2Client.send(new PutObjectCommand(uploadParams));
|
|
const r2Url = `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com/${process.env.R2_BUCKET}/${r2Key}`;
|
|
logger.log("Optimized image uploaded to R2", { url: r2Url });
|
|
|
|
// Delete the temporary file
|
|
await fs.unlink(outputPath);
|
|
|
|
// Return the optimized image buffer, file path, and R2 URL
|
|
return {
|
|
optimizedImageBuffer,
|
|
optimizedImagePath: outputPath,
|
|
r2Url,
|
|
};
|
|
},
|
|
});
|
|
```
|
|
|
|
## Testing your task
|
|
|
|
To test this task in the dashboard, you can use the following payload:
|
|
|
|
```json
|
|
{
|
|
"imageUrl": "<an-image-url.jpg>", // Replace with a URL to a JPEG image
|
|
"watermarkUrl": "<an-image-url.png>" // Replace with a URL to a PNG watermark image
|
|
}
|
|
```
|
|
|
|
<LocalDevelopment packages={"the Sharp image processing library"} /> |