8
n8n 中文网amn8n.com

使用OpenAI和Google Sheets从转录文本生成冲刺评审摘要

中级

这是一个Project Management, AI Summarization领域的自动化工作流,包含 13 个节点。主要使用 Code, Form, FormTrigger, GoogleSheets, Agent 等节点。 使用OpenAI和Google Sheets从转录文本生成冲刺评审摘要

前置要求
  • Google Sheets API 凭证
  • OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "meta": {
    "instanceId": "51c6a64ef13fda2e6aa96576c25d72519ca4bc44cea9da20af60a642b594d835",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "155c6cd6-3c71-4399-9f1a-3f6c52c3a384",
      "name": "收集冲刺评审输入",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -320,
        -64
      ],
      "webhookId": "610911dc-0778-4270-a571-9aa90143f00a",
      "parameters": {
        "options": {
          "buttonLabel": "Create Summary"
        },
        "formTitle": "Sprint Review Summary",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "Transcript file",
              "multipleFiles": false
            },
            {
              "fieldLabel": "Sprint name"
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "Domain",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Team 1"
                  },
                  {
                    "option": "Team 2"
                  },
                  {
                    "option": "Team 3"
                  }
                ]
              }
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "7f8b7ce6-d1d9-4961-93b6-22edb0e3c31a",
      "name": "解析转录文本",
      "type": "n8n-nodes-base.code",
      "position": [
        -16,
        -64
      ],
      "parameters": {
        "jsCode": "const binaryKey = Object.keys(items[0].binary || {})[0];\nif (!binaryKey) {\n  throw new Error('No binary data found. Please upload a transcript file.');\n}\nconst binaryData = items[0].binary[binaryKey];\nconst txtContent = Buffer.from(binaryData.data, 'base64').toString('utf-8');\nconst lines = txtContent.split('\\n');\nlet transcriptWithTimestamps = [];\nif (txtContent.startsWith('WEBVTT')) {\n  let currentTimestamp = null;\n  let currentText = [];\n  for (let i = 0; i < lines.length; i++) {\n    const line = lines[i].trim();\n    const ts = line.match(/^(\\d{2}:\\d{2}:\\d{2}\\.\\d{3}) --> (\\d{2}:\\d{2}:\\d{2}\\.\\d{3})$/);\n    if (ts) {\n      if (currentTimestamp && currentText.length) {\n        transcriptWithTimestamps.push(`[${currentTimestamp}] Unknown: ${currentText.join(' ').trim()}`);\n      }\n      currentTimestamp = ts[1];\n      currentText = [];\n    } else if (line !== '' && !line.startsWith('WEBVTT')) {\n      currentText.push(line);\n    }\n  }\n  if (currentTimestamp && currentText.length) {\n    transcriptWithTimestamps.push(`[${currentTimestamp}] Unknown: ${currentText.join(' ').trim()}`);\n  }\n} else {\n  let currentSpeaker = null;\n  let currentTimestamp = null;\n  let currentText = [];\n  for (let i = 0; i < lines.length; i++) {\n    const m = lines[i].match(/^\\[([^\\]]+)\\]\\s+(\\d{2}:\\d{2}:\\d{2})(.*)$/);\n    if (m) {\n      if (currentSpeaker && currentTimestamp && currentText.length) {\n        transcriptWithTimestamps.push(`[${currentTimestamp}] ${currentSpeaker}: ${currentText.join(' ').trim()}`);\n      }\n      currentSpeaker = m[1];\n      currentTimestamp = m[2];\n      currentText = m[3] ? [m[3].trim()] : [];\n    } else if (lines[i].trim() !== '') {\n      currentText.push(lines[i].trim());\n    }\n  }\n  if (currentSpeaker && currentTimestamp && currentText.length) {\n    transcriptWithTimestamps.push(`[${currentTimestamp}] ${currentSpeaker}: ${currentText.join(' ').trim()}`);\n  }\n}\nitems[0].json.transcriptWithTimestamps = transcriptWithTimestamps.join('\\n');\nreturn items;"
      },
      "typeVersion": 2
    },
    {
      "id": "86aa481e-f7aa-40f1-8f45-1d2ffea43d5a",
      "name": "生成摘要",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        272,
        -64
      ],
      "parameters": {
        "text": "=You are an expert Agile coach. Summarize the following Sprint Review transcript related to the domain: {{ $json.Domain }} and sprint: {{ $json['Sprint name'] }}.\n\nRequirements:\n- Output strictly in Markdown.\n- add header title\n- Start with concise summary\n- Then a brief executive summary (3–5 bullets).\n- Then a **Presentation recap** table with columns: Timestamp | Presenter | Topics.\n- Finish with **Action items** as a checklist with owners if recognizable.\n- keep format clean with headers for each sections\n\nTranscript:\n{{ $json.transcriptWithTimestamps }}\n\n\n\n",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 2.1
    },
    {
      "id": "1fb90118-9077-4488-9ab1-efbfffc23736",
      "name": "预览摘要",
      "type": "n8n-nodes-base.form",
      "position": [
        816,
        -144
      ],
      "webhookId": "c9b09c5d-a618-4ee0-a494-552f853306be",
      "parameters": {
        "options": {
          "customCss": ".card {\n\tposition: relative;\n\tmax-width: 500px;\n\tmargin: 20px auto;\n\tpadding: 20px;\n\tbackground: #fefefe !important;\n\tborder-radius: 12px;\n\tbox-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);\n\tfont-family: 'Courier New', monospace;\n\tcolor: #1f2937;\n\tfont-size: 16px;\n\tline-height: 1.6;\n\twhite-space: pre-wrap;\n}\n\n.header p { text-align: left; }\n\n@media (max-width: 768px) {\n\t.card { margin: 10px !important; padding: 15px !important; font-size: 14px; }\n}\n"
        },
        "operation": "completion",
        "completionTitle": "Summary",
        "completionMessage": "={{ $json.output }}"
      },
      "typeVersion": 1
    },
    {
      "id": "70b492a1-5674-4a79-9ae1-6a773b494ec9",
      "name": "OpenAI LLM",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        272,
        160
      ],
      "parameters": {
        "model": {
          "mode": "list",
          "value": "gpt-5-mini-2025-08-07"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "7CgAvVK5FzY7W0vB",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "adb94eee-700f-48af-b4c5-3298e87bfeb4",
      "name": "保存到 Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        816,
        48
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $('Parse Transcript').item.json.submittedAt }}",
            "Domain": "={{ $('Parse Transcript').item.json.Domain }}",
            "Content": "={{ $json.output }}",
            "VTT file": "={{ $('Parse Transcript').item.json['Transcript file'].filename }}",
            "Transcript": "={{ $('Parse Transcript').item.json.transcriptWithTimestamps }}",
            "Sprint name": "={{ $('Parse Transcript').item.json['Sprint name'] }}"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Domain",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Domain",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Sprint name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Sprint name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Content",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Content",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "VTT file",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "VTT file",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Transcript",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Transcript",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "output",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "output",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Date"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/your sheetlink",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1rNGViGRvVgIol0mJzsShXF7h21TC6L3eKt4R8i21AG4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1rNGViGRvVgIol0mJzsShXF7h21TC6L3eKt4R8i21AG4/edit?usp=drivesdk",
          "cachedResultName": "Sprint Review Summary"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "2wOj5Yn1ya1ZE298",
          "name": "Google Sheets Personal"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "d884f161-0977-46a2-8b0b-f59c9a97b942",
      "name": "便签:概览1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        -336
      ],
      "parameters": {
        "width": 256,
        "height": 240,
        "content": "## 概览"
      },
      "typeVersion": 1
    },
    {
      "id": "2886f243-599a-4328-a889-cf57d1b171b7",
      "name": "便签:输入表单1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        112
      ],
      "parameters": {
        "content": "## 输入表单"
      },
      "typeVersion": 1
    },
    {
      "id": "d201c8f4-cbf7-475e-80ce-329d020862eb",
      "name": "便签:解析器1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -80,
        -336
      ],
      "parameters": {
        "height": 192,
        "content": "## 转录文本解析器"
      },
      "typeVersion": 1
    },
    {
      "id": "1f1c40ee-cd8f-4899-b0eb-9bef6e59e1e3",
      "name": "便签:AI 摘要1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        256,
        -320
      ],
      "parameters": {
        "content": "## AI 摘要"
      },
      "typeVersion": 1
    },
    {
      "id": "946883d1-348d-4f49-9caa-ffad446422d2",
      "name": "便签:预览1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        784,
        -272
      ],
      "parameters": {
        "height": 256,
        "content": "## 预览"
      },
      "typeVersion": 1
    },
    {
      "id": "147f0d86-0272-41a7-a447-9cb8d1a9c0f4",
      "name": "便签:表格1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        784,
        224
      ],
      "parameters": {
        "content": "## 存档到表格"
      },
      "typeVersion": 1
    },
    {
      "id": "e38cebcc-793b-48cb-a1ee-3ae85d8ac289",
      "name": "便签:LLM1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        192,
        288
      ],
      "parameters": {
        "content": "## LLM 后端"
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "OpenAI LLM": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Summary",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Generate Summary": {
      "main": [
        [
          {
            "node": "Preview Summary",
            "type": "main",
            "index": 0
          },
          {
            "node": "Save to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Transcript": {
      "main": [
        [
          {
            "node": "Generate Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Collect Sprint Review Input": {
      "main": [
        [
          {
            "node": "Parse Transcript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

中级 - 项目管理, AI 摘要总结

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
中级
节点数量13
分类2
节点类型7
难度说明

适合有一定经验的用户,包含 6-15 个节点的中等复杂度工作流

外部链接
在 n8n.io 查看

分享此工作流