Field SOP
Field SOP

Meeting Recording to Minutes with n8n: Transcription, Action-Item Extraction, and Distribution SOP

Build an n8n workflow automating the full chain from meeting recording upload through Whisper transcription, LLM-generated minutes with action items (owner + deadline), to distribution via Feishu, email, and Notion. Covers 4-step node configuration, 6 pitfalls with fixes, Feishu webhook setup, and ffmpeg splitting commands.

Published August 6, 20269 min read
<!-- meeting-recording-summary-workflow-sop | sop | Meeting Recording to Minutes with n8n: Transcription, Action-Item Extraction, and Distribution SOP -->

Recording a meeting is easy. What happens after is not. A one-hour meeting takes two to three hours to transcribe by hand, one person types up the minutes, action items scatter across chat logs with no owner, and next week's meeting opens with "did anyone follow up on that?" -- silence. The recording sits on a drive, as useless as if it never existed.

The problem is not "did we record" but "nobody turned the recording into executable tasks afterward." This SOP builds an n8n workflow that automates the full chain: audio upload -> Whisper transcription -> LLM-generated minutes with action items (owner + deadline) -> distribution to Feishu, email, and Notion. Node names and API parameters follow official docs -- nothing fabricated.

One-line framing: this workflow does not solve "transcription" (Whisper already does that well) -- it solves the "structuring" that comes after. It turns a wall of text into minutes with a summary, decisions, owners, and deadlines, then pushes them where they need to go.


One: Scenario and Pain Points

The typical team meeting chain: record -> one person writes minutes -> posts in group chat -> everyone glances -> action items go unowned -> next week's meeting re-discusses the same thing. Four pain points dominate:

Pain pointSymptomConsequence
Manual transcriptionOne hour of audio takes 2-3 hours to processNobody volunteers; minutes arrive late or never
Unstructured minutesA wall of text, no clear pointsReading it is pointless; key info is buried
Ownerless action items"Follow up" and "advance" with no name attachedNo owner = no execution
Manual distributionPost to chat, then forgetTasks never enter any tracking system

The core gap: recording ≠ minutes, minutes ≠ executable tasks. Two steps are missing -- turning audio into text, then turning text into structured tasks with owners and deadlines. n8n + Whisper + LLM fills both.


Two: Tool Selection -- n8n Orchestration + Whisper Transcription + LLM Extraction

Three core components, each owning one segment of the chain:

ComponentWhat it doesWhy this choice
n8nWorkflow orchestration: trigger -> transcribe -> generate -> distributeVisual, self-hostable, data stays private, 400+ nodes for Feishu/email/Notion
OpenAI WhisperSpeech to textOfficial ASR, $0.006/min, supports Chinese, stable API
LLM (GPT-4o / DeepSeek)Generate minutes + extract action itemsExtracts summaries, decisions, tasks, owners, deadlines from unstructured text

Why not use a ready-made meeting bot (Otter, Fireflies, Feishu Minutes)?

Not because they are bad -- but in three scenarios, self-building wins:

  1. Control: Ready-made tools output a fixed format. If you need "every action item must have an owner + deadline + @-mention on Feishu," they cannot do it. A custom prompt gives you full control over output format.
  2. Cost: Otter Business is $20/month/user -- 10 people is $200/month. Whisper charges $0.36 per hour of audio; 50 hours of meetings a month is about $18. An order of magnitude cheaper.
  3. Data privacy: Self-hosted n8n + your choice of LLM means recordings never touch a third-party SaaS. For internal or sensitive meetings, this is a hard requirement.

Ready-made tools are fine for "personal use, non-sensitive, format-agnostic" scenarios. For teams that need custom output and private deployment, a self-built workflow is the better call.


Three: Step-by-Step Build

Four steps, each with node configuration details and key parameters. The following uses self-hosted n8n; cloud operations are identical unless noted.

Step 1: Recording Upload Trigger (Webhook Node)

Drag in a Webhook node as the workflow entry point. Audio files arrive via HTTP POST to this webhook.

Node configuration:

ParameterValueNotes
HTTP MethodPOSTFile upload requires POST
Pathmeeting-uploadPath segment of the webhook URL
Response ModeWhen Last Node FinishesWait for the workflow to complete before responding
Response DataAll EntriesReturn processing result to the uploader

When the Webhook node receives a file, n8n stores the binary data in a binary property (default property name depends on the upload field name, typically data). Downstream nodes reference the audio file by this property name.

bash
# Upload a recording to trigger the webhook (curl test)
curl -X POST https://your-n8n-domain/webhook/meeting-upload \
  -F "file=@meeting_20260806.mp3"

