For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Primary navigation

Meeting minutes

Create an automated meeting minutes generator with speech-to-text and a GPT model.

In this tutorial, you’ll build an automated meeting minutes generator. The application transcribes a meeting recording, summarizes the discussion, extracts key points and action items, analyzes sentiment, and saves the result as a Word document.

Getting started

This tutorial assumes familiarity with one of the supported languages and an OpenAI API key. You can use the short smoke-test audio file or your own recording of up to 25 MB.

Install the OpenAI SDK and a DOCX library for your language:

Transcribing audio

Audio Waveform created by DALL·E

The first step is to pass the meeting recording to the /v1/audio API. The current file transcription model converts spoken language into written text. To start, omit the optional

prompt

and

temperature

parameters and use their default values.

Download sample audio


Save the downloaded file as meeting.wav in the directory from which you run the example, or replace meeting.wav with the path to your recording. The short downloadable clip verifies the workflow; use an actual meeting recording of up to 25 MB to generate useful summaries and action items.

Define a helper that opens the recording and sends the file contents to gpt-transcribe:

import fs from "node:fs";

import { Document, HeadingLevel, Packer, Paragraph, TextRun } from "docx";
import OpenAI from "openai";

const openai = new OpenAI();

async function transcribeAudio(audioFilePath) {
  const transcription = await openai.audio.transcriptions.create({
    file: fs.createReadStream(audioFilePath),
    model: "gpt-transcribe",
  });
  return transcription.text;
}

The helper accepts a local audio path, opens the file with the language’s standard file API, and passes the file contents to the transcription model. The transcription endpoint needs the audio bytes, not a local path or remote URL. If your server stores recordings elsewhere, download or stream the recording into the request before creating the transcription.

Summarizing and analyzing the transcript with a GPT model

Pass the transcript to a GPT model through the Chat Completions API. This tutorial demonstrates the still-supported Chat Completions path for existing integrations. For new projects, use the Responses API and start with gpt-6-astra. The snippets below use a tested model to generate a summary, extract key points and action items, and analyze sentiment.

This tutorial uses a separate model call for each task. You can combine the instructions into one request to reduce calls, but separate prompts make each result easier to tune.

Define the shared helper that sends the transcript and task-specific instructions to the model:

async function complete(transcription, instructions) {
  const response = await openai.chat.completions.create({
    model: "gpt-5.5",
    messages: [
      { role: "system", content: instructions },
      { role: "user", content: transcription },
    ],
  });
  return response.choices[0].message.content ?? "";
}

Define an orchestration helper that returns the four sections of the meeting minutes:

async function buildMeetingMinutes(transcription) {
  return {
    "Abstract summary": await extractAbstractSummary(transcription),
    "Key points": await extractKeyPoints(transcription),
    "Action items": await extractActionItems(transcription),
    Sentiment: await analyzeSentiment(transcription),
  };
}

The helper passes the transcript to four focused helpers: one each for the summary, key points, action items, and sentiment. Add another helper and output section if your application needs more analysis.

Here is how each of these functions works:

Summary extraction

The summary helper asks the model for one concise paragraph that preserves important decisions and context while omitting tangents. The system message controls this behavior. For more ways to shape the result, see the prompt engineering guide.

async function extractAbstractSummary(transcription) {
  return complete(
    transcription,
    "Summarize the meeting transcript in one concise paragraph. Keep the most important decisions and context, and omit tangents."
  );
}

Key points extraction

The key-points helper lists the important ideas, findings, and topics discussed in the meeting. Add relevant project or company context to the system message when it helps the model identify what matters to your audience.

async function extractKeyPoints(transcription) {
  return complete(
    transcription,
    "List the most important ideas, findings, and topics from the meeting. Use concise bullet points."
  );
}

Action item extraction

The action-items helper identifies tasks and follow-ups, including owners and deadlines when the transcript provides them. To create and assign tasks in another system, connect this step to function calling.

async function extractActionItems(transcription) {
  return complete(
    transcription,
    "List every task or follow-up agreed to in the meeting. Include the owner and deadline when the transcript provides them."
  );
}

Sentiment analysis

The sentiment helper classifies the discussion as positive, negative, or neutral and explains the assessment. For simpler tasks, try gpt-5.6-terra to see whether it meets your quality target with lower cost and latency.

async function analyzeSentiment(transcription) {
  return complete(
    transcription,
    "Describe the meeting's overall sentiment as positive, negative, or neutral, and briefly explain the assessment."
  );
}

Exporting meeting minutes

Audio Waveform created by DALL·E

Save the meeting minutes in a readable format that you can distribute. Microsoft Word is a common choice for this kind of report. The examples use a DOCX library suited to each language. In an end-to-end application, you could send the result in an email or write it to another system instead.


Define a helper that writes each result section to a Word document:

async function saveAsDocx(minutes, filename) {
  const children = Object.entries(minutes).flatMap(([heading, content]) => [
    new Paragraph({ text: heading, heading: HeadingLevel.HEADING_1 }),
    new Paragraph({
      children: content
        .split(/\r\n?|\n/)
        .flatMap((line, index) => [
          ...(index > 0 ? [new TextRun({ break: 1 })] : []),
          new TextRun(line),
        ]),
    }),
  ]);
  const document = new Document({ sections: [{ children }] });
  await fs.promises.writeFile(filename, await Packer.toBuffer(document));
}

The helper receives the generated sections and an output filename, adds a heading and paragraph for each section, and saves the document to the current working directory.

Finally, combine the steps to generate meeting minutes from an audio file:

const transcription = await transcribeAudio("meeting.wav");
const minutes = await buildMeetingMinutes(transcription);
console.log(minutes);
await saveAsDocx(minutes, "meeting_minutes.docx");

This code resolves meeting.wav from the process working directory, generates and prints the meeting minutes, and saves them as meeting_minutes.docx.

Now that you have a basic meeting minutes workflow, tune the prompts with prompt engineering or build an end-to-end system with function calling.