Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions internal/api/api.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 42 additions & 1 deletion internal/validate/job_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package validate

import "testing"
import (
"encoding/json"
"strings"
"testing"
)

func TestJobPayloadRules(t *testing.T) {
valid := []byte(`{"template":{"id":"tpl","composition":"Main"},"settings":{"type":"video","codec":"video_h264_vbr_15mbps"}}`)
Expand Down Expand Up @@ -46,3 +50,40 @@ func TestJobPayloadTemplateSource(t *testing.T) {
}
}
}

func TestJobPayloadKeepsMultiFrame(t *testing.T) {
for _, tc := range []struct {
name string
payload string
want string
}{
{"off", `{"template":{"id":"tpl","composition":"Main"},"settings":{"multiFrame":false}}`, `"multiFrame":false`},
{"on", `{"template":{"id":"tpl","composition":"Main"},"settings":{"multiFrame":true}}`, `"multiFrame":true`},
} {
t.Run(tc.name, func(t *testing.T) {
payload, err := JobPayload([]byte(tc.payload))
if err != nil {
t.Fatalf("payload failed: %v", err)
}
encoded, err := json.Marshal(payload)
if err != nil {
t.Fatalf("marshal payload: %v", err)
}
if !strings.Contains(string(encoded), tc.want) {
t.Fatalf("submitted payload %s does not contain %s", encoded, tc.want)
}
})
}

omitted, err := JobPayload([]byte(`{"template":{"id":"tpl","composition":"Main"},"settings":{"type":"video"}}`))
if err != nil {
t.Fatalf("payload failed: %v", err)
}
encoded, err := json.Marshal(omitted)
if err != nil {
t.Fatalf("marshal payload: %v", err)
}
if strings.Contains(string(encoded), "multiFrame") {
t.Fatalf("submitted payload %s should leave multiFrame out when it is not set", encoded)
}
}
22 changes: 18 additions & 4 deletions openapi/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"properties": {
"src": {
"type": "string",
"description": "Source URL, script data or file path for the asset (supports HTTP/HTTPS URLs or local paths)"
"description": "Public HTTP(S), native s3:/gs:, inline data:, or a file: URL inside the current job work directory. The worker rejects local paths and symlinks escaping that directory. Other schemes and non-public network destinations are rejected."
},
"type": {
"type": "string",
Expand Down Expand Up @@ -178,6 +178,10 @@
"enum": ["ae2025", "ae2026"],
"default": "ae2026",
"description": "After Effects render engine version for the child job"
},
"multiFrame": {
"type": "boolean",
"description": "Turn After Effects Multi-Frame Rendering on (true) or off (false) for the child job. If omitted, the worker's own setting applies"
}
}
}
Expand Down Expand Up @@ -263,6 +267,10 @@
"enum": ["ae2025", "ae2026"],
"default": "ae2026",
"description": "After Effects render engine version for the child job"
},
"multiFrame": {
"type": "boolean",
"description": "Turn After Effects Multi-Frame Rendering on (true) or off (false) for the child job. If omitted, the worker's own setting applies"
}
}
}
Expand All @@ -289,7 +297,7 @@
},
"assets": {
"type": "array",
"description": "Ordered list of video or job assets to stitch together",
"description": "Ordered list of video or job assets to stitch together. A join needs at least two inputs.",
"items": {
"oneOf": [
{ "$ref": "#/components/schemas/JoinVideoAsset" },
Expand All @@ -303,7 +311,7 @@
}
}
},
"minItems": 1
"minItems": 2
},
"upload": {
"type": "object",
Expand Down Expand Up @@ -528,6 +536,10 @@
"enum": ["ae2025", "ae2026"],
"default": "ae2026",
"description": "After Effects render engine version used when the job is picked up by a worker"
},
"multiFrame": {
"type": "boolean",
"description": "Turn After Effects Multi-Frame Rendering on (true) or off (false) for this job. If omitted, the worker's own setting applies"
}
},
"additionalProperties": false
Expand Down Expand Up @@ -557,7 +569,7 @@
"endpoint": {
"type": "string",
"default": "https://s3.amazonaws.com",
"description": "Custom S3-compatible endpoint URL"
"description": "Public HTTP(S) S3-compatible endpoint URL. Explicit customer credentials are required; worker credentials are not used for arbitrary endpoints."
},
"region": {
"type": "string",
Expand Down Expand Up @@ -714,6 +726,7 @@
},
"displayName": {
"type": "string",
"maxLength": 255,
"description": "Human-readable name for the template shown in UI and listings"
},
"src": {
Expand All @@ -732,6 +745,7 @@
"properties": {
"displayName": {
"type": "string",
"maxLength": 255,
"description": "Updated human-readable name for the template"
}
}
Expand Down
1 change: 1 addition & 0 deletions skills/nexrender/references/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- Layer names are case-sensitive. Use the `name` returned by `template layers` as `layerName`.
- Codecs can be given by their short name (`h264_vbr_15mbps`, `prores_422`, `png`, `gif`) or in full (`video_h264_vbr_15mbps`, `image_png`). The API rejects unknown codecs and lists the supported ones.
- `preview: true` and `settings` are mutually exclusive. Preview mode ignores normal output settings.
- `settings.multiFrame` turns After Effects Multi-Frame Rendering on (`true`) or off (`false`) for one job. Leave it out to keep the render node's default. Set `false` when a template renders incorrectly with Multi-Frame Rendering.
- `${secrets.NAME}` is the secret reference form.
- `missingFonts` is a visual-correctness warning. A render may finish with fallback fonts and still be wrong.

Expand Down
Loading