Reference
Node reference
Types and typeVersions match n8n 2.47.3. API fields are the official JSON2Video and Zernio fields only — nothing is invented.
#The four workflows
#Auto Shorts – Submit Clip (Form)
| Node | Type | typeVersion | Role |
|---|---|---|---|
| Submit Clip Form | n8n-nodes-base.formTrigger |
2.3 | Path auto-shorts-submit. Fields: Clip URL (required), Topic or notes, Schedule time (optional ISO-8601 text). ignoreBots on, attribution off. |
| Config | n8n-nodes-base.set |
3.4 | Sheet ID, timezone, default visibility flags. includeOtherFields so form values pass through. |
| Normalize Form Row | n8n-nodes-base.code |
2 | Validates an http(s) URL, builds id (AS-YYYYMMDD-xxxx), status queued. |
| Append Queue Row | n8n-nodes-base.googleSheets |
4.5 | Operation append. Error output → Error Page. |
| Thank-You Page / Error Page | n8n-nodes-base.form |
2.3 | Operation completion. |
#Auto Shorts – Ingest & Render
| Node | Type | typeVersion | Role |
|---|---|---|---|
| Every 5 Minutes | n8n-nodes-base.scheduleTrigger |
1.2 | minutesInterval: 5. |
| Manual Test Run | n8n-nodes-base.manualTrigger |
1 | Safe first run. |
| Config | n8n-nodes-base.set |
3.4 | Buyer-facing defaults. |
| Read Queue | n8n-nodes-base.googleSheets |
4.5 | Operation read. |
| Select Queued or Resume | n8n-nodes-base.code |
2 | queued, or rendering with a saved project id. Caps at max_renders_per_run. |
| Resume Existing Project? | n8n-nodes-base.if |
2.2 | True → skip create (POST /movies is not idempotent). |
| Lock Row (rendering) | n8n-nodes-base.googleSheets |
4.5 | Operation update, match id. |
| Build Movie JSON | n8n-nodes-base.code |
2 | Official movie body (below). |
| Create JSON2Video Movie | n8n-nodes-base.httpRequest |
4.2 | POST https://api.json2video.com/v2/movies, Header Auth JSON2Video API. |
| Save Project ID | n8n-nodes-base.googleSheets |
4.5 | Stores json2video_project before polling. |
| Prepare Poll State | n8n-nodes-base.set |
3.4 | project from the create response (isExecuted) or the resumed row. |
| Wait 10 Seconds | n8n-nodes-base.wait |
1.1 | resume: timeInterval, amount: 10, unit: seconds. Waits under 65 s stay in-process. |
| Get Movie Status | n8n-nodes-base.httpRequest |
4.2 | GET /v2/movies?project=…&format=simple. |
| Note Poll Result | n8n-nodes-base.code |
2 | Official statuses pending, running, done, error, timeout. |
| Render Done? / Render Fatal? | n8n-nodes-base.if |
2.2 | Fatal = error, timeout, or attempt ≥ poll_max_attempts. |
| Fetch ASS Transcript | n8n-nodes-base.httpRequest |
4.2 | GET movie.ass as text. Error output still continues. |
| Use OpenAI? | n8n-nodes-base.if |
2.2 | Config llm_provider. |
| Draft Metadata (OpenAI) | n8n-nodes-base.httpRequest |
4.2 | POST https://api.openai.com/v1/chat/completions. |
| Draft Metadata (OpenRouter) | n8n-nodes-base.httpRequest |
4.2 | POST https://openrouter.ai/api/v1/chat/completions. |
| Parse Metadata | n8n-nodes-base.code |
2 | Title ≤ 100, description ≤ 5000, tags with shorts, combined length ≤ 500. |
| Write Awaiting Approval | n8n-nodes-base.googleSheets |
4.5 | Status awaiting_approval plus preview URLs. |
| Telegram: Preview Ready | n8n-nodes-base.telegram |
1.2 | Disabled. Notify-only. |
| Raise … Failure | n8n-nodes-base.stopAndError |
1 | Triggers the Error workflow after the row is marked failed. |
#Auto Shorts – Post Approved
| Node | Type | typeVersion | Role |
|---|---|---|---|
| Every 15 Minutes | n8n-nodes-base.scheduleTrigger |
1.2 | |
| Manual Test Run | n8n-nodes-base.manualTrigger |
1 | |
| Config / Read Queue / Select Approved Rows | set 3.4 / Sheets 4.5 / code 2 | Only status = approved with a preview URL and title. |
|
| Lock Row (publishing) | Sheets 4.5 | ||
| Build Zernio Body | n8n-nodes-base.code |
2 | Official YouTube post body (below). |
| Publish via Zernio | n8n-nodes-base.httpRequest |
4.2 | POST https://zernio.com/api/v1/posts, header Idempotency-Key = row id. |
| Mark Posted or Scheduled / Mark Post Failed | Sheets 4.5 | Uses post.status and platforms[0].platformPostUrl when present. |
#Auto Shorts – Error Handler
| Node | Type | typeVersion | Role |
|---|---|---|---|
| Error Trigger | n8n-nodes-base.errorTrigger |
1 | |
| Config / Format Error | set 3.4 | Sheet ID and execution fields from the trigger. | |
| Log Error to Sheet | Sheets 4.5 | Append to error_log. |
#JSON2Video movie body
POST https://api.json2video.com/v2/movies
Headers: x-api-key, Content-Type: application/json
Response: { success, project, timestamp }. Poll GET /v2/movies?project={id} until movie.status is done, error, or timeout.
{
"resolution": "custom",
"width": 1080,
"height": 1920,
"quality": "high",
"cache": true,
"client-data": { "queue_id": "AS-20261111-DEMO" },
"elements": [
{
"type": "subtitles",
"language": "auto",
"model": "whisper",
"settings": {
"style": "boxed-word",
"font-family": "Oswald Bold",
"font-size": 90,
"word-color": "#FFFF00",
"line-color": "#FFFFFF",
"box-color": "#000000",
"outline-color": "#000000",
"outline-width": 6,
"position": "bottom-center",
"max-words-per-line": 4
}
}
],
"scenes": [
{
"elements": [
{
"type": "video",
"src": "https://example.com/clip.mp4",
"resize": "cover",
"position": "center-center"
}
]
}
]
}Official notes used by this pack:
subtitlesis movie-level only (not inside a scene). One per movie.- Omitting
captionsmeans auto-transcribe the audio.modelenum:default,elevenlabs,deepgram,whisper. - Subtitle
settingsis a closed list. Do not invent CSS keys (coloris rejected; useword-color/line-color). resolution: customrequireswidthandheight. This pack uses explicit 1080×1920 rather than a named preset.- Official
fpsis accepted but every movie currently renders at 25 fps. - Rendered files and
movie.ass/ thumbnail are removed after 7 days. POST /v2/moviesis not idempotent.
#Zernio YouTube body
POST https://zernio.com/api/v1/posts
Header: Authorization: Bearer …, plus Idempotency-Key.
{
"content": "Description text\n\n#shorts",
"tags": ["shorts", "cafe"],
"mediaItems": [{ "type": "video", "url": "https://example.com/render.mp4", "thumbnail": "https://example.com/render.jpg" }],
"platforms": [{
"platform": "youtube",
"accountId": "ACCOUNT_ID",
"platformSpecificData": {
"title": "Title at most 100 characters",
"visibility": "private",
"madeForKids": false,
"containsSyntheticMedia": false
}
}],
"publishNow": true
}For a future time, omit publishNow and set top-level "scheduledFor": "2026-11-15T18:00:00+08:00" and "timezone": "Asia/Taipei". Official rule: publishNow: true wins over scheduledFor; a past scheduledFor publishes in the same request.
YouTube detects Shorts from duration and aspect ratio. There is no Shorts flag. tags is top-level. Always send madeForKids.
#Credentials
| Placeholder name | n8n credential type | Used on |
|---|---|---|
| Google Sheets (Auto Shorts Queue) | googleSheetsOAuth2Api |
All Sheets nodes |
| JSON2Video API | httpHeaderAuth |
Create movie, Get status |
| OpenAI | openAiApi |
Draft Metadata (OpenAI) |
| OpenRouter API | httpHeaderAuth |
Draft Metadata (OpenRouter) |
| Zernio API | httpHeaderAuth |
Publish via Zernio |
| Telegram (Auto Shorts) | telegramApi |
Disabled Telegram node |
IDs are REPLACE_ME. Pick the real credential after import.
Document (By ID) and Sheet (By Name) use expression mode with an = prefix and double curly braces:
={{ $('Config').first().json.google_sheet_id }}
={{ $('Config').first().json.queue_sheet_name }}On the Error Handler (pictured), the sheet field is error_sheet_name instead of queue_sheet_name.