Output Paths
Overview
Output path templates control the directory structure and file naming for transcoded outputs. Instead of manually specifying full paths for every output, you define templates with variables like {job_id} and {resolution} that are resolved automatically at job creation time.
Transcodely uses a 4-level template hierarchy that lets you set sensible defaults at the origin level and override them per-job or per-output as needed.
Template Variables
Use these variables in any path template. They are resolved at job creation time:
| Variable | Description | Example Value |
|---|---|---|
{job_id} | Job identifier | job_abc123def456 |
{video_id} | Your source video identifier (falls back to {job_id}) | my-video-123 |
{output_id} | Output identifier (unique per job) | out_xyz789 |
{preset_id} | Preset identifier | pst_x9y8z7w6v5 |
{date} | Date in YYYY-MM-DD format | 2026-02-28 |
{timestamp} | ISO timestamp (file-safe) | 2026-02-28T15-04-05Z |
{codec} | Video codec | h264, h265, vp9, av1 |
{resolution} | Resolution preset | 1080p, 720p, 480p |
{bitrate} | Video bitrate | 5000k |
{framerate} | Output framerate | 30, 60 |
{format} | Output container format | mp4, hls, dash |
{type} | Alias for {format} | mp4, hls, dash |
{quality} | Quality tier | economy, standard, premium |
{output_index} | 0-based output index | 0, 1, 2 |
{uuid} | Random UUID | 550e8400-e29b-41d4-a716-446655440000 |
Segment and thumbnail templates support additional context-specific variables: {segment_index}, {segment_number}, {segment_time} for streaming segments, and {thumb_index}, {thumb_time}, {thumb_time_ms} for thumbnails.
Template Hierarchy
The effective template for each output is resolved from up to four sources. The job-level output_path_template and the per-output path_template compose additively rather than overriding one another; the origin template and system default act as fallbacks when neither is set:
| Case | Effective template |
|---|---|
Both job-level output_path_template and per-output path_template set | <output_path_template>/<path_template> (composed) |
Only per-output path_template set | The per-output template |
Only job-level output_path_template set | The job-level template |
Neither set, origin has a path_template | The origin’s path_template |
| None of the above | System default {job_id}/{output_id} |
When both templates are set, the per-output path_template does not replace the job-level one — the job-level template becomes a prefix. For example, a job-level output_path_template of videos/{job_id} combined with a per-output path_template of {codec}-{resolution} resolves to:
videos/job_abc/h264-1080p.mp4Setting Templates at Each Level
Per-output template (the most specific level; composes onto any job-level template):
{
"outputs": [
{
"type": "mp4",
"video": [{ "codec": "h264", "resolution": "1080p", "quality": "standard" }],
"path_template": "featured/{job_id}/main"
}
]
}Job-level template (a job-wide prefix applied to every output; outputs without their own path_template use it alone, outputs with one compose onto it):
{
"output_path_template": "{date}/{job_id}/{codec}_{resolution}",
"outputs": [
{
"type": "mp4",
"video": [{ "codec": "h264", "resolution": "1080p", "quality": "standard" }]
},
{
"type": "mp4",
"video": [{ "codec": "h264", "resolution": "720p", "quality": "standard" }]
}
]
}This produces paths like:
2026-02-28/job_abc123/h264_1080p.mp4
2026-02-28/job_abc123/h264_720p.mp4Origin template (set when creating the origin):
curl -X POST https://api.transcodely.com/transcodely.v1.OriginService/Create
-H "Content-Type: application/json"
-H "Authorization: Bearer {{API_KEY}}"
-H "X-Organization-ID: {{ORG_ID}}"
-d '{
"name": "CDN Output Bucket",
"permissions": ["write"],
"path_template": "{date}/{job_id}/{resolution}",
"gcs": {
"bucket": "my-cdn-bucket",
"credentials": {
"service_account_json": "<sa-key contents>"
}
}
}'const origin = await client.origins.create({
name: "CDN Output Bucket",
permissions: [OriginPermission.WRITE],
pathTemplate: "{date}/{job_id}/{resolution}",
gcs: {
bucket: "my-cdn-bucket",
credentials: {
serviceAccountJson: "<sa-key contents>",
},
},
});origin = client.origins.create(
name="CDN Output Bucket",
permissions=["write"],
path_template="{date}/{job_id}/{resolution}",
gcs={
"bucket": "my-cdn-bucket",
"credentials": {
"service_account_json": "<sa-key contents>",
},
},
)origin, err := client.Origins.Create(ctx, &transcodely.OriginCreateParams{
Name: "CDN Output Bucket",
Permissions: []transcodely.OriginPermission{transcodely.OriginPermissionWrite},
PathTemplate: "{date}/{job_id}/{resolution}",
Gcs: &transcodely.GcsOriginConfig{
Bucket: "my-cdn-bucket",
Credentials: &transcodely.GcsCredentials{
ServiceAccountJson: "<sa-key contents>",
},
},
})All jobs using this origin will inherit the template unless they specify their own.
Path Computation
The final file path depends on whether the output is a regular file or a streaming package.
Regular Outputs (MP4, WebM, MKV, MOV)
The resolved template gets the file extension appended:
{resolved_template}.{extension}Example: Template {job_id}/{codec}_{resolution} with H.264 at 1080p in MP4:
job_abc123/h264_1080p.mp4Streaming Outputs (HLS, DASH, Adaptive)
Streaming outputs add the format directory and manifest filename:
{resolved_template}/{format}/{manifest}.{extension}Example: Template {job_id}/{codec}_{resolution} with HLS:
job_abc123/h264_1080p/hls/master.m3u8Example: Template {date}/{job_id} with DASH:
2026-02-28/job_abc123/dash/manifest.mpdAn output with type: "adaptive" resolves the same base path, then writes both manifests under it — an hls/ playlist and a dash/ manifest from shared CMAF segments.
Example: Template {date}/{job_id} with type: "adaptive":
2026-02-28/job_abc123/hls/master.m3u8
2026-02-28/job_abc123/dash/manifest.mpdCollision Detection
When multiple outputs in a job resolve to the same path, Transcodely detects the collision. The behavior depends on whether the template was explicitly set by you or implicitly inherited:
| Template Source | Collision Behavior |
|---|---|
| Per-output template (explicit) | Validation error — you must fix the template |
| Job-level template (explicit) | Validation error — you must fix the template |
| Origin template (implicit) | Auto-fix: /{output_id} is appended |
| System default (implicit) | Auto-fix: /{output_id} is appended |
Auto-Fix Example
If your origin template is {date}/{job_id}/{resolution} and you create two outputs at the same resolution:
{
"outputs": [
{
"type": "hls",
"video": [{ "codec": "h264", "resolution": "1080p", "quality": "standard" }]
},
{
"type": "hls",
"video": [{ "codec": "h265", "resolution": "1080p", "quality": "standard" }]
}
]
}Without auto-fix, both outputs would resolve to 2026-02-28/job_abc123/1080p/hls/master.m3u8. The API detects this and appends /{output_id} to each path:
2026-02-28/job_abc123/1080p/out_001/hls/master.m3u8
2026-02-28/job_abc123/1080p/out_002/hls/master.m3u8Fixing Explicit Collisions
If you set a job-level or output-level template that causes collisions, you must resolve it yourself. Add a distinguishing variable:
{
"output_path_template": "{job_id}/{codec}_{resolution}",
"outputs": [
{
"type": "mp4",
"video": [{ "codec": "h264", "resolution": "1080p", "quality": "standard" }]
},
{
"type": "mp4",
"video": [{ "codec": "h264", "resolution": "1080p", "quality": "premium" }]
}
]
}This would fail because both resolve to job_abc123/h264_1080p.mp4. Fix it by adding {quality}:
{
"output_path_template": "{job_id}/{codec}_{resolution}_{quality}"
}Now the paths are unique:
job_abc123/h264_1080p_standard.mp4
job_abc123/h264_1080p_premium.mp4Custom Manifest Names
For HLS and DASH outputs, you can customize the manifest filename:
{
"type": "hls",
"video": [
{ "codec": "h264", "resolution": "1080p", "quality": "standard" }
],
"hls": {
"manifest": "index",
"variant_pattern": "video_{resolution}"
}
}This produces index.m3u8 instead of the default master.m3u8, and variant playlists named video_1080p.m3u8 instead of h264_1080p.m3u8.
For DASH:
{
"type": "dash",
"dash": {
"manifest": "stream"
}
}This produces stream.mpd instead of manifest.mpd.
Base Path
Origins also have a base_path field that prefixes all paths. This is applied before the template:
{origin.base_path}/{resolved_template}.{extension}Example: Origin with base_path: "videos/" and template {job_id}/{resolution}:
videos/job_abc123/1080p.mp4Use base_path to keep Transcodely outputs in a specific directory within your bucket.
Best Practices
| Practice | Example |
|---|---|
Always include {job_id} | Ensures outputs from different jobs never collide |
Use {date} for time-based organization | {date}/{job_id}/... groups by day |
Add {codec} for multi-codec outputs | {job_id}/{codec}_{resolution} distinguishes H.264 from AV1 |
| Set origin template as your default | Avoids repeating templates in every job request |
| Use per-output templates sparingly | Only when a specific output needs a different path |
Include {quality} if mixing tiers | Prevents collisions when same codec+resolution at different qualities |