Trouble Fetching Files from /tmp Directory on During FFmpeg Process

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:

  1. Download Videos: Videos are downloaded to /tmp using custom utility functions.
  2. Process Videos: The videos are processed (e.g., padding, adding silent audio).
  3. Concatenate Videos: FFmpeg concatenates the processed videos into a single output file, saved to /tmp.
  4. 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:

  1. Is there a specific limitation or configuration on Vercel that could prevent files from being written or read in /tmp?
  2. Are there alternative approaches for handling temporary files during video processing on Vercel?
  3. Any recommended way to directly stream FFmpeg output to S3 without relying on /tmp?

Thank you in advance for your help!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.