Auto Shortsfor n8n
Get the kit

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

All names are prefixed Auto Shorts – and ship inactive.

#Auto Shorts – Submit Clip (Form)

Hosted form at /form/auto-shorts-submit. Do not put a Form Trigger in the same workflow as Respond to Webhook (an n8n 2.x limitation).
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

Create is skipped when a rendering row already has json2video_project. The poll loop is Wait → GET → Note → Done? → Fatal? and back to Wait.
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.
Config uses n8n Set 3.4 in Manual Mapping mode.

#Auto Shorts – Post Approved

Future scheduled_at is sent as scheduledFor; the workflow does not wait until that clock time.
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

Set this as the Error workflow of the form, ingest, and post workflows.
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.

JSON
{
  "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:

  • subtitles is movie-level only (not inside a scene). One per movie.
  • Omitting captions means auto-transcribe the audio. model enum: default, elevenlabs, deepgram, whisper.
  • Subtitle settings is a closed list. Do not invent CSS keys (color is rejected; use word-color / line-color).
  • resolution: custom requires width and height. This pack uses explicit 1080×1920 rather than a named preset.
  • Official fps is accepted but every movie currently renders at 25 fps.
  • Rendered files and movie.ass / thumbnail are removed after 7 days.
  • POST /v2/movies is not idempotent.

#Zernio YouTube body

POST https://zernio.com/api/v1/posts
Header: Authorization: Bearer …, plus Idempotency-Key.

JSON
{
  "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 and Sheet come from the Config node. Select the Google Sheets (Auto Shorts Queue) credential after import.

Document (By ID) and Sheet (By Name) use expression mode with an = prefix and double curly braces:

Text
={{ $('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.

Auto Shorts for n8n: a public clip becomes a captioned 9:16 Short, a person approves it, then it is posted to YouTube.

Checked against n8n 2.47.3. n8n, YouTube, Google Sheets, JSON2Video, OpenAI, OpenRouter, Zernio and Telegram are trademarks of their owners; this kit is not affiliated with them. Sample data is fictional.