Skip to content

Commit eace78f

Browse files
authored
Added fal AI example (#1439)
1 parent e81b2a7 commit eace78f

File tree

3 files changed

+117
-60
lines changed

3 files changed

+117
-60
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
title: "Convert an image to a cartoon using fal AI"
3+
sidebarTitle: "fal AI image to cartoon"
4+
description: "This example demonstrates how to convert an image to a cartoon using fal AI with Trigger.dev."
5+
---
6+
7+
## Overview
8+
9+
Fal AI is a platform that provides access to advanced AI models for tasks such as image generation, text summarization, and hyperparameter tuning.
10+
11+
## Prerequisites
12+
13+
- A project with [Trigger.dev initialized](/quick-start)
14+
- A [fal AI](https://fal.ai/) account
15+
- A [Cloudflare](https://developers.cloudflare.com/r2/) account and bucket
16+
17+
## Task code
18+
19+
This task converts an image to a cartoon using fal AI, and uploads the result to Cloudflare R2.
20+
21+
```ts trigger/fal-ai-image-to-cartoon.ts
22+
import { logger, task } from "@trigger.dev/sdk/v3";
23+
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
24+
import * as fal from "@fal-ai/serverless-client";
25+
import fetch from "node-fetch";
26+
import { z } from "zod";
27+
28+
// Initialize fal.ai client
29+
fal.config({
30+
credentials: process.env.FAL_KEY, // Get this from your fal AI dashboard
31+
});
32+
33+
// Initialize S3-compatible client for Cloudflare R2
34+
const s3Client = new S3Client({
35+
// How to authenticate to R2: https://developers.cloudflare.com/r2/api/s3/tokens/
36+
region: "auto",
37+
endpoint: process.env.R2_ENDPOINT,
38+
credentials: {
39+
accessKeyId: process.env.R2_ACCESS_KEY_ID ?? "",
40+
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY ?? "",
41+
},
42+
});
43+
44+
export const FalResult = z.object({
45+
images: z.tuple([z.object({ url: z.string() })]),
46+
});
47+
48+
export const falAiImageToCartoon = task({
49+
id: "fal-ai-image-to-cartoon",
50+
run: async (payload: { imageUrl: string; fileName: string }) => {
51+
logger.log("Converting image to cartoon", payload);
52+
53+
// Convert image to cartoon using fal.ai
54+
const result = await fal.subscribe("fal-ai/flux/dev/image-to-image", {
55+
input: {
56+
prompt: "Turn the image into a cartoon in the style of a Pixar character",
57+
image_url: payload.imageUrl,
58+
},
59+
onQueueUpdate: (update) => {
60+
logger.info("Fal.ai processing update", { update });
61+
},
62+
});
63+
64+
const $result = FalResult.parse(result);
65+
const [{ url: cartoonImageUrl }] = $result.images;
66+
67+
// Download the cartoon image
68+
const imageResponse = await fetch(cartoonImageUrl);
69+
const imageBuffer = await imageResponse.arrayBuffer().then(Buffer.from);
70+
71+
// Upload to Cloudflare R2
72+
const r2Key = `cartoons/${payload.fileName}`;
73+
const uploadParams = {
74+
Bucket: process.env.R2_BUCKET, // Create a bucket in your Cloudflare dashboard
75+
Key: r2Key,
76+
Body: imageBuffer,
77+
ContentType: "image/png",
78+
};
79+
80+
logger.log("Uploading cartoon to R2", { key: r2Key });
81+
await s3Client.send(new PutObjectCommand(uploadParams));
82+
83+
logger.log("Cartoon uploaded to R2", { key: r2Key });
84+
85+
return {
86+
originalUrl: payload.imageUrl,
87+
cartoonUrl: `File uploaded to storage at: ${r2Key}`,
88+
};
89+
},
90+
});
91+
```
92+
93+
### Testing your task
94+
95+
You can test your task by triggering it from the Trigger.dev dashboard.
96+
97+
```json
98+
"imageUrl": "<image-url>", // Replace with the URL of the image you want to convert to a cartoon
99+
"fileName": "<file-name>" // Replace with the name you want to save the file as in Cloudflare R2
100+
```

docs/guides/introduction.mdx

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Tasks you can copy and paste to get started with Trigger.dev. They can all be ex
4141
| :---------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- |
4242
| [DALL·E 3 image generation](/guides/examples/dall-e3-generate-image) | Use OpenAI's GPT-4o and DALL·E 3 to generate an image and text. |
4343
| [Deepgram audio transcription](/guides/examples/deepgram-transcribe-audio) | Transcribe audio using Deepgram's speech recognition API. |
44+
| [fal AI image to cartoon](/guides/examples/fal-ai-image-to-cartoon) | Convert an image to a cartoon using fal AI, and upload the result to Cloudflare R2. |
4445
| [FFmpeg video processing](/guides/examples/ffmpeg-video-processing) | Use FFmpeg to process a video in various ways and save it to Cloudflare R2. |
4546
| [Firecrawl URL crawl](/guides/examples/firecrawl-url-crawl) | Learn how to use Firecrawl to crawl a URL and return LLM-ready markdown. |
4647
| [OpenAI with retrying](/guides/examples/open-ai-with-retrying) | Create a reusable OpenAI task with custom retry options. |

docs/mint.json

+16-60
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
{
22
"$schema": "https://mintlify.com/schema.json",
33
"name": "Trigger.dev",
4-
"openapi": [
5-
"/openapi.yml",
6-
"/v3-openapi.yaml"
7-
],
4+
"openapi": ["/openapi.yml", "/v3-openapi.yaml"],
85
"api": {
96
"playground": {
107
"mode": "simple"
@@ -122,43 +119,27 @@
122119
"navigation": [
123120
{
124121
"group": "Getting Started",
125-
"pages": [
126-
"introduction",
127-
"quick-start",
128-
"how-it-works",
129-
"upgrading-beta",
130-
"limits"
131-
]
122+
"pages": ["introduction", "quick-start", "how-it-works", "upgrading-beta", "limits"]
132123
},
133124
{
134125
"group": "Fundamentals",
135126
"pages": [
136127
{
137128
"group": "Tasks",
138-
"pages": [
139-
"tasks/overview",
140-
"tasks/schemaTask",
141-
"tasks/scheduled"
142-
]
129+
"pages": ["tasks/overview", "tasks/schemaTask", "tasks/scheduled"]
143130
},
144131
"triggering",
145132
"runs",
146133
"apikeys",
147134
{
148135
"group": "Configuration",
149-
"pages": [
150-
"config/config-file",
151-
"config/extensions/overview"
152-
]
136+
"pages": ["config/config-file", "config/extensions/overview"]
153137
}
154138
]
155139
},
156140
{
157141
"group": "Development",
158-
"pages": [
159-
"cli-dev",
160-
"run-tests"
161-
]
142+
"pages": ["cli-dev", "run-tests"]
162143
},
163144
{
164145
"group": "Deployment",
@@ -168,9 +149,7 @@
168149
"github-actions",
169150
{
170151
"group": "Deployment integrations",
171-
"pages": [
172-
"vercel-integration"
173-
]
152+
"pages": ["vercel-integration"]
174153
}
175154
]
176155
},
@@ -182,13 +161,7 @@
182161
"errors-retrying",
183162
{
184163
"group": "Wait",
185-
"pages": [
186-
"wait",
187-
"wait-for",
188-
"wait-until",
189-
"wait-for-event",
190-
"wait-for-request"
191-
]
164+
"pages": ["wait", "wait-for", "wait-until", "wait-for-event", "wait-for-request"]
192165
},
193166
"queue-concurrency",
194167
"versioning",
@@ -204,10 +177,7 @@
204177
},
205178
{
206179
"group": "Frontend usage",
207-
"pages": [
208-
"frontend/overview",
209-
"frontend/react-hooks"
210-
]
180+
"pages": ["frontend/overview", "frontend/react-hooks"]
211181
},
212182
{
213183
"group": "Realtime API",
@@ -225,10 +195,7 @@
225195
"management/overview",
226196
{
227197
"group": "Tasks API",
228-
"pages": [
229-
"management/tasks/trigger",
230-
"management/tasks/batch-trigger"
231-
]
198+
"pages": ["management/tasks/trigger", "management/tasks/batch-trigger"]
232199
},
233200
{
234201
"group": "Runs API",
@@ -267,9 +234,7 @@
267234
},
268235
{
269236
"group": "Projects API",
270-
"pages": [
271-
"management/projects/runs"
272-
]
237+
"pages": ["management/projects/runs"]
273238
}
274239
]
275240
},
@@ -315,17 +280,11 @@
315280
},
316281
{
317282
"group": "Help",
318-
"pages": [
319-
"community",
320-
"help-slack",
321-
"help-email"
322-
]
283+
"pages": ["community", "help-slack", "help-email"]
323284
},
324285
{
325286
"group": "",
326-
"pages": [
327-
"guides/introduction"
328-
]
287+
"pages": ["guides/introduction"]
329288
},
330289
{
331290
"group": "Frameworks",
@@ -369,6 +328,7 @@
369328
"pages": [
370329
"guides/examples/dall-e3-generate-image",
371330
"guides/examples/deepgram-transcribe-audio",
331+
"guides/examples/fal-ai-image-to-cartoon",
372332
"guides/examples/ffmpeg-video-processing",
373333
"guides/examples/firecrawl-url-crawl",
374334
"guides/examples/open-ai-with-retrying",
@@ -386,20 +346,16 @@
386346
},
387347
{
388348
"group": "Dashboard",
389-
"pages": [
390-
"guides/dashboard/creating-a-project"
391-
]
349+
"pages": ["guides/dashboard/creating-a-project"]
392350
},
393351
{
394352
"group": "Migrations",
395-
"pages": [
396-
"guides/use-cases/upgrading-from-v2"
397-
]
353+
"pages": ["guides/use-cases/upgrading-from-v2"]
398354
}
399355
],
400356
"footerSocials": {
401357
"twitter": "https://twitter.com/triggerdotdev",
402358
"github": "https://github.com/triggerdotdev",
403359
"linkedin": "https://www.linkedin.com/company/triggerdotdev"
404360
}
405-
}
361+
}

0 commit comments

Comments
 (0)