chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
---
|
||||
title: "Convert an image to a cartoon using Fal.ai"
|
||||
sidebarTitle: "Fal.ai image to cartoon"
|
||||
description: "This example task generates an image from a URL using Fal.ai and uploads it to Cloudflare R2."
|
||||
---
|
||||
|
||||
## Walkthrough
|
||||
|
||||
This video walks through the process of creating this task in a Next.js project.
|
||||
|
||||
<iframe
|
||||
width="100%"
|
||||
height="315"
|
||||
src="https://www.youtube.com/embed/AyRT4X8dHK0?si=ugA172V_3TMjik9h"
|
||||
title="Trigger.dev walkthrough"
|
||||
allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
referrerPolicy="strict-origin-when-cross-origin"
|
||||
allowFullScreen
|
||||
/>
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- An existing project
|
||||
- A [Trigger.dev account](https://cloud.trigger.dev) with Trigger.dev [initialized in your project](/quick-start)
|
||||
- A [Fal.ai](https://fal.ai/) account
|
||||
- A [Cloudflare](https://developers.cloudflare.com/r2/) account with an R2 bucket setup
|
||||
|
||||
## Task code
|
||||
|
||||
This task converts an image to a cartoon using Fal.ai, and uploads the result to Cloudflare R2.
|
||||
|
||||
```ts trigger/fal-ai-image-to-cartoon.ts
|
||||
import { logger, task } from "@trigger.dev/sdk";
|
||||
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
||||
import * as fal from "@fal-ai/serverless-client";
|
||||
import fetch from "node-fetch";
|
||||
import { z } from "zod";
|
||||
|
||||
// Initialize fal.ai client
|
||||
fal.config({
|
||||
credentials: process.env.FAL_KEY, // Get this from your fal.ai dashboard
|
||||
});
|
||||
|
||||
// Initialize S3-compatible client for Cloudflare R2
|
||||
const s3Client = new S3Client({
|
||||
// How to authenticate to R2: https://developers.cloudflare.com/r2/api/s3/tokens/
|
||||
region: "auto",
|
||||
endpoint: process.env.R2_ENDPOINT,
|
||||
credentials: {
|
||||
accessKeyId: process.env.R2_ACCESS_KEY_ID ?? "",
|
||||
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY ?? "",
|
||||
},
|
||||
});
|
||||
|
||||
export const FalResult = z.object({
|
||||
images: z.tuple([z.object({ url: z.string() })]),
|
||||
});
|
||||
|
||||
export const falAiImageToCartoon = task({
|
||||
id: "fal-ai-image-to-cartoon",
|
||||
run: async (payload: { imageUrl: string; fileName: string }) => {
|
||||
logger.log("Converting image to cartoon", payload);
|
||||
|
||||
// Convert image to cartoon using fal.ai
|
||||
const result = await fal.subscribe("fal-ai/flux/dev/image-to-image", {
|
||||
input: {
|
||||
prompt: "Turn the image into a cartoon in the style of a Pixar character",
|
||||
image_url: payload.imageUrl,
|
||||
},
|
||||
onQueueUpdate: (update) => {
|
||||
logger.info("Fal.ai processing update", { update });
|
||||
},
|
||||
});
|
||||
|
||||
const $result = FalResult.parse(result);
|
||||
const [{ url: cartoonImageUrl }] = $result.images;
|
||||
|
||||
// Download the cartoon image
|
||||
const imageResponse = await fetch(cartoonImageUrl);
|
||||
const imageBuffer = await imageResponse.arrayBuffer().then(Buffer.from);
|
||||
|
||||
// Upload to Cloudflare R2
|
||||
const r2Key = `cartoons/${payload.fileName}`;
|
||||
const uploadParams = {
|
||||
Bucket: process.env.R2_BUCKET, // Create a bucket in your Cloudflare dashboard
|
||||
Key: r2Key,
|
||||
Body: imageBuffer,
|
||||
ContentType: "image/png",
|
||||
};
|
||||
|
||||
logger.log("Uploading cartoon to R2", { key: r2Key });
|
||||
await s3Client.send(new PutObjectCommand(uploadParams));
|
||||
|
||||
logger.log("Cartoon uploaded to R2", { key: r2Key });
|
||||
|
||||
return {
|
||||
originalUrl: payload.imageUrl,
|
||||
cartoonUrl: `File uploaded to storage at: ${r2Key}`,
|
||||
};
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Testing your task
|
||||
|
||||
You can test your task by triggering it from the Trigger.dev dashboard.
|
||||
|
||||
```json
|
||||
"imageUrl": "<image-url>", // Replace with the URL of the image you want to convert to a cartoon
|
||||
"fileName": "<file-name>" // Replace with the name you want to save the file as in Cloudflare R2
|
||||
```
|
||||
Reference in New Issue
Block a user