Skip to content

Commit 382ce8d

Browse files
D-K-Psamejr
andauthored
Added overview pages for guides and examples, and improved examples (#1314)
* Added introduction page for guides * New intro page for examples * Fixed links * Updated examples intro to include all of the new ones * Improved FFmpeg example * Improved the react pdf example * Added Supabase overview page * Updated card-supabase snippet * Added sharp payload instructions * Added vercel payload instructions * Added dall-e payload instructions * Added openai payload instructions * Added resend payload instructions * Made the prompts more consistent * Minor tweaks and moved bun * Updated links and added bun logo --------- Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
1 parent 3d53d4c commit 382ce8d

17 files changed

+514
-73
lines changed

docs/examples/dall-e3-generate-image.mdx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ export const generateContent = task({
2929
maxAttempts: 3, // Retry up to 3 times
3030
},
3131
run: async ({ theme, description }: Payload) => {
32-
3332
// Generate text
3433
const textResult = await openai.chat.completions.create({
3534
model: "gpt-4o",
@@ -64,4 +63,15 @@ function generateTextPrompt(theme: string, description: string): any {
6463
function generateImagePrompt(theme: string, description: string): any {
6564
return `Theme: ${theme}\n\nDescription: ${description}`;
6665
}
67-
```
66+
```
67+
68+
## Testing your task
69+
70+
To test this task in the dashboard, you can use the following payload:
71+
72+
```json
73+
{
74+
"theme": "A beautiful sunset",
75+
"description": "A sunset over the ocean with a tiny yacht in the distance."
76+
}
77+
```

docs/examples/ffmpeg-video-processing.mdx

Lines changed: 73 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,13 @@ export const ffmpegCompressVideo = task({
9898

9999
// Read the compressed video
100100
const compressedVideo = await fs.readFile(outputPath);
101-
102101
const compressedSize = compressedVideo.length;
103102

104103
// Log compression results
105104
logger.log(`Compressed video size: ${compressedSize} bytes`);
106-
logger.log(`Compressed video saved at: ${outputPath}`);
105+
logger.log(`Temporary compressed video file created`, { outputPath });
107106

108-
// Upload the compressed video to S3, replacing slashes with underscores
107+
// Create the r2Key for the extracted audio, using the base name of the output path
109108
const r2Key = `processed-videos/${path.basename(outputPath)}`;
110109

111110
const uploadParams = {
@@ -116,22 +115,31 @@ export const ffmpegCompressVideo = task({
116115

117116
// Upload the video to R2 and get the URL
118117
await s3Client.send(new PutObjectCommand(uploadParams));
119-
const r2Url = `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com/${process.env.R2_BUCKET}/${r2Key}`;
120-
logger.log("Compressed video uploaded to R2", { url: r2Url });
118+
logger.log(`Compressed video saved to your r2 bucket`, { r2Key });
121119

122120
// Delete the temporary compressed video file
123121
await fs.unlink(outputPath);
122+
logger.log(`Temporary compressed video file deleted`, { outputPath });
124123

125-
// Return the compressed video file path, compressed size, and S3 URL
124+
// Return the compressed video buffer and r2 key
126125
return {
127-
compressedVideoPath: outputPath,
128-
compressedSize,
129-
r2Url,
126+
Bucket: process.env.R2_BUCKET,
127+
r2Key,
130128
};
131129
},
132130
});
133131
```
134132

133+
### Testing:
134+
135+
To test this task, use this payload structure:
136+
137+
```json
138+
{
139+
"videoUrl": "<video-url>"
140+
}
141+
```
142+
135143
## Extract audio from a video using FFmpeg
136144

137145
This task demonstrates how to use FFmpeg to extract audio from a video, convert it to WAV format, and upload it to R2 storage.
@@ -145,11 +153,6 @@ This task demonstrates how to use FFmpeg to extract audio from a video, convert
145153

146154
### Task code
147155

148-
<Warning>
149-
When testing, make sure to provide a video URL that contains audio. If the video does not have
150-
audio, the task will fail.
151-
</Warning>
152-
153156
```ts trigger/ffmpeg-extract-audio.ts
154157
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
155158
import { logger, task } from "@trigger.dev/sdk/v3";
@@ -176,63 +179,81 @@ export const ffmpegExtractAudio = task({
176179
run: async (payload: { videoUrl: string }) => {
177180
const { videoUrl } = payload;
178181

179-
// Generate temporary and output file names
182+
// Generate temporary file names
180183
const tempDirectory = os.tmpdir();
181-
const outputPath = path.join(tempDirectory, `output_${Date.now()}.wav`);
184+
const outputPath = path.join(tempDirectory, `audio_${Date.now()}.wav`);
182185

183186
// Fetch the video
184187
const response = await fetch(videoUrl);
185188

186-
// Convert the video to WAV
189+
// Extract the audio
187190
await new Promise((resolve, reject) => {
188191
if (!response.body) {
189192
return reject(new Error("Failed to fetch video"));
190193
}
194+
191195
ffmpeg(Readable.from(response.body))
192-
.toFormat("wav")
193-
.save(outputPath)
194-
.on("end", () => {
195-
logger.log(`WAV file saved to ${outputPath}`);
196-
resolve(outputPath);
197-
})
198-
.on("error", (err) => {
199-
reject(err);
200-
});
196+
.outputOptions([
197+
"-vn", // Disable video output
198+
"-acodec pcm_s16le", // Use PCM 16-bit little-endian encoding
199+
"-ar 44100", // Set audio sample rate to 44.1 kHz
200+
"-ac 2", // Set audio channels to stereo
201+
])
202+
.output(outputPath)
203+
.on("end", resolve)
204+
.on("error", reject)
205+
.run();
201206
});
202207

203-
// Read the WAV file
204-
const wavBuffer = await fs.readFile(outputPath);
208+
// Read the extracted audio
209+
const audioBuffer = await fs.readFile(outputPath);
210+
const audioSize = audioBuffer.length;
205211

206-
// Log the output file path
207-
logger.log(`Converted video saved at: ${outputPath}`);
212+
// Log audio extraction results
213+
logger.log(`Extracted audio size: ${audioSize} bytes`);
214+
logger.log(`Temporary audio file created`, { outputPath });
208215

209-
// Upload the compressed video to S3, replacing slashes with underscores
210-
const r2Key = `processed-audio/${path.basename(outputPath)}`;
216+
// Create the r2Key for the extracted audio, using the base name of the output path
217+
const r2Key = `extracted-audio/${path.basename(outputPath)}`;
211218

212219
const uploadParams = {
213220
Bucket: process.env.R2_BUCKET,
214221
Key: r2Key,
215-
Body: wavBuffer,
222+
Body: audioBuffer,
216223
};
217224

218225
// Upload the audio to R2 and get the URL
219226
await s3Client.send(new PutObjectCommand(uploadParams));
220-
const r2Url = `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com/${process.env.R2_BUCKET}/${r2Key}`;
221-
logger.log("Extracted audio uploaded to R2", { url: r2Url });
227+
logger.log(`Extracted audio saved to your R2 bucket`, { r2Key });
222228

223-
// Delete the temporary file
229+
// Delete the temporary audio file
224230
await fs.unlink(outputPath);
231+
logger.log(`Temporary audio file deleted`, { outputPath });
225232

226-
// Return the WAV buffer and file path
233+
// Return the audio file path, size, and R2 URL
227234
return {
228-
wavBuffer,
229-
wavFilePath: outputPath,
230-
r2Url,
235+
Bucket: process.env.R2_BUCKET,
236+
r2Key,
231237
};
232238
},
233239
});
234240
```
235241

242+
### Testing:
243+
244+
To test this task, use this payload structure:
245+
246+
<Warning>
247+
Make sure to provide a video URL that contains audio. If the video does not have audio, the task
248+
will fail.
249+
</Warning>
250+
251+
```json
252+
{
253+
"videoUrl": "<video-url>"
254+
}
255+
```
256+
236257
## Generate a thumbnail from a video using FFmpeg
237258

238259
This task demonstrates how to use FFmpeg to generate a thumbnail from a video at a specific time and upload the generated thumbnail to R2 storage.
@@ -298,7 +319,7 @@ export const ffmpegGenerateThumbnail = task({
298319
// Read the generated thumbnail
299320
const thumbnail = await fs.readFile(outputPath);
300321

301-
// Upload the compressed video to S3, replacing slashes with underscores
322+
// Create the r2Key for the extracted audio, using the base name of the output path
302323
const r2Key = `thumbnails/${path.basename(outputPath)}`;
303324

304325
const uploadParams = {
@@ -318,7 +339,7 @@ export const ffmpegGenerateThumbnail = task({
318339
// Log thumbnail generation results
319340
logger.log(`Thumbnail uploaded to S3: ${r2Url}`);
320341

321-
// Return the thumbnail buffer, file path, sizes, and S3 URL
342+
// Return the thumbnail buffer, path, and R2 URL
322343
return {
323344
thumbnailBuffer: thumbnail,
324345
thumbnailPath: outputPath,
@@ -327,3 +348,13 @@ export const ffmpegGenerateThumbnail = task({
327348
},
328349
});
329350
```
351+
352+
## Testing your task
353+
354+
To test this task in the dashboard, you can use the following payload:
355+
356+
```json
357+
{
358+
"videoUrl": "<video-url>"
359+
}
360+
```

docs/examples/intro.mdx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
title: "Introduction"
3+
sidebarTitle: "Introduction"
4+
description: "Learn how to use Trigger.dev with these practical task examples."
5+
---
6+
7+
| Example task | Description |
8+
| :------------------------------------------------------------ | :-------------------------------------------------------------------------- |
9+
| [DALL·E 3 image generation](/examples/dall-e3-generate-image) | Use OpenAI's GPT-4o and DALL·E 3 to generate an image and text. |
10+
| [FFmpeg video processing](/examples/ffmpeg-video-processing) | Use FFmpeg to process a video in various ways and save it to Cloudflare R2. |
11+
| [OpenAI with retrying](/examples/open-ai-with-retrying) | Create a reusable OpenAI task with custom retry options. |
12+
| [React to PDF](/examples/react-pdf) | Use `react-pdf` to generate a PDF and save it to Cloudflare R2. |
13+
| [Resend email sequence](/examples/resend-email-sequence) | Send a sequence of emails over several days using Resend with Trigger.dev. |
14+
| [Sharp image processing](/examples/sharp-image-processing) | Use Sharp to process an image and save it to Cloudflare R2. |
15+
| [Vercel AI SDK](/examples/vercel-ai-sdk) | Use Vercel AI SDK to generate text using OpenAI. |

docs/examples/open-ai-with-retrying.mdx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,14 @@ export const openaiTask = task({
4343
return chatCompletion.choices[0].message.content;
4444
},
4545
});
46+
```
4647

47-
```
48+
## Testing your task
49+
50+
To test this task in the dashboard, you can use the following payload:
51+
52+
```json
53+
{
54+
"prompt": "What is the meaning of life?"
55+
}
56+
```

docs/examples/react-pdf.mdx

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@ This example demonstrates how to use Trigger.dev to generate a PDF using `react-
1010

1111
## Task code
1212

13-
```ts trigger/generateResumePDF.ts
13+
<Info> This example must be a .tsx file to use React components. </Info>
14+
15+
```ts trigger/generateResumePDF.tsx
1416
import { logger, task } from "@trigger.dev/sdk/v3";
15-
import { Document, Page, Text, View } from "@react-pdf/renderer";
16-
import { renderToBuffer } from "@react-pdf/renderer";
17+
import { renderToBuffer, Document, Page, Text, View } from "@react-pdf/renderer";
1718
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
1819

19-
// Initialize S3 client
20-
const s3Client = new S3Client({
20+
// Initialize R2 client
21+
const r2Client = new S3Client({
22+
// How to authenticate to R2: https://developers.cloudflare.com/r2/api/s3/tokens/
2123
region: "auto",
22-
endpoint: process.env.S3_ENDPOINT,
24+
endpoint: process.env.R2_ENDPOINT,
2325
credentials: {
2426
accessKeyId: process.env.R2_ACCESS_KEY_ID ?? "",
2527
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY ?? "",
@@ -29,6 +31,7 @@ const s3Client = new S3Client({
2931
export const generateResumePDF = task({
3032
id: "generate-resume-pdf",
3133
run: async (payload: { text: string }) => {
34+
// Log the payload
3235
logger.log("Generating PDF resume", payload);
3336

3437
// Render the ResumeDocument component to a PDF buffer
@@ -42,28 +45,41 @@ export const generateResumePDF = task({
4245
</Document>
4346
);
4447

45-
// Generate a unique filename
46-
const filename = `${payload.text
47-
.replace(/\s+/g, "-")
48-
.toLowerCase()}-${Date.now()}.pdf`;
48+
// Generate a unique filename based on the text and current timestamp
49+
const filename = `${payload.text.replace(/\s+/g, "-").toLowerCase()}-${Date.now()}.pdf`;
50+
51+
// Set the R2 key for the PDF file
52+
const r2Key = `resumes/${filename}`;
4953

50-
// Upload to R2
51-
const s3Key = `resumes/${filename}`;
54+
// Set the upload parameters for R2
5255
const uploadParams = {
53-
Bucket: process.env.S3_BUCKET,
54-
Key: s3Key,
56+
Bucket: process.env.R2_BUCKET,
57+
Key: r2Key,
5558
Body: pdfBuffer,
5659
ContentType: "application/pdf",
5760
};
5861

62+
// Log the upload parameters
5963
logger.log("Uploading to R2 with params", uploadParams);
6064

61-
// Upload the PDF to R2 and return the URL.
62-
await s3Client.send(new PutObjectCommand(uploadParams));
63-
const s3Url = `https://${process.env.S3_BUCKET}.s3.amazonaws.com/${s3Key}`;
64-
logger.log("PDF uploaded to R2", { url: s3Url });
65-
return { pdfUrl: s3Url };
65+
// Upload the PDF to R2
66+
await r2Client.send(new PutObjectCommand(uploadParams));
67+
68+
// Return the Bucket and R2 key for the uploaded PDF
69+
return {
70+
Bucket: process.env.R2_BUCKET,
71+
Key: r2Key,
72+
};
6673
},
6774
});
75+
```
76+
77+
## Testing your task
78+
79+
To test this task in the dashboard, you can use the following payload:
6880

69-
```
81+
```json
82+
{
83+
"text": "Hello, world!"
84+
}
85+
```

0 commit comments

Comments
 (0)