File Management
Unlock FFmpegâs full potential with proper file management. FFmpeg can process single files or work with multiple files using patterns (like creating videos from image sequences). Directories are essential for multi-file operations, enabling FFmpeg to reference and process collections of related files.
Why Directories Matter for FFmpeg
FFmpegâs true power lies in its ability to work with file patterns and multiple inputs. Many advanced operations require directories:
Image Sequences
Create videos from frame001.jpg, frame002.jpg, etc. using patterns like frame%03d.jpg
(Support for glob/image-sequence patterns like frame%03d.png
is coming soon.)
Batch Processing
Apply the same transformations to multiple files at once, or combine several inputs into one output
Complex Workflows
Mix audio tracks, overlay multiple videos, or process related files together in a single operation
Key insight: For single-file operations, directories are optional. For multi-file operations (sequences, batches, complex workflows), directories are essential.
Choose Your Workflow
đŹ Multi-File Processing
For image sequences, batch operations, and complex workflows
*.jpg
or frame%03d.png
(coming soon)Examples: Video from 100 images, slideshow creation, audio mixing
⥠Single-File Processing
For simple conversions and one-file operations
Examples: MP4 to GIF, resize video, extract audio
Step 1: Create a Directory
For multi-file processing or organized workflows, create a directory first:
const response = await fetch("https://api.ffmpeg-api.com/directory", {
method: "POST",
headers: {
Authorization: "Basic YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({}),
})
const { directory } = await response.json()
console.log(`Created directory: ${directory.id}`)
// Output: Created directory: dir_abc123
Response:
{
"ok": true,
"directory": {
"id": "dir_abc123",
"ttl": 86400
}
}
TTL (Time To Live): Directories auto-delete after 24 hours (86400 seconds) by default. All files inside are cleaned up automatically.
Step 2: Register Files & Get Upload URLs
With a specific directory:
const fileResponse = await fetch("https://api.ffmpeg-api.com/file", {
method: "POST",
headers: {
Authorization: "Basic YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
file_name: "video.mp4",
dir_id: "dir_abc123", // Use your directory ID
}),
})
Without a directory (auto-create):
const fileResponse = await fetch("https://api.ffmpeg-api.com/file", {
method: "POST",
headers: {
Authorization: "Basic YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
file_name: "video.mp4",
// dir_id omitted - creates temporary directory
}),
})
Response breakdown:
{
"ok": true,
"file": {
"dir_id": "dir_abc123",
"file_path": "dir_abc123/video.mp4",
"file_name": "video.mp4",
"added_on": "2024-01-01T00:00:00Z"
},
"upload": {
"url": "https://presigned-upload-url...",
"method": "PUT",
"expiresInSeconds": 300,
"headers": {
"Content-Type": "video/mp4"
}
}
}
Response Fields Explained
file.file_path
â
Use this in processing requests
upload.url
â
Upload your file bytes to this URL
upload.headers
â
Use these exact headers when uploading (if present)
upload.expiresInSeconds
â Upload URL expires in ~5 minutes
Step 3: Upload Your Files
Once you have the upload URL, send your file bytes directly to it:
// For Node.js with file system
const fs = require("fs")
const fileBuffer = fs.readFileSync("./video.mp4")
// Use the headers from the /file response (if provided)
const uploadHeaders = uploadData.headers || {}
await fetch(uploadUrl, {
method: "PUT",
body: fileBuffer,
headers: uploadHeaders,
})
console.log("â
Upload complete!")
// For browser with File input
const fileInput = document.getElementById("fileInput")
const file = fileInput.files[0]
await fetch(uploadUrl, {
method: "PUT",
body: file,
headers: uploadData.headers || {},
})
Upload URLs expire in 5 minutes. If you get a 403 error, request a new
upload URL from /file
and try again.
File Types & Limits: While any file type can be uploaded, only upload files relevant to your FFmpeg processing needs. Maximum file size is up to 5GB depending on your plan.
Important: If the /file
response includes a headers
property, use only
those headers when uploading. Do not add any additional headers beyond whatâs
provided.
Managing Your Files
List All Directories
See all your active directories:
const response = await fetch("https://api.ffmpeg-api.com/directory", {
headers: { Authorization: "Basic YOUR_API_KEY" },
})
const { directories } = await response.json()
console.log("Your directories:", directories)
Response:
{
"ok": true,
"directories": [
{
"id": "dir_abc123",
"ttl": 86400,
"added_on": "2024-01-01T10:30:00Z"
}
]
}
List Files in a Directory
See what files are stored in a specific directory:
const response = await fetch(
"https://api.ffmpeg-api.com/directory/dir_abc123",
{
headers: { Authorization: "Basic YOUR_API_KEY" },
}
)
const { files } = await response.json()
console.log("Files in directory:", files)
Response:
{
"ok": true,
"files": [
{
"file_name": "video.mp4",
"added_on": "2024-01-01T10:35:00Z"
},
{
"file_name": "audio.wav",
"added_on": "2024-01-01T10:40:00Z"
}
]
}
Get File Info (type, size)
Check the stored fileâs MIME type and size for any file youâve uploaded:
const response = await fetch(
`https://api.ffmpeg-api.com/file/dir_abc123/video.mp4`,
{ headers: { Authorization: 'Basic YOUR_API_KEY' } }
)
const { file_info } = await response.json()
console.log(file_info.file_type, file_info.file_size)
Pro Tips & Best Practices
đ Directory Organization
- ⢠One directory per project - Keep related files together
- ⢠Descriptive file names - Use clear, consistent naming
- ⢠Group by workflow - Inputs and outputs in same directory
- ⢠Clean as you go - Let TTL handle automatic cleanup
⥠Performance Tips
- ⢠Upload immediately - Donât delay after getting URL
- ⢠Reuse files - Same file, multiple processing tasks
- ⢠Batch uploads - Register multiple files at once
- ⢠Upload relevant files only - Only media files youâll process
- ⢠Check file sizes - Max 5GB per file (plan dependent)
Multi-File FFmpeg Examples
Here are real-world scenarios where directories enable powerful FFmpeg operations:
Image Sequence to Video
Create smooth video from numbered image files:
# FFmpeg pattern for files: frame001.jpg, frame002.jpg, frame003.jpg...
ffmpeg -i frame%03d.jpg -c:v libx264 -pix_fmt yuv420p output.mp4
Setup with FFmpeg API:
- Create directory and upload:
frame001.jpg
,frame002.jpg
,frame003.jpg
⌠- Process with input pattern:
{"task":{"inputs": [{"file_path": "dir_123/frame%03d.jpg"}]}}
Support for glob/image-sequence patterns like frame%03d.png
is
coming soon.
Batch Audio Processing
Apply the same transformation to multiple audio files:
# Process all WAV files in a directory
for file in *.wav; do
ffmpeg -i "$file" -c:a libmp3lame "processed_$file.mp3"
done
Setup with FFmpeg API:
- Upload multiple WAV files to same directory
- Use wildcard processing:
{"task":{"inputs": [{"file_path": "dir_123/*.wav"}]}}
Multi-Track Audio Mixing
Combine multiple audio sources:
# Mix background music with narration
ffmpeg -i music.mp3 -i narration.wav -filter_complex amix=inputs=2 final.mp3
Setup with FFmpeg API:
- Upload all audio files to same directory
- Reference multiple inputs:
{"task":{"inputs": [{"file_path": "dir_123/music.mp3"}, {"file_path": "dir_123/narration.wav"}]}}
Pro tip: Directories arenât just containersâthey enable FFmpeg to use
wildcards (*.jpg
), patterns (frame%03d.png
), and reference multiple
related files efficiently.
Support for glob/image-sequence patterns is coming soon.
Common File Management Patterns
Single File Processing
For quick, one-off conversions:
// 1. Register file (auto-creates directory)
const { file, upload } = await registerFile("input.gif")
// 2. Upload immediately
await uploadFile(upload.url, "./input.gif")
// 3. Process right away
const result = await processFile(file.file_path, "output.mp4")
Batch File Processing
For multiple related files:
// 1. Create organized directory
const { directory } = await createDirectory()
// 2. Register all files
const files = await Promise.all([
registerFile("video1.mp4", directory.id),
registerFile("video2.mp4", directory.id),
registerFile("audio.wav", directory.id),
])
// 3. Upload all files
for (const fileData of files) {
const fileBuffer = fs.readFileSync(`./${fileData.file.file_name}`)
await fetch(fileData.upload.url, {
method: "PUT",
body: fileBuffer,
})
}
// 4. Process with multiple inputs
const processResponse = await fetch(
"https://api.ffmpeg-api.com/ffmpeg/process",
{
method: "POST",
headers: {
Authorization: "Basic YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
task: {
inputs: files.map((f) => ({ file_path: f.file.file_path })),
outputs: [{ file: "combined_output.mp4" }],
},
}),
}
)
Long-term Project Management
For ongoing projects with file reuse:
// Create project directory
const projectResponse = await fetch("https://api.ffmpeg-api.com/directory", {
method: "POST",
headers: {
Authorization: "Basic YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({}),
})
const { directory } = await projectResponse.json()
console.log(`Project directory: ${directory.id}`)
// Upload source materials once (conceptual - implement upload logic for each file)
const sourceFiles = {
footage: `${directory.id}/raw-footage.mp4`,
music: `${directory.id}/background-music.mp3`,
logo: `${directory.id}/logo.png`,
}
// Process multiple variations using same source files
const webVersion = await fetch("https://api.ffmpeg-api.com/ffmpeg/process", {
method: "POST",
headers: {
Authorization: "Basic YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
task: {
inputs: [{ file_path: sourceFiles.footage }],
outputs: [
{
file: "web-version.mp4",
options: ["-vf", "scale=1280:720", "-crf", "23"],
},
],
},
}),
})
const mobileVersion = await fetch("https://api.ffmpeg-api.com/ffmpeg/process", {
method: "POST",
headers: {
Authorization: "Basic YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
task: {
inputs: [{ file_path: sourceFiles.footage }],
outputs: [
{
file: "mobile-version.mp4",
options: ["-vf", "scale=640:360", "-crf", "28"],
},
],
},
}),
})
File Upload Troubleshooting
â Upload fails with 403 Forbidden
Upload URL has expired (5-minute limit). Solutions:
- Get a fresh upload URL by calling
/file
again - Upload immediately after getting the URL
- Donât store upload URLs for later use
- Implement retry logic with new URL generation
â âFile name already existsâ error
File names must be unique within a directory. Options:
- Use different file names (add timestamps, versions, etc.)
- Create separate directories for different versions
Check existing files with
GET /directory/{id}
Use descriptive naming patterns:
project-v1-final.mp4
â Large file upload times out
For large files, optimize your approach (max file size: 5GB depending on plan):
- Compress files before uploading when possible
- Use appropriate HTTP client timeout settings
- Consider breaking large operations into smaller parts
- Monitor network stability during uploads
- Check your planâs file size limits in the dashboard
Understanding Directories: The Key to FFmpegâs Power
đ Key Takeaway
Directories arenât just for organizationâtheyâre the foundation that enables FFmpegâs most powerful features:
đŹ Multi-File Magic
- ⢠Image sequences â videos
- ⢠Batch processing workflows
- ⢠Pattern-based file selection
đ§ FFmpeg Patterns
â˘
*.jpg
wildcardsâ˘
frame%03d.png
sequences- ⢠Multiple input references
Whatâs Next?
⥠Start Processing
Learn how to transform your uploaded files with FFmpeg commands.
đ See Examples
Complete code examples for file management in different languages.
đ° Understand Pricing
Learn how file sizes and processing time affect your costs.
Need help with file organization? The patterns above work for most use cases, but every project is different. Check our Examples for more specific implementations.