If n8n runs on an internal network, the Webhook must be publicly reachable. Use an ngrok tunnel or reverse proxy to expose it. In production, always use HTTPS and access control.

Alternative: Local File Trigger node. If recordings land in a shared folder automatically (e.g., Zoom auto-records to a directory), use the Local File Trigger node instead of Webhook. Configure the watch path and trigger event (file created) to skip manual upload. Self-hosted only.

Step 2: HTTP Request to Whisper for Transcription

Drag in an HTTP Request node, connect it to the Webhook output. This calls the OpenAI Whisper API to convert audio to text.

Whisper API spec (per official docs):

  • Endpoint: POST https://api.openai.com/v1/audio/transcriptions
  • Auth: Authorization: Bearer sk-xxx (store via n8n Credentials, do not hardcode)
  • Required params: file (audio file), model (whisper-1)
  • Optional params: language (ISO-639-1, e.g. zh, en), response_format (json/text/srt/verbose_json/vtt), prompt (context/proper nouns), temperature (0-1)
  • File size limit: 25 MB
  • Supported formats: mp3, mp4, mpeg, mpga, m4a, wav, webm

HTTP Request node configuration:

ParameterValue
MethodPOST
URLhttps://api.openai.com/v1/audio/transcriptions
AuthenticationGeneric Credential Type -> OpenAI API (credential reference, not hardcoded)
Body Content TypeMultipart-Form Data
Input Field modelwhisper-1 (type: String)
Input Field fileType: File, Binary Property set to the Webhook's property name (e.g. data)
Input Field response_formatverbose_json (type: String)
Input Field languagezh (type: String, for Chinese meetings)
json
// verbose_json response example (includes timestamped segments for speaker diarization)
{
  "task": "transcribe",
  "language": "chinese",
  "duration": 3600.12,
  "text": "Today's meeting mainly discussed the Q3 product roadmap...",
  "segments": [
    { "id": 0, "start": 0.0, "end": 5.32, "text": "Today's meeting mainly discussed..." },
    { "id": 1, "start": 5.32, "end": 12.10, "text": "..." }
  ]
}

Why verbose_json over the default json: it returns both text (full transcript) and segments (timestamped chunks). If you later need speaker diarization or timestamp annotation, segments are the foundation.

Cost reference: Whisper charges $0.006/min. A one-hour meeting costs about $0.36. See the OpenAI pricing page for current rates.

Step 3: LLM Node to Generate Minutes + Extract Action Items

With the full transcript in hand, use n8n's Basic LLM Chain node (Advanced AI node family) to generate structured minutes. This node takes a prompt and returns LLM output -- no Memory or Tools needed, making it lighter than the AI Agent node and ideal for single-shot "input text -> structured result" tasks.

