{
  "name": "H3 视频入门：创建一次、有界查询、手动下载",
  "nodes": [
    {
      "id": "8926bf90-8c20-4810-8ed8-e773a17566c3",
      "name": "01 手动开始",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ],
      "parameters": {},
      "notes": "导入后先配置凭据与参数，再手动执行。执行本工作流会真实创建一次视频，可能产生费用。不要重复点击或单独重跑创建节点。",
      "notesInFlow": true
    },
    {
      "id": "5015ce75-d30c-48d1-b478-b325c5fbc8eb",
      "name": "02 参数设置（不填 Key）",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        260,
        0
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "6cc196e8-f4ad-4956-8e44-8e6bc259775a",
              "name": "model",
              "value": "h3",
              "type": "string"
            },
            {
              "id": "d4bc8342-c066-4391-8cb7-1a34b95fab3c",
              "name": "prompt",
              "value": "一只蓝色纸船在平静水面缓缓漂浮，固定镜头，无人物，无文字",
              "type": "string"
            },
            {
              "id": "aaaaf5a2-e999-4d61-9345-3715751eac48",
              "name": "duration",
              "value": 6,
              "type": "number"
            },
            {
              "id": "5d45599e-4002-4d6e-8db2-b6b520e6341c",
              "name": "poll_interval_seconds",
              "value": 5,
              "type": "number"
            },
            {
              "id": "a5d5bd67-a0a1-4391-bc63-91ce440045bd",
              "name": "max_polls",
              "value": 120,
              "type": "number"
            },
            {
              "id": "0c850e3f-404d-42ae-930d-4f5c57f46245",
              "name": "max_seconds",
              "value": 600,
              "type": "number"
            }
          ]
        },
        "includeOtherFields": false,
        "options": {}
      },
      "notes": "只填非机密参数；不在此处保存 Key。H3 模板只发送 model、prompt、duration，不默认要求分辨率。查询最多 120 次，整个执行最多 10 分钟。",
      "notesInFlow": true
    },
    {
      "id": "5eab2614-f808-47c4-beff-76d3ab106508",
      "name": "03 校验参数与计时",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        520,
        0
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "const c = $input.first().json;\nconst errors = [];\nconst model = typeof c.model === 'string' ? c.model.trim() : '';\nconst prompt = typeof c.prompt === 'string' ? c.prompt.trim() : '';\nif (model !== 'h3') errors.push('此模板仅支持 model=h3；其他型号请使用独立契约。');\nif (!prompt || prompt.length > 4000) errors.push('prompt 必须为 1–4000 个字符。');\nconst limits = { duration: [1, 15], poll_interval_seconds: [1, 30], max_polls: [1, 120], max_seconds: [1, 600] };\nfor (const [key, [min, max]] of Object.entries(limits)) {\n  if (!Number.isInteger(c[key]) || c[key] < min || c[key] > max) errors.push(key + ' 必须为 ' + min + '–' + max + ' 的整数。');\n}\nconst now = Date.now();\nconst config = { model, prompt, duration: c.duration, poll_interval_seconds: c.poll_interval_seconds, max_polls: c.max_polls, max_seconds: c.max_seconds };\nreturn [{ json: {\n  config, request_body: { model, prompt, duration: c.duration },\n  started_at_ms: now, deadline_ms: now + (errors.length ? 0 : c.max_seconds * 1000),\n  task_id: null, poll_count: 0, generation_status: errors.length ? 'stopped' : 'ready',\n  can_create: errors.length === 0, can_poll: false, continue_polling: false,\n  error_code: errors.length ? 'INVALID_SETTINGS' : null,\n  message: errors.length ? errors.join(' ') : '参数通过；本次手动执行只允许创建一次。',\n}, pairedItem: { item: 0 } }];"
      },
      "notes": "检查 H3 字段与硬上限，创建前开始计时。参数错误直接进入停止输出。",
      "notesInFlow": true
    },
    {
      "id": "53a3616d-e4bc-41cc-82b4-c8cead1f849d",
      "name": "04 参数有效？",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        780,
        0
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "e269faec-18cb-42ef-85eb-626d69ee217c",
              "leftValue": "={{ $json.can_create }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "notes": "true → 创建一次；false → 停止，不发出创建请求。",
      "notesInFlow": true
    },
    {
      "id": "4702f79a-7f91-4fd5-a6eb-397cb4bcbf9b",
      "name": "05 创建视频（仅一次）",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.5,
      "position": [
        1040,
        0
      ],
      "parameters": {
        "method": "POST",
        "url": "https://xcmapi.org/v1/videos",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ $json.request_body }}",
        "options": {
          "redirect": {
            "redirect": {
              "followRedirects": false,
              "maxRedirects": 0
            }
          },
          "sendCredentialsOnCrossOriginRedirect": false,
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": true,
              "responseFormat": "json"
            }
          },
          "timeout": "={{ Math.max(1, Math.min(30000, $json.deadline_ms - Date.now() - 1000)) }}"
        }
      },
      "notes": "必须选择自己创建的 Header Auth：Name=Authorization，Value=Bearer 加空格加用户 Key。11 查询节点也选择同一凭据。Retry On Fail 已关闭，禁止自动重试、分页和跳转；超时不代表创建失败。",
      "notesInFlow": true,
      "credentials": {},
      "retryOnFail": false,
      "onError": "continueRegularOutput",
      "alwaysOutputData": true
    },
    {
      "id": "82100d62-bbab-4170-bb93-ede02d3df8e2",
      "name": "06 保存任务 ID",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1300,
        0
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "const state = { ...$('03 校验参数与计时').item.json, can_create: false, can_poll: false, continue_polling: false };\nconst r = $input.first().json;\nconst object = x => x && typeof x === 'object' && !Array.isArray(x) ? x : {};\nconst body = object(r.body);\nconst data = object(body.data);\nconst ids = [body.task_id, data.task_id, body.id, data.id, body.request_id, data.request_id];\nconst rawId = ids.find(x => x !== undefined && x !== null && x !== '');\nconst id = typeof rawId === 'string' ? rawId.trim() : (Number.isSafeInteger(rawId) && rawId >= 0 ? String(rawId) : '');\nconst validId = /^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/.test(id);\nstate.task_id = validId ? id : null;\nstate.http_status = Number.isInteger(r.statusCode) ? r.statusCode : null;\nconst stop = (code, message) => { state.generation_status = 'stopped'; state.error_code = code; state.message = message; };\nconst status = String(body.status ?? body.state ?? data.status ?? data.state ?? '').trim().toLowerCase().replace(/[\\s-]+/g, '_');\nif (r.error) stop('CREATE_RESULT_UNKNOWN', '创建请求出错或超时，服务端可能已受理。先核查任务或账单，不要重新执行创建。');\nelse if (!state.http_status || state.http_status < 200 || state.http_status >= 300) stop('CREATE_HTTP_ERROR', '创建返回非 2xx（含被阻止的跳转）。请核查任务，不自动重建。');\nelse if (body.error || data.error || ['failed', 'error', 'expired', 'cancelled', 'canceled'].includes(status)) stop('CREATE_REJECTED', '创建响应表示失败或取消；已保留可用任务 ID，不会重建。');\nelse if (!validId) stop(rawId === undefined ? 'MISSING_TASK_ID' : 'INVALID_TASK_ID', '未收到可安全使用的任务 ID；不会采用响应中的轮询 URL，不会重建。');\nelse if (Date.now() >= state.deadline_ms - 1000) stop('TIME_LIMIT', '已达到时间上限；保留任务 ID，稍后仅查询这个任务。');\nelse {\n  state.generation_status = 'pending'; state.can_poll = true; state.error_code = null;\n  state.wait_seconds = Math.min(state.config.poll_interval_seconds, Math.max(0.001, (state.deadline_ms - Date.now() - 1000) / 1000));\n  state.message = '已保存 task_id；后续只发送 GET 查询。';\n}\nreturn [{ json: state, pairedItem: { item: 0 } }];"
      },
      "notes": "从顶层或 data 提取 task_id / id / request_id，并校验仅含安全路径字符。立即复制 task_id。忽略所有响应中的轮询 URL；创建结果不确定时停止。",
      "notesInFlow": true
    },
    {
      "id": "dbfdbcbd-823a-4adb-9a17-fdb5e63b3eb9",
      "name": "07 可以开始查询？",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1560,
        0
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "4f91b690-0486-435a-ad31-2e9b2a3b6139",
              "leftValue": "={{ $json.can_poll }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "notes": "true → 等待并查询；false → 保留任务 ID 停止，绝不返回创建。",
      "notesInFlow": true
    },
    {
      "id": "ad6b177f-951e-497e-8ca2-dc29c7440d7f",
      "name": "08 等待后再查",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1560,
        320
      ],
      "parameters": {
        "resume": "timeInterval",
        "amount": "={{ $json.wait_seconds }}",
        "unit": "seconds"
      },
      "notes": "短间隔等待。等待后再次核对次数与墙上时间，不因多次循环重置计时。",
      "notesInFlow": true
    },
    {
      "id": "ce8a3307-583d-4a99-97d9-5adf094dd238",
      "name": "09 查询前检查上限",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1300,
        320
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "const state = { ...$input.first().json, can_poll: false, continue_polling: false };\nconst remaining = state.deadline_ms - Date.now();\nconst stop = (code, message) => { state.generation_status = 'stopped'; state.error_code = code; state.message = message; };\nif (!/^[A-Za-z0-9][A-Za-z0-9_-]{0,199}$/.test(state.task_id || '')) stop('INVALID_TASK_ID', '任务 ID 无效；不发送查询。');\nelse if (remaining <= 1000) stop('TIME_LIMIT', '已达到时间上限（预留 1 秒收尾）；不再查询。');\nelse if (state.poll_count >= state.config.max_polls || state.poll_count >= 120) stop('POLL_LIMIT', '已达到查询次数上限；不再查询，也不重建。');\nelse {\n  state.poll_count += 1;\n  state.can_poll = true;\n  state.request_timeout_ms = Math.max(1, Math.min(15000, Math.floor(remaining - 1000)));\n}\nreturn [{ json: state, pairedItem: { item: 0 } }];"
      },
      "notes": "每次 GET 前再次校验原任务 ID、120 次和 600 秒上限；预留 1 秒收尾。通过后才增加本次查询计数。",
      "notesInFlow": true
    },
    {
      "id": "2a8b6b5e-aa4e-4664-a0e6-8890cbb74bbc",
      "name": "10 允许本次查询？",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1040,
        320
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "23c6adfd-34cd-4e16-a3ff-3b48c5ac7989",
              "leftValue": "={{ $json.can_poll }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "notes": "true → 仅查询原任务；false → 停止。",
      "notesInFlow": true
    },
    {
      "id": "7474f123-bcaf-404c-b90b-a84ff2266c1f",
      "name": "11 查询任务（同一凭据）",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.5,
      "position": [
        780,
        320
      ],
      "parameters": {
        "method": "GET",
        "url": "={{ 'https://xcmapi.org/v1/videos/' + encodeURIComponent($json.task_id) }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "redirect": {
            "redirect": {
              "followRedirects": false,
              "maxRedirects": 0
            }
          },
          "sendCredentialsOnCrossOriginRedirect": false,
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": true,
              "responseFormat": "json"
            }
          },
          "timeout": "={{ $json.request_timeout_ms }}"
        }
      },
      "notes": "必须选择与 05 创建节点完全相同的 Header Auth。地址固定为本站 + 校验后的 task_id，不接受服务端给出的轮询 URL。禁止跳转、分页与自动重试。",
      "notesInFlow": true,
      "credentials": {},
      "retryOnFail": false,
      "onError": "continueRegularOutput",
      "alwaysOutputData": true
    },
    {
      "id": "43219afa-8582-452f-a780-6bad7a88dcfe",
      "name": "12 解析状态与计数",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        520,
        320
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "// .item 保留当前这轮 GET 的关联，不能用固定第 0 轮数据替代。\nconst state = { ...$('09 查询前检查上限').item.json, can_poll: false, continue_polling: false };\nconst r = $input.first().json;\nconst object = x => x && typeof x === 'object' && !Array.isArray(x) ? x : {};\nconst body = object(r.body); const data = object(body.data);\nstate.http_status = Number.isInteger(r.statusCode) ? r.statusCode : null;\nconst status = String(body.status ?? body.state ?? data.status ?? data.state ?? '').trim().toLowerCase().replace(/[\\s-]+/g, '_');\nstate.server_status = /^[a-z_]{1,40}$/.test(status) ? status : 'unknown';\nconst stop = (code, message) => { state.generation_status = 'stopped'; state.error_code = code; state.message = message; };\nconst rawId = [body.task_id, data.task_id, body.id, data.id, body.request_id, data.request_id].find(x => x !== undefined && x !== null && x !== '');\nconst replyId = typeof rawId === 'string' ? rawId.trim() : (Number.isSafeInteger(rawId) && rawId >= 0 ? String(rawId) : '');\nif (Date.now() >= state.deadline_ms - 1000) stop('TIME_LIMIT', '已达到时间上限；保留原 task_id，不再查询或重建。');\nelse if (r.error) stop('QUERY_TRANSPORT_ERROR', '查询网络或解析失败；保留任务 ID。先排查，再单独查询原任务。');\nelse if (!state.http_status || state.http_status < 200 || state.http_status >= 300) stop('QUERY_HTTP_ERROR', '查询返回非 2xx（含被阻止的跳转）；保留任务 ID，不重建。');\nelse if (rawId !== undefined && replyId !== state.task_id) stop('TASK_ID_MISMATCH', '查询响应的任务 ID 与原任务不一致；停止，不采用其他任务或地址。');\nelse if (body.error || data.error || ['failed', 'error', 'expired', 'cancelled', 'canceled'].includes(status)) stop('TASK_' + (['failed','error','expired','cancelled','canceled'].includes(status) ? status.toUpperCase() : 'ERROR'), '任务已失败、过期或取消；保留任务 ID，不会重建。');\nelse if (['done', 'completed', 'succeeded', 'success'].includes(status)) {\n  state.generation_status = 'succeeded'; state.error_code = null; state.message = '服务端报告生成完成；本模板尚未下载文件。';\n  const result = object(body.result); const dataResult = object(data.result);\n  const candidates = [object(body.video).url, object(data.video).url, body.video_url, data.video_url, body.download_url, data.download_url, body.url, data.url, result.url, dataResult.url, Array.isArray(body.result_urls) ? body.result_urls[0] : null, Array.isArray(data.result_urls) ? data.result_urls[0] : null];\n  const rawUrl = candidates.find(x => typeof x === 'string' && x.trim());\n  // 地址仅作为结果展示；任何响应地址都不接入带凭据的 HTTP 节点。\n  state.result_url = typeof rawUrl === 'string' && /^https:\\/\\/[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?(?::443)?(?:[/?#][^\\s<>\"\\\\]*)?$/i.test(rawUrl.trim()) && rawUrl.length <= 8192 ? rawUrl.trim() : null;\n  state.result_url_omitted = Boolean(rawUrl && !state.result_url);\n}\nelse if (!['queued', 'pending', 'submitted', 'created', 'running', 'processing', 'in_progress', 'waiting', 'starting'].includes(status)) stop('UNKNOWN_STATUS', '未识别的任务状态；停止自动查询，先核查接口响应，不重建。');\nelse if (state.poll_count >= state.config.max_polls || state.poll_count >= 120) stop('POLL_LIMIT', '已达到查询次数上限；保留任务 ID，稍后仅查询这个任务。');\nelse {\n  state.generation_status = 'pending'; state.continue_polling = true; state.error_code = null;\n  state.wait_seconds = Math.min(state.config.poll_interval_seconds, Math.max(0.001, (state.deadline_ms - Date.now() - 1000) / 1000));\n  state.message = '任务仍在生成；等待后查询同一任务。';\n}\nreturn [{ json: state, pairedItem: { item: 0 } }];"
      },
      "notes": "用当前轮查询前的数据保留 task_id 与累计计数。失败、取消、未知状态、HTTP/网络错误直接停止；完成则给出手动下载结果。",
      "notesInFlow": true
    },
    {
      "id": "898f0247-0089-47d0-a8c7-1c501f068513",
      "name": "13 继续轮询？",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        260,
        320
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "73a0a44a-92d7-4a0f-8803-b0dddb8c519a",
              "leftValue": "={{ $json.continue_polling }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "notes": "true → 仅回到 08 等待；false → 判断最终状态。",
      "notesInFlow": true
    },
    {
      "id": "964edddb-e3b1-4e72-ac84-67a1eb8cc025",
      "name": "14 视频成功？",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        260,
        640
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "a5a29715-8dd7-4961-813b-8b143e3c104f",
              "leftValue": "={{ $json.generation_status }}",
              "rightValue": "succeeded",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "notes": "只有明确成功状态进入完成输出。停止输出即使显示工作流执行结束，也不代表视频生成成功。",
      "notesInFlow": true
    },
    {
      "id": "5e2971cf-7291-4bc0-9b18-1f38ae77a50e",
      "name": "15 完成（手动下载）",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        520,
        640
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "const s = $input.first().json;\nreturn [{ json: {\n  ok: true, generation_status: 'succeeded', task_id: s.task_id,\n  model: s.config.model, duration_requested_seconds: s.config.duration,\n  poll_count: s.poll_count, elapsed_seconds: Math.round((Date.now() - s.started_at_ms) / 1000),\n  download_status: 'not_downloaded', file_saved: false,\n  content_url: 'https://xcmapi.org/v1/videos/' + encodeURIComponent(s.task_id) + '/content',\n  content_requires_same_header_auth: true,\n  result_url: s.result_url || null, result_url_omitted: Boolean(s.result_url_omitted),\n  message: '服务端报告生成完成；本工作流没有下载或保存视频文件。',\n  next_step: '先复制 task_id。若 result_url 是外部 HTTPS 地址，用不带 Authorization 的浏览器下载；否则用同一 Header Auth 单独请求 content_url，并关闭跳转。若返回 30x 或 JSON 外部地址，另开无鉴权请求下载，不能转发 API Key。',\n}, pairedItem: { item: 0 } }];"
      },
      "notes": "这是生成结果与下载指引，不是已下载文件。content_url 需同一凭据且禁止自动跳转；外部存储地址须另用不带 Authorization 的请求下载。",
      "notesInFlow": true
    },
    {
      "id": "61ffe859-49ce-4a4e-ba67-11b11d066a9f",
      "name": "16 停止（保留 task_id）",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1040,
        640
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "const s = $input.first().json;\nreturn [{ json: {\n  ok: false, generation_status: 'stopped', error_code: s.error_code || 'STOPPED',\n  task_id: s.task_id || null, task_id_display: s.task_id || '未返回可用任务 ID：创建结果可能不确定，请先核查任务记录。',\n  poll_count: s.poll_count || 0, elapsed_seconds: Math.max(0, Math.round((Date.now() - s.started_at_ms) / 1000)),\n  http_status: s.http_status || null, server_status: s.server_status || null,\n  message: s.message || '自动流程已停止。', file_saved: false,\n  next_step: s.task_id ? '复制并保留 task_id；排查后仅 GET 查询原任务。不要重新执行 05 创建视频，也不要把连线接回创建节点。' : '先在控制台核查是否已创建或扣费；不要因超时或 ID 缺失直接重试创建。',\n  automatic_stop_does_not_cancel_server_task: true,\n}, pairedItem: { item: 0 } }];"
      },
      "notes": "查看 ok=false、error_code、task_id。停止轮询不等于取消服务端生成；不要重跑创建来代替查询。",
      "notesInFlow": true
    }
  ],
  "connections": {
    "01 手动开始": {
      "main": [
        [
          {
            "node": "02 参数设置（不填 Key）",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "02 参数设置（不填 Key）": {
      "main": [
        [
          {
            "node": "03 校验参数与计时",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "03 校验参数与计时": {
      "main": [
        [
          {
            "node": "04 参数有效？",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "04 参数有效？": {
      "main": [
        [
          {
            "node": "05 创建视频（仅一次）",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "16 停止（保留 task_id）",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "05 创建视频（仅一次）": {
      "main": [
        [
          {
            "node": "06 保存任务 ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "06 保存任务 ID": {
      "main": [
        [
          {
            "node": "07 可以开始查询？",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "07 可以开始查询？": {
      "main": [
        [
          {
            "node": "08 等待后再查",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "16 停止（保留 task_id）",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "08 等待后再查": {
      "main": [
        [
          {
            "node": "09 查询前检查上限",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "09 查询前检查上限": {
      "main": [
        [
          {
            "node": "10 允许本次查询？",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "10 允许本次查询？": {
      "main": [
        [
          {
            "node": "11 查询任务（同一凭据）",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "16 停止（保留 task_id）",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "11 查询任务（同一凭据）": {
      "main": [
        [
          {
            "node": "12 解析状态与计数",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "12 解析状态与计数": {
      "main": [
        [
          {
            "node": "13 继续轮询？",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "13 继续轮询？": {
      "main": [
        [
          {
            "node": "08 等待后再查",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "14 视频成功？",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "14 视频成功？": {
      "main": [
        [
          {
            "node": "15 完成（手动下载）",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "16 停止（保留 task_id）",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "executionTimeout": 600,
    "saveExecutionProgress": false,
    "saveManualExecutions": false,
    "saveDataSuccessExecution": "none",
    "saveDataErrorExecution": "none",
    "timezone": "Asia/Shanghai"
  },
  "tags": [],
  "meta": {
    "templateCredsSetupCompleted": false
  }
}
