Search Documentation
Search across all documentation pages
Output Paths

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:

VariableDescriptionExample Value
{job_id}Job identifierjob_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 identifierpst_x9y8z7w6v5
{date}Date in YYYY-MM-DD format2026-02-28
{timestamp}ISO timestamp (file-safe)2026-02-28T15-04-05Z
{codec}Video codech264, h265, vp9, av1
{resolution}Resolution preset1080p, 720p, 480p
{bitrate}Video bitrate5000k
{framerate}Output framerate30, 60
{format}Output container formatmp4, hls, dash
{type}Alias for {format}mp4, hls, dash
{quality}Quality tiereconomy, standard, premium
{output_index}0-based output index0, 1, 2
{uuid}Random UUID550e8400-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:

CaseEffective template
Both job-level output_path_template and per-output path_template set<output_path_template>/<path_template> (composed)
Only per-output path_template setThe per-output template
Only job-level output_path_template setThe job-level template
Neither set, origin has a path_templateThe origin’s path_template
None of the aboveSystem 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.mp4

Setting 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.mp4

Origin 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.mp4

Streaming 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.m3u8

Example: Template {date}/{job_id} with DASH:

2026-02-28/job_abc123/dash/manifest.mpd

An 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.mpd

Collision 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 SourceCollision 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.m3u8

Fixing 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.mp4

Custom 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.mp4

Use base_path to keep Transcodely outputs in a specific directory within your bucket.


Best Practices

PracticeExample
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 defaultAvoids repeating templates in every job request
Use per-output templates sparinglyOnly when a specific output needs a different path
Include {quality} if mixing tiersPrevents collisions when same codec+resolution at different qualities