AutomationFlowsData & Sheets › Transcribe Google Drive Audio to Markdown with Gladia and Google Sheets

Transcribe Google Drive Audio to Markdown with Gladia and Google Sheets

ByKevin Yu @exekyute on n8n.io

This workflow watches a Google Drive folder for new audio files, sends them to Gladia for asynchronous transcription, saves the resulting Markdown transcript back to Google Drive, and appends a success or failure record (with a link and details) to a Google Sheets log. Triggers…

Event trigger★★★★☆ complexity18 nodesGoogle Drive TriggerGoogle DriveHTTP RequestGoogle Sheets
Data & Sheets Trigger: Event Nodes: 18 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #16955 — we link there as the canonical source.

This workflow follows the Google Drive → Google Drive Trigger recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "name": "Transcribe new audio files from Google Drive using Gladia and Google Sheets",
  "tags": [],
  "nodes": [
    {
      "id": "3f6d2b7d-c7e9-4543-9b9a-cfa7b2d2baa7",
      "name": "Google Drive Audio Trigger",
      "type": "n8n-nodes-base.googleDriveTrigger",
      "position": [
        -16,
        704
      ],
      "parameters": {
        "event": "fileCreated",
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "mode": "id",
          "value": "REPLACE_WITH_SOURCE_FOLDER_ID"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "72166108-75e5-4b98-90af-026316c77a2a",
      "name": "Prepare Config Values",
      "type": "n8n-nodes-base.set",
      "position": [
        208,
        704
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "c1",
              "name": "wait_seconds",
              "type": "number",
              "value": 15
            },
            {
              "id": "c2",
              "name": "max_attempts",
              "type": "number",
              "value": 40
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "25b2175b-fcfb-4918-ab1c-05642a0be3cd",
      "name": "Download File from Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        432,
        704
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Google Drive Audio Trigger').item.json.id }}"
        },
        "options": {
          "binaryPropertyName": "data"
        },
        "resource": "file",
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "ba1499c8-97bf-4054-af90-ca9785aa2aeb",
      "name": "Upload Audio to Gladia",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "maxTries": 3,
      "position": [
        688,
        704
      ],
      "parameters": {
        "url": "https://api.gladia.io/v2/upload",
        "method": "POST",
        "options": {
          "timeout": 120000
        },
        "sendBody": true,
        "contentType": "multipart-form-data",
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "audio",
              "parameterType": "formBinaryData",
              "inputDataFieldName": "data"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.4,
      "waitBetweenTries": 5000
    },
    {
      "id": "285cbe8b-c58e-4fa2-a8d2-292152acaaba",
      "name": "Start Transcription Job",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "maxTries": 3,
      "position": [
        928,
        688
      ],
      "parameters": {
        "url": "https://api.gladia.io/v2/pre-recorded",
        "method": "POST",
        "options": {
          "timeout": 30000
        },
        "jsonBody": "={{ { \"audio_url\": $json.audio_url } }}",
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.4,
      "waitBetweenTries": 5000
    },
    {
      "id": "9d170652-3c50-4cbe-97f0-df9e34835907",
      "name": "Wait for Processing",
      "type": "n8n-nodes-base.wait",
      "position": [
        1200,
        544
      ],
      "parameters": {
        "unit": "seconds",
        "amount": "={{ $('Prepare Config Values').item.json.wait_seconds }}",
        "resume": "timeInterval"
      },
      "typeVersion": 1.1
    },
    {
      "id": "7279d3f5-ad94-4fe9-ad0e-955a2809eff7",
      "name": "Get Transcription Result",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "maxTries": 3,
      "position": [
        1360,
        544
      ],
      "parameters": {
        "url": "=https://api.gladia.io/v2/pre-recorded/{{ $('Start Transcription Job').item.json.id }}",
        "method": "GET",
        "options": {
          "timeout": 30000
        },
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.4,
      "waitBetweenTries": 5000
    },
    {
      "id": "7499c9d7-66d7-4ac7-992d-1e7e7099dacf",
      "name": "Route by Status",
      "type": "n8n-nodes-base.switch",
      "position": [
        1568,
        512
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.status }}",
                    "rightValue": "done"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "or",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.status }}",
                    "rightValue": "error"
                  },
                  {
                    "operator": {
                      "type": "number",
                      "operation": "gte"
                    },
                    "leftValue": "={{ $runIndex }}",
                    "rightValue": "={{ $('Prepare Config Values').item.json.max_attempts }}"
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra",
          "renameFallbackOutput": "Still Processing"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "9447b3e3-71f2-4f7a-9471-02e530d36834",
      "name": "Build Transcript File",
      "type": "n8n-nodes-base.code",
      "position": [
        1824,
        496
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const result = $json.result || {};\nconst transcription = result.transcription || {};\nconst fullTranscript = (transcription.full_transcript || '').trim();\nconst utterances = Array.isArray(transcription.utterances) ? transcription.utterances : [];\nconst duration = result.metadata?.audio_duration ?? $json.file?.audio_duration ?? $('Upload Audio to Gladia').item.json.audio_metadata?.audio_duration ?? null;\nconst sourceName = $('Google Drive Audio Trigger').item.json.name || 'audio-file';\nconst dot = sourceName.lastIndexOf('.');\nconst baseName = dot > 0 ? sourceName.slice(0, dot) : sourceName;\nconst stamp = $now.toFormat('yyyyLLdd-HHmmss');\nconst fileName = baseName + '-transcript-' + stamp + '.md';\nconst NL = String.fromCharCode(10);\nconst lines = [];\nlines.push('# Transcript: ' + sourceName);\nlines.push('');\nlines.push('- Source file: ' + sourceName);\nlines.push('- Duration: ' + (duration != null ? duration + ' seconds' : 'unknown'));\nlines.push('- Transcribed: ' + $now.toISO());\nlines.push('');\nlines.push('---');\nlines.push('');\nif (utterances.length) {\n  for (const u of utterances) {\n    const who = (u.speaker !== undefined && u.speaker !== null) ? ('Speaker ' + u.speaker) : 'Speaker';\n    lines.push('**' + who + ':** ' + (u.text || '').trim());\n    lines.push('');\n  }\n} else {\n  lines.push(fullTranscript || '(No transcript text was returned.)');\n}\nconst body = lines.join(NL);\nconst preview = fullTranscript.slice(0, 180);\nreturn { json: { source_file: sourceName, audio_duration: duration, file_name: fileName, preview: preview, status: 'Transcribed' }, binary: { data: { data: Buffer.from(body, 'utf-8').toString('base64'), mimeType: 'text/markdown', fileName: fileName, fileExtension: 'md' } } };"
      },
      "typeVersion": 2
    },
    {
      "id": "691fccab-9fd5-4ba6-8618-8e214e2fb2a1",
      "name": "Save Transcript to Drive",
      "type": "n8n-nodes-base.googleDrive",
      "onError": "continueErrorOutput",
      "position": [
        2016,
        496
      ],
      "parameters": {
        "name": "={{ $json.file_name }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive",
          "cachedResultName": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "REPLACE_WITH_TRANSCRIPTS_FOLDER_ID"
        },
        "resource": "file",
        "operation": "upload",
        "inputDataFieldName": "data"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "f1224ff7-e5cf-41a9-9684-5ce4026642f5",
      "name": "Log Transcript in Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2208,
        480
      ],
      "parameters": {
        "columns": {
          "value": {
            "Detail": "={{ $('Build Transcript File').item.json.preview }}",
            "Status": "Transcribed",
            "Timestamp": "={{ $now.toISO() }}",
            "Source File": "={{ $('Google Drive Audio Trigger').item.json.name }}",
            "Duration (s)": "={{ $('Build Transcript File').item.json.audio_duration }}",
            "Transcript Link": "={{ $json.webViewLink || 'https://drive.google.com/file/d/' + $json.id + '/view' }}"
          },
          "schema": [
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Source File",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Source File",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Duration (s)",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Duration (s)",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Transcript Link",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Transcript Link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Detail",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Detail",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "REPLACE_WITH_SHEET_TAB",
          "cachedResultName": "Log"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "REPLACE_WITH_YOUR_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "7f6f7a25-e326-448e-804e-26d3b22dea56",
      "name": "Log Failure in Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2144,
        864
      ],
      "parameters": {
        "columns": {
          "value": {
            "Detail": "={{ $json.error?.message || ($json.status ? ('Gladia status: ' + $json.status) : 'Transcription failed or timed out. Check the execution log.') }}",
            "Status": "Failed",
            "Timestamp": "={{ $now.toISO() }}",
            "Source File": "={{ $('Google Drive Audio Trigger').first().json.name }}",
            "Duration (s)": "",
            "Transcript Link": ""
          },
          "schema": [
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Source File",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Source File",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Duration (s)",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Duration (s)",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Transcript Link",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Transcript Link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Detail",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Detail",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "REPLACE_WITH_SHEET_TAB",
          "cachedResultName": "Log"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "REPLACE_WITH_YOUR_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "5f71244f-9393-4b18-8c2d-640457307d09",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        -192
      ],
      "parameters": {
        "width": 1232,
        "height": 532,
        "content": "## Transcribe new audio files from Google Drive using Gladia and Google Sheets\n\n### How it works\n\n1. A Google Drive trigger fires when a new audio or video file lands in a watched folder.\n2. The file is downloaded and sent to Gladia, which transcribes it asynchronously.\n3. The workflow polls Gladia until the transcript is ready, then saves it as a Markdown file in a Drive folder.\n4. Every run is logged to a Google Sheet, and failures are logged with a reason so nothing is lost silently.\n\n### Setup steps\n\n- [ ] Create a Header Auth credential named Gladia with header name x-gladia-key and your Gladia API key, then select it on the three Gladia HTTP nodes.\n- [ ] Set the watched folder on the trigger and the Transcripts folder on Save Transcript to Drive.\n- [ ] Pick the log spreadsheet and tab on both Sheets nodes.\n- [ ] Adjust wait_seconds and max_attempts in Prepare Config Values if your files run long.\n\n### Customization\n\nPoint the trigger at any Drive folder, change the transcript layout in Build Transcript File, or add a Slack node after the log to get a ping when a transcript is ready."
      },
      "typeVersion": 1
    },
    {
      "id": "2e3aa313-7621-4a57-83c7-7afde87e3032",
      "name": "Group Watch And Download",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        544
      ],
      "parameters": {
        "color": 7,
        "width": 668,
        "height": 384,
        "content": "## Watch and download the file\n\nA new file in the Drive folder triggers the run, config values are prepared, then the file is downloaded to binary."
      },
      "typeVersion": 1
    },
    {
      "id": "28504a13-cd04-40b8-bb3b-41b6f0451ae3",
      "name": "Group Send To Gladia",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        624,
        544
      ],
      "parameters": {
        "color": 7,
        "width": 472,
        "height": 368,
        "content": "## Send audio to Gladia\n\nUpload the file to Gladia, then start an asynchronous transcription job."
      },
      "typeVersion": 1
    },
    {
      "id": "2380a42a-a9ce-4834-b6fb-ee0d0b3a542b",
      "name": "Group Poll For Result",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1120,
        384
      ],
      "parameters": {
        "color": 7,
        "width": 628,
        "height": 416,
        "content": "## Poll until transcription is done\n\nWait, fetch the result, and route by status. Loop back until Gladia returns done or the attempt limit is reached."
      },
      "typeVersion": 1
    },
    {
      "id": "dfe9c1f2-3cab-4721-bfce-b8e3c6d4da03",
      "name": "Group Save And Log",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1776,
        352
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 308,
        "content": "## Save transcript and log\n\nBuild a Markdown transcript, save it to Drive, and append a row to the log sheet."
      },
      "typeVersion": 1
    },
    {
      "id": "fb183416-6279-4697-acd1-48162079ba8b",
      "name": "Group Handle Failures",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2032,
        688
      ],
      "parameters": {
        "color": 7,
        "width": 340,
        "height": 344,
        "content": "## Handle failures\n\nAny API error or a timeout writes a Failed row with a reason, so nothing fails silently."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "Route by Status": {
      "main": [
        [
          {
            "node": "Build Transcript File",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log Failure in Sheets",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait for Processing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Processing": {
      "main": [
        [
          {
            "node": "Get Transcription Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Transcript File": {
      "main": [
        [
          {
            "node": "Save Transcript to Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Config Values": {
      "main": [
        [
          {
            "node": "Download File from Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Audio to Gladia": {
      "main": [
        [
          {
            "node": "Start Transcription Job",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log Failure in Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start Transcription Job": {
      "main": [
        [
          {
            "node": "Wait for Processing",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log Failure in Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download File from Drive": {
      "main": [
        [
          {
            "node": "Upload Audio to Gladia",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Transcription Result": {
      "main": [
        [
          {
            "node": "Route by Status",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log Failure in Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Transcript to Drive": {
      "main": [
        [
          {
            "node": "Log Transcript in Sheets",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log Failure in Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Drive Audio Trigger": {
      "main": [
        [
          {
            "node": "Prepare Config Values",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow watches a Google Drive folder for new audio files, sends them to Gladia for asynchronous transcription, saves the resulting Markdown transcript back to Google Drive, and appends a success or failure record (with a link and details) to a Google Sheets log. Triggers…

Source: https://n8n.io/workflows/16955/ — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Data & Sheets

Automatically process invoices and receipts using Gemini OCR, extracting data directly into Google Sheets from multiple sources including Google Drive, Gmail, and Telegram. This powerful workflow ensu

HTTP Request, Google Sheets, Google Drive +3
Data & Sheets

OCR receipts from Google Drive. Uses httpRequest, googleDriveTrigger, googleDrive, googleSheets. Event-driven trigger; 10 nodes.

HTTP Request, Google Drive Trigger, Google Drive +1
Data & Sheets

This workflow allows you to recognize a folder with receipts or invoices (make sure your files are in .pdf, .png, or .jpg format). The workflow can be triggered via the "Test workflow" button, and it

HTTP Request, Google Drive Trigger, Google Drive +1
Data & Sheets

This workflow is perfect for operations teams, accountants, e-commerce businesses, or finance managers who regularly process digital invoices and need to automate data extraction and record-keeping.

Google Drive Trigger, Google Drive, HTTP Request +1
Data & Sheets

PCN. Uses googleSheets, httpRequest, @n-octo-n/n8n-nodes-json-database, itemLists. Event-driven trigger; 60 nodes.

Google Sheets, HTTP Request, @N Octo N/N8N Nodes Json Database +3