Skip to content

Commit 753d17f

Browse files
committed
Updated ffmpeg examples with new code and updated mint.json
1 parent 1c16506 commit 753d17f

File tree

4 files changed

+309
-220
lines changed

4 files changed

+309
-220
lines changed
Lines changed: 109 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,134 @@
11
---
22
title: "Compress a video using FFmpeg"
3-
sidebarTitle: "Compress a video with FFmpeg"
4-
description: "This example shows you how to compress a video using FFmpeg with Trigger.dev."
3+
sidebarTitle: "FFmpeg compress video"
4+
description: "This example shows you how to compress a video using FFmpeg with Trigger.dev and upload the compressed video to R2 storage."
55
---
66

77
## Overview
88

9-
This task uses FFmpeg to compress a video, reducing its file size while attempting to maintain reasonable quality.
9+
This task demonstrates how to use FFmpeg to compress a video, reducing its file size while maintaining reasonable quality, and upload the compressed video to R2 storage using Trigger.dev.
1010

1111
## Key Features:
1212

1313
- Fetches a video from a given URL
14-
- Uses the H.264 codec for video compression
15-
- Sets the Constant Rate Factor (CRF) to 28 for a good balance between quality and file size
16-
- Uses the "veryslow" preset for the best compression
17-
- Scales the video resolution to 50% of the original width and height
18-
- Uses AAC codec for audio with a bitrate of 64kbps and converts to mono
19-
- Handles temporary file management by creating and cleaning up input and output files
20-
- Returns the compressed video buffer, the file path of the compressed video, the original file size, the compressed file size, and the compression ratio
14+
- Compresses the video using FFmpeg with various compression settings
15+
- Uploads the compressed video to R2 storage
16+
- Handles temporary file management by creating and cleaning up the output file
17+
- Returns the compressed video file path, the compressed file size, and the R2 URL of the uploaded video
18+
19+
### Extension configuration
20+
21+
To use our FFmpeg extension during the build process, you need to add it to your project configuration like this:
22+
23+
```ts trigger.config.ts
24+
import { ffmpeg } from "@trigger.dev/build/extensions/core";
25+
import { defineConfig } from "@trigger.dev/sdk/v3";
26+
27+
export default defineConfig({
28+
project: "<your-project-id>",
29+
30+
...
31+
// Your other config settings...
32+
...
33+
34+
build: {
35+
extensions: [
36+
ffmpeg(),
37+
],
38+
},
39+
});
40+
```
2141

2242
## Task code
2343

