Concat / Merge Files
The concat recipe merges two or more media files into a single output using FFmpeg’s concat demuxer with stream copy (-c copy). This is fast because it doesn’t re-encode — it just joins the files end to end.
Basic usage
Section titled “Basic usage”Merge two MP3 files:
curl -X POST https://api.xora.sh/v1/jobs \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "mode": "recipe", "input_files": { "in_1": "https://example.com/part1.mp3", "in_2": "https://example.com/part2.mp3" }, "output": { "format": "mp3" }, "recipe": { "name": "concat" } }'const response = await fetch('https://api.xora.sh/v1/jobs', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ mode: 'recipe', input_files: { in_1: 'https://example.com/part1.mp3', in_2: 'https://example.com/part2.mp3' }, output: { format: 'mp3' }, recipe: { name: 'concat' } })});const data = await response.json();console.log(data);import requests
response = requests.post( "https://api.xora.sh/v1/jobs", headers={ "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, json={ "mode": "recipe", "input_files": { "in_1": "https://example.com/part1.mp3", "in_2": "https://example.com/part2.mp3" }, "output": { "format": "mp3" }, "recipe": { "name": "concat" } })data = response.json()print(data)Response
Section titled “Response”{ "jobId": "01JXYZ1234ABCDEF56789000", "state": "queued"}Parameters
Section titled “Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Must be "concat" |
Important: input_files, not input
Section titled “Important: input_files, not input”The concat recipe uses input_files instead of input. This is the only recipe that works this way:
| Key | Pattern | Example |
|---|---|---|
in_1 | First file | "https://example.com/part1.mp4" |
in_2 | Second file | "https://example.com/part2.mp4" |
in_3 | Third file (optional) | "https://example.com/part3.mp4" |
| … | More files | As many as needed |
Keys must follow the pattern in_ followed by letters, numbers, or underscores. You need at least two entries.
Examples
Section titled “Examples”Merge video segments
Section titled “Merge video segments”Join two MP4 clips:
{ "mode": "recipe", "input_files": { "in_1": "https://example.com/intro.mp4", "in_2": "https://example.com/main.mp4" }, "output": { "format": "mp4" }, "recipe": { "name": "concat" }}Merge three audio files
Section titled “Merge three audio files”{ "mode": "recipe", "input_files": { "in_1": "https://example.com/chapter1.mp3", "in_2": "https://example.com/chapter2.mp3", "in_3": "https://example.com/chapter3.mp3" }, "output": { "format": "mp3" }, "recipe": { "name": "concat" }}Merge many files
Section titled “Merge many files”You can merge as many files as needed:
{ "mode": "recipe", "input_files": { "in_part_a": "https://example.com/a.mp4", "in_part_b": "https://example.com/b.mp4", "in_part_c": "https://example.com/c.mp4", "in_part_d": "https://example.com/d.mp4", "in_part_e": "https://example.com/e.mp4" }, "output": { "format": "mp4" }, "recipe": { "name": "concat" }}Supported output formats
Section titled “Supported output formats”| Format | Type |
|---|---|
mp4 | Video |
webm | Video |
mov | Video |
mp3 | Audio |
aac | Audio |
wav | Audio |
How it works
Section titled “How it works”The concat recipe uses FFmpeg’s concat demuxer with stream copy (-c copy). This means:
- No re-encoding — files are joined as-is, preserving original quality
- Very fast — processing time is minimal regardless of file size
- Inputs must be compatible — same codec, sample rate, and format
Troubleshooting
Section titled “Troubleshooting”| Problem | Cause | Fix |
|---|---|---|
| ”codec mismatch” error | Input files use different codecs | Transcode all inputs to the same format first |
| Audio out of sync | Different sample rates | Ensure all audio tracks use the same sample rate |
Only 1 input_files entry | Need at least 2 | Add a second file |
Used input instead of input_files | Wrong field | Remove input, use input_files with in_1, in_2, etc. |