Current Behavior:
I’m using FFmpeg on Vercel to concatenate multiple videos into one file, saving the output to the /tmp
directory. After the concatenation, I attempt to upload the output file to my Amazon S3 bucket. However, the file does not appear to exist in /tmp
when I try to fetch it for the upload.
Here’s the flow I’m using:
- Download Videos: Videos are downloaded to
/tmp
using custom utility functions. - Process Videos: The videos are processed (e.g., padding, adding silent audio).
- Concatenate Videos: FFmpeg concatenates the processed videos into a single output file, saved to
/tmp
. - Upload File: I attempt to fetch the file from
/tmp
and upload it to Amazon S3.
Problem:
The fetch call to retrieve the file from /tmp
fails, stating that the file cannot be found. This issue only occurs on Vercel. Locally, the process works as expected.
Expected Behavior:
The file created by FFmpeg in /tmp
should be accessible for further processing and uploading to Amazon S3.
Code and Configuration:
Here’s the relevant portion of my code:
API Route (/api/assemble-videos
):
export async function POST(req: Request) {
const TEMP_DIR = "/tmp";
const OUTPUT_DIR = "/tmp"; // Output directory is set to /tmp for Vercel.
try {
const { videos } = await req.json();
if (!videos || videos.length < 2) {
return new Response(JSON.stringify({ error: "At least two videos are required." }), { status: 400 });
}
// Step 1: Download videos
const downloadedPaths = await Promise.all(
videos.map((url, idx) => downloadFile(url, TEMP_DIR, `video-${idx}.mp4`))
);
// Step 2: Process videos (pad, add silent audio if necessary)
const processedPaths = await Promise.all(
downloadedPaths.map(async (file) => {
// Processing logic
return file;
})
);
// Step 3: Concatenate videos
const outputFileName = `output.mp4`;
const outputFilePath = path.join(OUTPUT_DIR, outputFileName);
await concatenateVideos(processedPaths, outputFilePath);
// Step 4: Return file path
return new Response(JSON.stringify({ path: outputFilePath }), { status: 200 });
} catch (error) {
console.error("Error assembling videos:", error);
return new Response(JSON.stringify({ error: "Failed to assemble videos." }), { status: 500 });
}
}
Client-Side Fetch Logic:
const response = await fetch("/api/assemble-videos", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ videos: videoUrls }),
});
if (!response.ok) {
console.error("API Error Response:", await response.text());
throw new Error("API Error");
}
const { path } = await response.json();
const videoResponse = await fetch(path); // Fails here, unable to find the file.
const blob = await videoResponse.blob();
const file = new File([blob], "output.mp4", { type: "video/mp4" });
Environment Details:
- Hosting Platform: Vercel
- Framework: Next.js
- Video Processing Library: FFmpeg (via
fluent-ffmpeg
) - S3 Upload Tool: AWS SDK
Request for Help:
- Is there a specific limitation or configuration on Vercel that could prevent files from being written or read in
/tmp
? - Are there alternative approaches for handling temporary files during video processing on Vercel?
- Any recommended way to directly stream FFmpeg output to S3 without relying on
/tmp
?
Thank you in advance for your help!