Node configuration:

  1. Drag in a Basic LLM Chain node, connect it to the HTTP Request (Whisper) output.
  2. Attach an OpenAI Chat Model sub-node as the Language Model: select gpt-4o (or a DeepSeek-compatible model), reference the API key via credentials.
  3. In the Basic LLM Chain prompt, reference the transcript: {{ $json.text }} (the full text from Whisper's verbose_json response).

System Prompt (the critical part):

text
You are a meeting minutes assistant. Given a meeting transcript, output Markdown in this structure:

## Meeting Minutes

### Summary
(3-5 sentences capturing the core content)

### Key Decisions
1. (One decision per line)

### Action Items
| Task | Owner | Deadline |
|---|---|---|
| (Specific, executable task) | (Name; "TBD" if unclear) | (Date; "TBD" if unclear) |

### Open Issues
- (Discussed but unresolved topics)

Rules:
- Summary: max 5 sentences, conclusions only
- Action items must be concrete actions, not vague phrases like "advance X"
- Extract owners and deadlines from the text; mark "TBD" if not explicitly stated -- never guess
- Do not fabricate information not present in the text

Advanced: Use a Code node to split action items. If you need to push each action item individually to Feishu (e.g., @-mention the owner), add a Code node after the LLM. Have the LLM output JSON instead of Markdown, then parse it into an array:

javascript
// Code node: parse LLM JSON output, split into individual items
const raw = $input.first().json.text; // LLM output
const parsed = JSON.parse(raw);
const actionItems = parsed.action_items || [];

// Output each action item as a separate item for downstream per-item distribution
return actionItems.map(item => ({
  json: {
    task: item.task,
    owner: item.owner,
    deadline: item.deadline,
    full_minutes: parsed.summary // attach full minutes
  }
}));

The Split Out node achieves the same result; the Code node is more flexible.

Step 4: Distribute to Feishu / Email / Notion

Once minutes and action items are generated, distribute them through your team's preferred channels. Three common routes:

① Feishu (HTTP Request to Feishu custom bot webhook)

n8n has no native Feishu node. Use an HTTP Request to call a Feishu custom bot's Incoming Webhook. First, add a custom bot in your Feishu group and copy the webhook URL.

json
// HTTP Request node -> Feishu webhook
// Method: POST
// URL: https://open.feishu.cn/open-apis/bot/v2/hook/xxx
// Headers: Content-Type: application/json
// Body (JSON):
{
  "msg_type": "interactive",
  "card": {
    "header": {
      "title": { "tag": "plain_text", "content": "Meeting Minutes - {{ $json.date }}" }
    },
    "elements": [
      {
        "tag": "markdown",
        "content": "{{ $json.minutes }}"
      }
    ]
  }
}

② Email (Email Send node)

n8n's built-in Email Send node sends via SMTP. Configure SMTP credentials (Gmail, corporate mail, etc.), then reference the LLM output in the recipient, subject, and body fields using expressions.

ParameterValue
From[email protected]
To[email protected] (or extract from attendee list)
SubjectMeeting Minutes - {{ $now.toFormat('yyyy-MM-dd') }}
Email TypeHTML
Message{{ $json.minutes }} (LLM-generated Markdown, convert to HTML with marked)

③ Notion (Notion node for archiving)

n8n's built-in Notion node writes minutes into a Notion database for searchability and tracking. Configure Notion credentials (OAuth or Internal Integration Token), select Create Database Page, specify the Database ID, and map summary and action items to the corresponding properties.

ParameterValue
ResourceDatabase Page
OperationCreate
Database IDYour meeting-minutes database ID
PropertiesTitle: {{ $json.title }}, Date: {{ $json.date }}, Owner: {{ $json.owner }}
Content{{ $json.minutes }} (written to the page body)

Distribution recommendation: push action items to Feishu (@-mention owners for instant reach) + archive full minutes in Notion (searchable, traceable) + email a summary (fallback). Three channels cover "instant alert + long-term archive + passive notification."


Four: Pitfall Quick Reference

Pitfall 1: Poor audio quality, transcription full of errors. Whisper is highly accurate for clean speech, but background noise, far-field microphones, and overlapping voices cause frequent errors. Fix: use a near-field microphone or record directly from the meeting system (no speaker playback into a mic). Pre-process with ffmpeg noise reduction:

bash
# ffmpeg noise reduction (self-hosted n8n can run via Execute Command node)
ffmpeg -i input.mp3 -af "afftdn=nr=10" output.mp3

Pitfall 2: Long audio exceeds Whisper's 25 MB limit. A one-hour mp3 is 15-30 MB; wav is larger. It is easy to hit the ceiling. Fix: split the audio by time (e.g., 20-minute segments) with ffmpeg before uploading, call Whisper per segment, then concatenate the text:

bash
# Split audio by duration (1200 seconds = 20 minutes per segment)
ffmpeg -i long_meeting.mp3 -f segment -segment_time 1200 -c copy chunk_%03d.mp3

On self-hosted n8n, use the Execute Command node to run ffmpeg (per official docs; not available on cloud). Alternatively, pre-process on the upload side.

Pitfall 3: Transcript exceeds LLM token limit. A one-hour meeting yields roughly 8,000-15,000 Chinese characters. GPT-4o's context window handles this, but longer meetings or cheaper models may not. Fix: send Whisper segments in batches to the LLM, generate a summary per batch, then have a final LLM pass merge them. Or use a long-context model (GPT-4o 128K, DeepSeek 64K).

Pitfall 4: Action items extracted incorrectly -- wrong owners or missed items. The hard part of extracting action items from spoken language: "someone should follow up on that" does not name a person. Fix: (1) In the prompt, require "mark owner as TBD if unclear; never guess"; (2) have the LLM output JSON instead of free text for tighter structural constraints; (3) build a meeting culture of explicitly saying "Zhang San, finish X by Friday" -- solve it at the source.

Pitfall 5: Chinese proper nouns, names, and jargon transcribed wrong. Whisper handles common Chinese well but stumbles on internal names, product codenames, and industry terms. Fix: use Whisper's prompt parameter to provide context vocabulary. Place a reference text containing the proper nouns in the prompt -- Whisper uses it to adjust recognition:

json
// Whisper prompt parameter example (provide proper-noun context)
"prompt": "Names and terms that may appear in this meeting: Zhang Wei, Li Na, Project Alpha, Q3 OKR, Feishu Bitable."

Pitfall 6: Speaker diarization. The Whisper API does not natively support speaker diarization -- the transcript is continuous text with no "Speaker A / Speaker B" labels. Fix: (1) Use verbose_json to get timestamped segments and coarsely split by silence gaps; (2) post-process with a third-party diarization service (e.g., pyannote.audio); (3) if you only need minutes (not verbatim transcript), let the LLM infer speakers from context during generation (limited effectiveness, works best for meetings with clear, distinct speakers).


FAQ

Q1: Can I use a transcription service other than OpenAI Whisper? A: Yes. Replace the HTTP Request in Step 2 with another transcription API -- Alibaba Cloud Speech-to-Text, Tencent Cloud ASR, and Azure Speech to Text all offer REST APIs callable via n8n's HTTP Request node with similar parameter structures. For Chinese scenarios, domestic ASR services may handle dialects and proper nouns better. Endpoints and parameters per each provider's docs.

Q2: Can I run this on n8n Cloud without self-hosting? A: Yes. n8n Cloud supports all core nodes, but the Local File Trigger and Execute Command nodes are unavailable (security restriction). Use Webhook triggers and pre-process audio on the upload side instead. Cloud webhooks are publicly reachable out of the box -- no ngrok needed.

Q3: How do I set up the Feishu bot webhook? A: Feishu group -> Settings -> Group Bots -> Add Bot -> select "Custom Bot." Copy the webhook URL (format: https://open.feishu.cn/open-apis/bot/v2/hook/xxx) and paste it into the HTTP Request node's URL field. If signature verification is enabled, add timestamp and sign fields to the request body; the signing algorithm is in the Feishu Open Platform docs.

Q4: How do I handle meetings longer than one hour? A: Two-step approach -- first, split the audio by time (Pitfall 2), call Whisper per segment, and concatenate the full transcript. Then send segments to the LLM for per-segment summaries, with a final LLM pass to merge them. If using a long-context model like GPT-4o, a one-hour meeting's transcript (roughly 10,000-20,000 characters) usually fits within the context window and can be sent in one piece.

Q5: Can action items be auto-created in Jira or Feishu Tasks? A: Yes. After the Code node in Step 3 splits action items into individual items, connect n8n's Jira node or the Feishu Tasks API (via HTTP Request) to create a task per item. You need to configure the corresponding credentials and project ID. Specific node parameters per n8n docs.


Take

The essence of this workflow is not "AI replaces humans at taking minutes" -- it is filling in the "recording -> executable task" chain that should have been automated all along. Whisper solves "dictation," the LLM solves "structuring," and n8n solves "wiring it together to run automatically." All three are cheap: $0.36 for one hour of transcription plus one LLM call is orders of magnitude cheaper than having a person spend two hours on minutes.

The real difficulty is not building the workflow (dragging four nodes on the n8n canvas). It is in two places: audio quality (garbage in, garbage out -- no ASR saves a far-field noise recording) and prompt design (action-item accuracy lives or dies by prompt constraints). Get those two right, and the workflow will consistently produce minutes that are more uniform and less leaky than manual notes.


References

This article is AI-assisted and human-edited. Last updated: 2026-08-06

FAQ

Can I use a transcription service other than OpenAI Whisper?
Yes. Replace the HTTP Request in Step 2 with another transcription API -- Alibaba Cloud Speech-to-Text, Tencent Cloud ASR, and Azure Speech to Text all offer REST APIs callable via n8n's HTTP Request node with similar parameter structures. For Chinese scenarios, domestic ASR services may handle dialects and proper nouns better. Endpoints and parameters per each provider's docs.
Can I run this on n8n Cloud without self-hosting?
Yes. n8n Cloud supports all core nodes, but the Local File Trigger and Execute Command nodes are unavailable (security restriction). Use Webhook triggers and pre-process audio on the upload side instead. Cloud webhooks are publicly reachable out of the box -- no ngrok needed.
How do I set up the Feishu bot webhook?
Feishu group -> Settings -> Group Bots -> Add Bot -> select "Custom Bot." Copy the webhook URL (format: `https://open.feishu.cn/open-apis/bot/v2/hook/xxx`) and paste it into the HTTP Request node's URL field. If signature verification is enabled, add `timestamp` and `sign` fields to the request body; the signing algorithm is in the Feishu Open Platform docs.
How do I handle meetings longer than one hour?
Two-step approach -- first, split the audio by time (Pitfall 2), call Whisper per segment, and concatenate the full transcript. Then send segments to the LLM for per-segment summaries, with a final LLM pass to merge them. If using a long-context model like GPT-4o, a one-hour meeting's transcript (roughly 10,000-20,000 characters) usually fits within the context window and can be sent in one piece.
Can action items be auto-created in Jira or Feishu Tasks?
Yes. After the Code node in Step 3 splits action items into individual items, connect n8n's **Jira** node or the Feishu Tasks API (via HTTP Request) to create a task per item. You need to configure the corresponding credentials and project ID. Specific node parameters per n8n docs. ---

Related