{
  "name": "Cloudinary — Accessible Video Player (AI captions, transcript, chapters)",
  "nodes": [
    {
      "parameters": {},
      "id": "66660000-0000-4a01-9001-000000000001",
      "name": "Start",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        240,
        320
      ]
    },
    {
      "parameters": {
        "resource": "upload",
        "operation": "uploadUrl",
        "url": "https://cloudinary-res.cloudinary.com/video/upload/training/update-img-node-sdk",
        "resource_type": "video",
        "additionalFields": {
          "public_id": "n8n_blog/accessible_player_demo",
          "tags": "n8n-blog,a11y-player"
        }
      },
      "id": "66660000-0000-4a01-9001-000000000002",
      "name": "Upload Sample Video",
      "type": "n8n-nodes-cloudinary.cloudinary",
      "typeVersion": 1,
      "position": [
        520,
        320
      ]
    },
    {
      "parameters": {
        "resource": "widget",
        "operation": "videoPlayer",
        "transformPublicId": "={{ $json.public_id }}",
        "type": "upload",
        "playerSourceTypes": [
          "mp4"
        ],
        "playerPlayback": {
          "autoplayMode": "",
          "muted": false,
          "loop": false,
          "playsinline": true,
          "controls": true,
          "bigPlayButton": true
        },
        "playerLayout": {
          "fluid": true,
          "aspectRatio": "16:9",
          "cropMode": "fill"
        },
        "playerAppearance": {
          "skin": "light"
        },
        "playerFeatures": {
          "seekThumbnails": true
        },
        "playerAiOptions": {
          "generateCaptions": true,
          "captionsLabel": "English",
          "generateTitle": true,
          "generateDescription": true,
          "generateChapters": true,
          "chaptersButton": true
        }
      },
      "id": "66660000-0000-4a01-9001-000000000003",
      "name": "Accessible Player + AI Captions",
      "type": "n8n-nodes-cloudinary.cloudinary",
      "typeVersion": 2,
      "position": [
        820,
        320
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "// The Video Player node emits a hosted embed_url without the AI caption track.\n// We append it as a source[textTracks] URL param (it renders in the hosted\n// player). The player auto-generates the English transcript on demand. No newlines.\nconst embed_url = $json.embed_url\n  + '&source[textTracks][captions][label]=English&source[textTracks][captions][default]=true';\n\n// Paste-in player. A bare <video> won't show captions — this hosted iframe does.\nconst embed_snippet = '<iframe src=\"' + embed_url + '\" width=\"640\" height=\"360\" style=\"width:100%;aspect-ratio:16/9;border:0\" allow=\"autoplay; fullscreen; encrypted-media; picture-in-picture\" allowfullscreen></iframe>';\n\nreturn [{ json: { embed_url, embed_snippet, player_config: $json.player_config } }];"
      },
      "id": "66660000-0000-4a01-9001-000000000004",
      "name": "Build Embed Snippet",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1120,
        320
      ]
    },
    {
      "parameters": {
        "content": "## ♿ Accessible Video Player (AI-generated captions)\n\n**A compliant, captioned player from one upload — no .vtt files, no front-end build.** Great for accessibility (WCAG), regulated content, and searchable video.\n\n### What it does\n1. **Upload Sample Video** fetches a narrated demo clip — real speech, so the transcript has something to caption — into your Cloudinary account.\n2. **Accessible Player + AI Captions** configures the **Video Player** with accessibility-first settings and turns on **AI-Generated Content**: an auto-generated transcript shown as toggleable captions, plus AI title, description, and chapters.\n3. **Build Embed Snippet** outputs a one-click, shareable **`embed_url`** plus a paste-in **`embed_snippet`** `<iframe>` for the hosted player. It opens with captions on.\n\n### Why it's low-effort\nNobody writes `.vtt` files. The captions and chapters **generate on demand** the first time they're requested — the player returns `202` while generating, then caches — only when they don't already exist, and the unsigned actions are **enabled by default** on most accounts. One upload, captioned player.\n\n### Make it yours\n- **Your video:** point *Upload Sample Video* at your own clip with spoken audio.\n- **Use it:** open `embed_url` to share or test, or paste `embed_snippet` into your page.\n\n> 🌍 **Translated subtitles (e.g. Español)?** Unlike the base transcript, the player does **not** generate translations on demand — they must be produced up front with `auto_transcription: { translate: ['es'] }` at upload time (which also needs the Google Translate add-on enabled). The upload node doesn't expose that field yet, so this template ships **original-language captions only**. To add translations today, generate them once with an `explicit` Upload API call on the asset.\n\n> ℹ️ Captions ride on the hosted player via a `source[textTracks]` URL param. A bare `<video>` element won't show them — they need the Cloudinary player. This demo serves a **progressive `mp4`** rather than HLS adaptive streaming: in the hosted player, HLS and manually-supplied caption tracks conflict (the streaming tech can't redefine `textTracks`), so for a captioned clip, mp4 is the reliable source.\n\n### Setup\n👉 Add your **Cloudinary API** credential to the Cloudinary nodes (Cloud name + API Key + Secret from the [Console](https://console.cloudinary.com/settings/api-keys)). Not included in this template.\n\n💾 **Then press `Cmd/Ctrl+S` to save before running.** That one save persists the credential to *every* Cloudinary node at once, so a full **Execute Workflow** run finds credentials everywhere. Skip the save and the run can fail node-after-node with *\"Node does not have any credentials set\"* — even though the credential looks selected. (If **Execute step** works but **Execute Workflow** doesn't, you forgot the save.)",
        "height": 1140,
        "width": 600
      },
      "id": "66660000-0000-4a01-9001-000000000005",
      "name": "README",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        200,
        560
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Upload Sample Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Sample Video": {
      "main": [
        [
          {
            "node": "Accessible Player + AI Captions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Accessible Player + AI Captions": {
      "main": [
        [
          {
            "node": "Build Embed Snippet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {}
}