2444
```ts trigger/ffmpeg-compress-video.ts
25-
import fetch from "node-fetch";
26-
import fs from "fs/promises";
27-
import path from "path";
45+
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
2846
import { logger, task } from "@trigger.dev/sdk/v3";
2947
import ffmpeg from "fluent-ffmpeg";
48+
import fs from "fs/promises";
49+
import fetch from "node-fetch";
50+
import { Readable } from "node:stream";
51+
import os from "os";
52+
import path from "path";
53+
54+
// Initialize S3 client for R2 storage
55+
const s3Client = new S3Client({
56+
region: "auto",
57+
endpoint: process.env.S3_ENDPOINT,
58+
credentials: {
59+
accessKeyId: process.env.R2_ACCESS_KEY_ID ?? "",
60+
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY ?? "",
61+
},
62+
});
3063

3164
export const ffmpegCompressVideo = task({
3265
id: "ffmpeg-compress-video",
33-
run: async (payload: { videoUrl: string }, { ctx }) => {
34-
if (ctx.environment.type !== "DEVELOPMENT") {
35-
ffmpeg.setFfmpegPath("/usr/bin/ffmpeg");
36-
ffmpeg.setFfprobePath("/usr/bin/ffprobe");
37-
}
66+
run: async (payload: { videoUrl: string }) => {
3867
const { videoUrl } = payload;
3968

40-
// Generate temporary file names
41-
const tempInputPath = path.join("/tmp", `input_${Date.now()}.mp4`);
42-
const outputPath = path.join("/tmp", `output_${Date.now()}.mp4`);
43-
44-
try {
45-
// Fetch the video
46-
const response = await fetch(videoUrl);
47-
const buffer = await response.buffer();
48-
await fs.writeFile(tempInputPath, buffer);
49-
50-
// Compress the video
51-
await new Promise((resolve, reject) => {
52-
ffmpeg(tempInputPath)
53-
.outputOptions([
54-
"-c:v libx264", // Use H.264 codec
55-
"-crf 28", // Higher CRF for more compression (28 is near the upper limit for acceptable quality)
56-
"-preset veryslow", // Slowest preset for best compression
57-
"-vf scale=iw/2:ih/2", // Reduce resolution to 320p width (height auto-calculated)
58-
"-c:a aac", // Use AAC for audio
59-
"-b:a 64k", // Reduce audio bitrate to 64k
60-
"-ac 1", // Convert to mono audio
61-
])
62-
.output(outputPath)
63-
.on("end", resolve)
64-
.on("error", reject)
65-
.run();
66-
});
67-
68-
// Read the compressed video
69-
const compressedVideo = await fs.readFile(outputPath);
70-
71-
// Get file sizes for comparison
72-
const originalSize = buffer.length;
73-
const compressedSize = compressedVideo.length;
74-
75-
// Clean up temporary files
76-
await fs.unlink(tempInputPath);
77-
78-
// Log compression results
79-
logger.log(`Original video size: ${originalSize} bytes`);
80-
logger.log(`Compressed video size: ${compressedSize} bytes`);
81-
logger.log(`Compression ratio: ${((1 - compressedSize / originalSize) * 100).toFixed(2)}%`);
82-
logger.log(`Compressed video saved at: ${outputPath}`);
83-
84-
// Return the compressed video buffer, file path, and compression stats
85-
return {
86-
compressedVideoBuffer: compressedVideo,
87-
compressedVideoPath: outputPath,
88-
originalSize,
89-
compressedSize,
90-
compressionRatio: ((1 - compressedSize / originalSize) * 100).toFixed(2),
91-
};
92-
} catch (error) {
93-
logger.error("Error compressing video:", { error });
94-
// Clean up files in case of error
95-
try {
96-
await fs.unlink(tempInputPath);
97-
await fs.unlink(outputPath);
98-
} catch (cleanupError) {
99-
logger.error("Error during cleanup:", { cleanupError });
69+
// Generate output file name with a timestamp
70+
const tempDirectory = os.tmpdir();
71+
const outputPath = path.join(tempDirectory, `output_${Date.now()}.mp4`);
72+
73+
// Fetch the video from the provided URL
74+
const response = await fetch(videoUrl);
75+
76+
// Compress the video using FFmpeg
77+
await new Promise((resolve, reject) => {
78+
if (!response.body) {
79+
return reject(new Error("Failed to fetch video"));
10080
}
101-
throw error;
102-
}
81+
82+
ffmpeg(Readable.from(response.body))
83+
.outputOptions([
84+
"-c:v libx264", // Use H.264 codec
85+
"-crf 28", // Higher CRF for more compression (28 is near the upper limit for acceptable quality)
86+
"-preset veryslow", // Slowest preset for best compression
87+
"-vf scale=iw/2:ih/2", // Reduce resolution to 50% of original width and height
88+
"-c:a aac", // Use AAC for audio
89+
"-b:a 64k", // Reduce audio bitrate to 64k
90+
"-ac 1", // Convert to mono audio
91+
])
92+
.output(outputPath)
93+
.on("end", resolve)
94+
.on("error", reject)
95+
.run();
96+
});
97+
98+
// Read the compressed video into a buffer
99+
const compressedVideo = await fs.readFile(outputPath);
100+
101+
// Get the compressed video size
102+
const compressedSize = compressedVideo.length;
103+
104+
// Log compression results for debugging purposes
105+
logger.log(`Compressed video size: ${compressedSize} bytes`);
106+
logger.log(`Compressed video saved at: ${outputPath}`);
107+
108+
// Generate the S3 key for the uploaded video file
109+
const s3Key = `processed-videos/${path.basename(outputPath)}`;
110+
111+
// Set up the parameters for uploading the video to R2
112+
const uploadParams = {
113+
Bucket: process.env.S3_BUCKET,
114+
Key: s3Key,
115+
Body: compressedVideo,
116+
};
117+
118+
// Upload the video to R2 and get the public URL
119+
await s3Client.send(new PutObjectCommand(uploadParams));
120+
const s3Url = `https://${process.env.S3_BUCKET}.s3.amazonaws.com/${s3Key}`;
121+
logger.log("Compressed video uploaded to R2", { url: s3Url });
122+
123+
// Delete the temporary compressed video file
124+
await fs.unlink(outputPath);
125+
126+
// Return the compressed video file path, compressed size, and R2 URL
127+
return {
128+
compressedVideoPath: outputPath,
129+
compressedSize,
130+
s3Url,
131+
};
103132
},
104133
});
105134
```

0 commit comments

Comments
 (0)