{
  "name": "One Video Ten Posts",
  "nodes": [
    {
      "parameters": {
        "content": "## One video, ten posts\n\nDrop a long video in a Drive folder and get a transcript, clip hooks, LinkedIn posts, X threads and a newsletter draft back in a Google Doc for approval.\n\n**Setup (self-hosted n8n, needs ffmpeg installed)**\n1. Connect Google Drive, Google Docs, Gmail and OpenAI.\n2. Pick the folder to watch in **New Video** and the output folder in **Create Doc**.\n3. Edit your brand voice in **Write Posts**.\n4. Put your scheduler token in **Schedule in Buffer** (or swap that node for Metricool / your scheduler).\n\nOn n8n Cloud there's no ffmpeg: delete the three file nodes and send videos under 25 MB straight to **Transcribe**.",
        "height": 460,
        "width": 460
      },
      "id": "682a82e9-a62c-4889-a022-b6c33f4b4871",
      "name": "Note 0",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -460,
        -260
      ]
    },
    {
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_DRIVE_FOLDER_ID"
        },
        "event": "fileCreated",
        "options": {}
      },
      "id": "61da286b-0771-4a2d-953e-fd7def5d916a",
      "name": "New Video",
      "type": "n8n-nodes-base.googleDriveTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "operation": "download",
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {}
      },
      "id": "021b35ca-ac35-443f-af1e-4fe36961f5b1",
      "name": "Download Video",
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "operation": "write",
        "fileName": "=/tmp/{{ $('New Video').item.json.id }}.video",
        "options": {}
      },
      "id": "69337dd3-82c7-4cb4-8536-bdfd04f2c3ba",
      "name": "Save to Disk",
      "type": "n8n-nodes-base.readWriteFile",
      "typeVersion": 1,
      "position": [
        440,
        0
      ]
    },
    {
      "parameters": {
        "command": "=ffmpeg -y -i /tmp/{{ $('New Video').item.json.id }}.video -vn -ac 1 -ar 16000 -b:a 32k /tmp/{{ $('New Video').item.json.id }}.mp3"
      },
      "id": "bab32259-11ee-439f-b48b-34865a499edc",
      "name": "Extract Audio",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        660,
        0
      ]
    },
    {
      "parameters": {
        "operation": "read",
        "fileSelector": "=/tmp/{{ $('New Video').item.json.id }}.mp3",
        "options": {}
      },
      "id": "cf8b9dc9-3369-415c-8c46-9369a8926149",
      "name": "Read Audio",
      "type": "n8n-nodes-base.readWriteFile",
      "typeVersion": 1,
      "position": [
        880,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/audio/transcriptions",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "openAiApi",
        "sendBody": true,
        "contentType": "multipart-form-data",
        "bodyParameters": {
          "parameters": [
            {
              "parameterType": "formBinaryData",
              "name": "file",
              "inputDataFieldName": "data"
            },
            {
              "name": "model",
              "value": "whisper-1"
            },
            {
              "name": "response_format",
              "value": "verbose_json"
            }
          ]
        },
        "options": {}
      },
      "id": "9ae11d60-d076-4978-b602-ae2727896ce1",
      "name": "Transcribe",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1100,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// [mm:ss] text lines, so the model can point at clip start times.\nconst fmt = s => `${String(Math.floor(s / 60)).padStart(2, '0')}:${String(Math.floor(s % 60)).padStart(2, '0')}`;\nconst lines = ($json.segments || []).map(s => `[${fmt(s.start)}] ${s.text.trim()}`);\nreturn [{ json: { transcript: lines.join('\\n') || $json.text, title: $('New Video').item.json.name } }];",
        "mode": "runOnceForEachItem"
      },
      "id": "ed65016e-e853-47f0-baa1-69f540f0f0e6",
      "name": "Timestamp Transcript",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1320,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/chat/completions",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "openAiApi",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ model: 'gpt-4.1', response_format: { type: 'json_schema', json_schema: { name: 'posts', strict: true, schema: {\"type\": \"object\", \"additionalProperties\": false, \"required\": [\"hooks\", \"linkedin_posts\", \"x_threads\", \"newsletter\"], \"properties\": {\"hooks\": {\"type\": \"array\", \"items\": {\"type\": \"object\", \"additionalProperties\": false, \"required\": [\"timestamp\", \"hook\"], \"properties\": {\"timestamp\": {\"type\": \"string\"}, \"hook\": {\"type\": \"string\"}}}}, \"linkedin_posts\": {\"type\": \"array\", \"items\": {\"type\": \"string\"}}, \"x_threads\": {\"type\": \"array\", \"items\": {\"type\": \"array\", \"items\": {\"type\": \"string\"}}}, \"newsletter\": {\"type\": \"string\"}}} } }, messages: [ { role: 'system', content: \"You repurpose long videos for YOUR BRAND. Voice: YOUR BRAND VOICE (e.g. plain-spoken, practical, no hype). From the timestamped transcript, write: 5 short-form clip hooks with the start timestamp of each clip, 3 LinkedIn posts, 2 X threads (4-7 posts each) and 1 newsletter draft in Markdown.\" }, { role: 'user', content: $json.transcript } ] }) }}",
        "options": {}
      },
      "id": "150f0761-13d5-4e22-ad5c-329440e04305",
      "name": "Write Posts",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1540,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const p = JSON.parse($json.choices[0].message.content);\nconst t = $('Timestamp Transcript').item.json;\nconst out = [`# ${t.title}: content pack`, '', '## Clip hooks', ...p.hooks.map(h => `- [${h.timestamp}] ${h.hook}`), '',\n  '## LinkedIn posts', ...p.linkedin_posts.map((x, i) => `### Post ${i + 1}\\n${x}\\n`), '## X threads',\n  ...p.x_threads.map((th, i) => `### Thread ${i + 1}\\n${th.map((x, j) => `${j + 1}/ ${x}`).join('\\n')}\\n`),\n  '## Newsletter draft', p.newsletter, '', '## Transcript', t.transcript];\nreturn [{ json: { title: `${t.title} - content pack`, text: out.join('\\n'), posts: p } }];",
        "mode": "runOnceForEachItem"
      },
      "id": "fd4a70a6-4924-4742-a9d9-46aeb1368ae2",
      "name": "Format Doc",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1760,
        0
      ]
    },
    {
      "parameters": {
        "folderId": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
        "title": "={{ $json.title }}"
      },
      "id": "d8d1b4b6-0044-4e6c-bd4b-9b698d09eded",
      "name": "Create Doc",
      "type": "n8n-nodes-base.googleDocs",
      "typeVersion": 2,
      "position": [
        1980,
        0
      ]
    },
    {
      "parameters": {
        "operation": "update",
        "documentURL": "={{ $json.id }}",
        "actionsUi": {
          "actionFields": [
            {
              "action": "insert",
              "text": "={{ $('Format Doc').item.json.text }}"
            }
          ]
        }
      },
      "id": "a0e613be-d231-4953-8e8f-725a9ca19b87",
      "name": "Write Doc",
      "type": "n8n-nodes-base.googleDocs",
      "typeVersion": 2,
      "position": [
        2200,
        0
      ]
    },
    {
      "parameters": {
        "sendTo": "YOUR_EMAIL",
        "subject": "=Content pack ready: {{ $('Format Doc').item.json.title }}",
        "emailType": "text",
        "message": "=Review and edit here: https://docs.google.com/document/d/{{ $('Create Doc').item.json.id }}\n\nWhen you're happy, approve and schedule the LinkedIn posts:\nYOUR_N8N_WEBHOOK_URL/content-approve?doc={{ $('Create Doc').item.json.id }}",
        "options": {
          "appendAttribution": false
        }
      },
      "id": "3412e680-73be-4f3d-862c-e9f7b28b86ad",
      "name": "Send for Approval",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        2420,
        0
      ]
    },
    {
      "parameters": {
        "httpMethod": "GET",
        "path": "content-approve",
        "options": {}
      },
      "id": "5c8452ee-7f35-4de3-872e-20b822f0dada",
      "name": "Approve",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        400
      ],
      "webhookId": "ed57e785-2580-495f-a202-a8e96e852db8"
    },
    {
      "parameters": {
        "operation": "get",
        "documentURL": "={{ $json.query.doc }}"
      },
      "id": "c48e4fab-330d-424c-95b1-8cf3609b2dfb",
      "name": "Get Doc",
      "type": "n8n-nodes-base.googleDocs",
      "typeVersion": 2,
      "position": [
        220,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "// Reads the approved (edited) posts back out of the doc.\nconst text = $json.content || '';\nconst section = (text.split('## LinkedIn posts')[1] || '').split('## X threads')[0];\nreturn section.split(/### Post \\d+/).map(s => s.trim()).filter(Boolean).map(post => ({ json: { post } }));"
      },
      "id": "abc6e838-22c0-403c-af01-6e2101eb67fc",
      "name": "Pull LinkedIn Posts",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        400
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.bufferapp.com/1/updates/create.json",
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "access_token",
              "value": "YOUR_BUFFER_ACCESS_TOKEN"
            },
            {
              "name": "profile_ids[]",
              "value": "YOUR_BUFFER_PROFILE_ID"
            },
            {
              "name": "text",
              "value": "={{ $json.post }}"
            }
          ]
        },
        "options": {}
      },
      "id": "6db713cd-56de-43c4-93b7-db0b7bb9fb7d",
      "name": "Schedule in Buffer",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        660,
        400
      ]
    }
  ],
  "connections": {
    "New Video": {
      "main": [
        [
          {
            "node": "Download Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Video": {
      "main": [
        [
          {
            "node": "Save to Disk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save to Disk": {
      "main": [
        [
          {
            "node": "Extract Audio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Audio": {
      "main": [
        [
          {
            "node": "Read Audio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Audio": {
      "main": [
        [
          {
            "node": "Transcribe",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transcribe": {
      "main": [
        [
          {
            "node": "Timestamp Transcript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Timestamp Transcript": {
      "main": [
        [
          {
            "node": "Write Posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write Posts": {
      "main": [
        [
          {
            "node": "Format Doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Doc": {
      "main": [
        [
          {
            "node": "Create Doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Doc": {
      "main": [
        [
          {
            "node": "Write Doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write Doc": {
      "main": [
        [
          {
            "node": "Send for Approval",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Approve": {
      "main": [
        [
          {
            "node": "Get Doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Doc": {
      "main": [
        [
          {
            "node": "Pull LinkedIn Posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pull LinkedIn Posts": {
      "main": [
        [
          {
            "node": "Schedule in Buffer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "active": false
}