{
  "name": "Remotion - Render Video (Polling)",
  "nodes": [
    {
      "parameters": {
        "content": "## Remotion Render (Polling)\n\n**Sebelum pakai:**\n1. Jalankan `npm run server` di proyek Remotion\n2. Ganti `http://localhost:3001` di semua node HTTP jika API beda host\n3. Aktifkan workflow \u2192 salin URL Webhook Production\n\n**Body Webhook contoh:**\n```json\n{\n  \"title\": \"Judul Video\",\n  \"subtitle\": \"Subjudul\",\n  \"aspectPreset\": \"portrait\",\n  \"logoUrl\": \"uploads/xxx.png\",\n  \"features\": [{\"icon\":\"\u26a1\",\"label\":\"Fitur 1\"}],\n  \"metadata\": {\"orderId\":\"001\"}\n}\n```",
        "height": 340,
        "width": 420
      },
      "id": "note-0001",
      "name": "Catatan",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -200,
        -120
      ]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "remotion-render",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "node-webhook",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://localhost:3001/render",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({\n  compositionId: 'ContohRemotion',\n  metadata: $json.metadata || {},\n  props: {\n    title: $json.title || 'Remotion',\n    subtitle: $json.subtitle || 'Video dengan React',\n    featureHeading: $json.featureHeading || 'Fitur Kami',\n    features: $json.features || [\n      { icon: '\u26a1', label: 'Fitur 1' },\n      { icon: '\ud83c\udfac', label: 'Fitur 2' },\n      { icon: '\u269b\ufe0f', label: 'Fitur 3' }\n    ],\n    outroTitle: $json.outroTitle || 'Terima Kasih',\n    ctaText: $json.ctaText || 'www.example.com',\n    logoUrl: $json.logoUrl || null,\n    backgroundImageUrl: $json.backgroundImageUrl || null,\n    audioUrl: $json.audioUrl || null,\n    audioVolume: $json.audioVolume ?? 0.5,\n    theme: $json.theme || undefined,\n    scenes: $json.scenes || undefined,\n    output: {\n      aspectPreset: $json.aspectPreset || 'landscape',\n      fps: $json.fps || 30,\n      format: $json.format || 'mp4'\n    }\n  }\n}) }}",
        "options": {
          "timeout": 30000
        }
      },
      "id": "node-render",
      "name": "Render Video",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        480,
        300
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=http://localhost:3001/render/{{ $('Render Video').item.json.jobId }}",
        "options": {
          "timeout": 30000
        }
      },
      "id": "node-poll",
      "name": "Poll Status",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        720,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "cond-completed",
              "leftValue": "={{ $json.status }}",
              "rightValue": "completed",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "node-if-done",
      "name": "Selesai?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        960,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "cond-failed",
              "leftValue": "={{ $json.status }}",
              "rightValue": "failed",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "node-if-failed",
      "name": "Gagal?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1200,
        420
      ]
    },
    {
      "parameters": {
        "amount": 5
      },
      "id": "node-wait",
      "name": "Tunggu 5 Detik",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1440,
        540
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=http://localhost:3001{{ $json.outputUrl }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          },
          "timeout": 120000
        }
      },
      "id": "node-download",
      "name": "Download Video",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1200,
        120
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ {\n  success: true,\n  jobId: $('Render Video').item.json.jobId,\n  status: $('Poll Status').item.json.status,\n  outputUrl: 'http://localhost:3001' + $('Poll Status').item.json.outputUrl,\n  metadata: $('Poll Status').item.json.metadata,\n  completedAt: $('Poll Status').item.json.completedAt,\n  message: 'Video berhasil di-render'\n} }}",
        "options": {
          "responseCode": 200
        }
      },
      "id": "node-respond-ok",
      "name": "Respond Sukses",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        1440,
        120
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ {\n  success: false,\n  jobId: $('Render Video').item.json.jobId,\n  status: 'failed',\n  error: $json.error || 'Render gagal',\n  metadata: $json.metadata\n} }}",
        "options": {
          "responseCode": 500
        }
      },
      "id": "node-respond-err",
      "name": "Respond Gagal",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        1440,
        360
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Render Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Render Video": {
      "main": [
        [
          {
            "node": "Poll Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Poll Status": {
      "main": [
        [
          {
            "node": "Selesai?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Selesai?": {
      "main": [
        [
          {
            "node": "Download Video",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Gagal?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gagal?": {
      "main": [
        [
          {
            "node": "Respond Gagal",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Tunggu 5 Detik",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tunggu 5 Detik": {
      "main": [
        [
          {
            "node": "Poll Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Video": {
      "main": [
        [
          {
            "node": "Respond Sukses",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [],
  "triggerCount": 1,
  "meta": {
    "templateCredsSetupCompleted": true
  }
}