AutomationFlowsData & Sheets › Create Audiobooks from Google Sheets with Qwen3-TTS

Create Audiobooks from Google Sheets with Qwen3-TTS

Original n8n title: Create Long Audiobooks 🔊📚 with Custom Voices Using Qwen3-tts Voice Design

ByDavide Boizza @n3witalia on n8n.io

This workflow automates the creation of audiobooks from structured text data using AI-powered text-to-speech and audio processing services.

Event trigger★★★★☆ complexity20 nodesHTTP RequestGoogle SheetsGoogle Drive
Data & Sheets Trigger: Event Nodes: 20 Complexity: ★★★★☆ Added:

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

This workflow follows the Google Drive → Google Sheets 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
{
  "id": "bZxjBuVF4OptcGFN",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Audiobook with Qwen3-TTS Voice Design",
  "tags": [],
  "nodes": [
    {
      "id": "f440e0c7-fdd2-4a07-8814-ac6fa7102d71",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -720,
        416
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "3eb00552-7e40-4787-9332-990cb70eb012",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -80,
        416
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "29352fb7-0dd7-40db-9e9d-bb898fb9550a",
      "name": "Get status",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        832,
        32
      ],
      "parameters": {
        "url": "=https://queue.fal.run/fal-ai/ffmpeg-api/requests/{{ $('Merge Audios').item.json.request_id }}/status ",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "4453e98c-fe81-4afc-a70c-6aebb43a1746",
      "name": "Wait 30 sec.",
      "type": "n8n-nodes-base.wait",
      "position": [
        640,
        32
      ],
      "parameters": {
        "amount": 30
      },
      "typeVersion": 1.1
    },
    {
      "id": "5dab72a8-326f-4483-a83f-0c68546508fe",
      "name": "Get scripts",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -416,
        416
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupColumn": "Temp URL"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1f4rB-i3cVDzKLi6nv8EMvjjyg9n4rgkOVx28_EI1NBI/edit#gid=0",
          "cachedResultName": "Foglio1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1f4rB-i3cVDzKLi6nv8EMvjjyg9n4rgkOVx28_EI1NBI",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1f4rB-i3cVDzKLi6nv8EMvjjyg9n4rgkOVx28_EI1NBI/edit?usp=drivesdk",
          "cachedResultName": "Audiobooks"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "08e31150-9ab1-4a21-8076-a8321152cf05",
      "name": "Update Temp URL",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        368,
        432
      ],
      "parameters": {
        "columns": {
          "value": {
            "Temp URL": "={{ $json.output }}",
            "To Merge": "x",
            "row_number": "={{ $('Loop Over Items').item.json.row_number }}"
          },
          "schema": [
            {
              "id": "Text",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Text",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Speaker",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Speaker",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Voice Description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Voice Description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Style Instruction",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Style Instruction",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Temp URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Temp URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "To Merge",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "To Merge",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "row_number"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1f4rB-i3cVDzKLi6nv8EMvjjyg9n4rgkOVx28_EI1NBI/edit#gid=0",
          "cachedResultName": "Foglio1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1f4rB-i3cVDzKLi6nv8EMvjjyg9n4rgkOVx28_EI1NBI",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1f4rB-i3cVDzKLi6nv8EMvjjyg9n4rgkOVx28_EI1NBI/edit?usp=drivesdk",
          "cachedResultName": "Audiobooks"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "f239924d-33e2-4ed7-b6a5-e71e7b1450a6",
      "name": "Set AudioUrls Json",
      "type": "n8n-nodes-base.code",
      "position": [
        208,
        32
      ],
      "parameters": {
        "jsCode": "return [\n  {\n    urls: items.map(item => item.json[\"Temp URL\"])\n  }\n];\n\n"
      },
      "typeVersion": 2
    },
    {
      "id": "45fb2780-ac50-419f-b629-ecbb1cab266b",
      "name": "Merge Audios",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        416,
        32
      ],
      "parameters": {
        "url": "https://queue.fal.run/fal-ai/ffmpeg-api/merge-audios",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"audio_urls\": {{ JSON.stringify($json.urls) }}\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "544c385c-9805-4a6d-b894-49634a54b79c",
      "name": "Wait 10 sec.",
      "type": "n8n-nodes-base.wait",
      "position": [
        576,
        432
      ],
      "parameters": {
        "amount": 10
      },
      "typeVersion": 1.1
    },
    {
      "id": "17cd91ad-9287-4350-9abf-ec73ad50f34e",
      "name": "Completed?",
      "type": "n8n-nodes-base.if",
      "position": [
        1008,
        32
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "383d112e-2cc6-4dd4-8985-f09ce0bd1781",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "COMPLETED"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "db353b51-789f-4784-a0b5-0fc8f6c12d13",
      "name": "Get final audio url",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1248,
        16
      ],
      "parameters": {
        "url": "=https://queue.fal.run/fal-ai/ffmpeg-api/requests/{{ $json.request_id }}",
        "options": {},
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "45e5f4d1-2e49-4ea9-9f52-3edec44d9cd2",
      "name": "Get File",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1488,
        16
      ],
      "parameters": {
        "url": "={{$json.audio.url}}",
        "options": {}
      },
      "typeVersion": 4.3
    },
    {
      "id": "889c8e2c-9a08-49b9-a820-1bfd194e8934",
      "name": "Upload Audiobook",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1696,
        16
      ],
      "parameters": {
        "name": "={{ $now.format('yyyyLLddHHmmss') }}-{{ $json.audio.file_name }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "1aHRwLWyrqfzoVC8HoB-YMrBvQ4tLC-NZ",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1aHRwLWyrqfzoVC8HoB-YMrBvQ4tLC-NZ",
          "cachedResultName": "Fal.run"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "888104ba-8bce-432c-9384-29fab163c784",
      "name": "Voice Design",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        160,
        432
      ],
      "parameters": {
        "url": "https://api.replicate.com/v1/models/qwen/qwen3-tts/predictions",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"input\": {\n    \"mode\": \"voice_design\",\n    \"text\": \"{{ $json.Text }}\",\n    \"language\": \"auto\",\n     \"speaker\": \"{{ $json.Speaker }}\",\n    \"voice_description\": \"{{ $json['Voice Description'] }}\",\n    \"style_instruction\":\"{{ $json['Style Instruction'] }}\"\n  }\n} ",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Prefer",
              "value": "wait"
            }
          ]
        }
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "d4038999-92ea-414d-9963-59435a6c955a",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -544,
        -432
      ],
      "parameters": {
        "width": 608,
        "height": 704,
        "content": "## Create Long Audiobooks with Custom Voices using Qwen3-TTS Voice Design\nThis workflow automates the **creation of audiobooks from structured text data** using AI-powered text-to-speech and audio processing services.\n\n[Click here to listen](https://iframe.mediadelivery.net/play/580928/5e137292-5d19-4745-9d79-aeb3cc5f5a23) the result of my example.\n\n### **How it works**\n\nThis workflow automates end-to-end audiobook production using AI-powered text-to-speech and audio processing. It starts by reading structured script data from Google Sheets, including text content, speaker details, voice descriptions, and style instructions. Each row is processed in batches to safely handle API limits, sending the text to the Qwen3-TTS model on Replicate to generate individual audio segments with customized voice design. Generated audio URLs are written back to the spreadsheet for tracking. Once enough segments are available, the workflow triggers an external FFmpeg API to merge them into a single audiobook file. Status polling and wait nodes ensure asynchronous, fault-tolerant execution. After merging is complete, the final audio file is retrieved and uploaded to Google Drive with a timestamped filename, ready for distribution or review.\n\n### **Setup steps**\n\nBegin by configuring the Google Sheets node to connect to your script document, ensuring required columns such as Text, Speaker, Voice Description, Style Instruction, Temp URL, and To Merge are present. Next, set up API credentials in n8n for Replicate (Qwen3-TTS), Fal.run (FFmpeg audio merging), and Google Drive OAuth2 for storage. Populate the spreadsheet with voice descriptions and style instructions compatible with the Qwen3-TTS model. Verify the target Google Drive folder ID in the upload node to control where the final audiobook is stored. Once configuration is complete, manually trigger the workflow to process script rows, generate audio segments, merge them, and upload the finished audiobook automatically.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "34a2c76c-1b7c-4465-be6f-a5619c79829a",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -544,
        288
      ],
      "parameters": {
        "color": 7,
        "width": 384,
        "height": 384,
        "content": "## STEP 1 - Clone the Sheet\n**Double click** to edit me. [Clone this Sheet](https://docs.google.com/spreadsheets/d/1f4rB-i3cVDzKLi6nv8EMvjjyg9n4rgkOVx28_EI1NBI/edit?usp=sharing) and fill \"Text\", \"Speaker\", \"Voice Description\" and \"Style Instruction\""
      },
      "typeVersion": 1
    },
    {
      "id": "3d67b3ef-a0a2-4081-9053-7e57a54a6886",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        288
      ],
      "parameters": {
        "color": 7,
        "width": 688,
        "height": 384,
        "content": "## STEP 2 - Clone the Sheet\nConfigure [Replicate API](https://replicate.com) credentials for Qwen3-TTS voice synthesis. Ensure your spreadsheet contains appropriate voice descriptions and style instructions compatible with the Qwen3-TTS model's requirements"
      },
      "typeVersion": 1
    },
    {
      "id": "1b7ec519-99b7-459b-a864-39d534a5cec7",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 1312,
        "height": 400,
        "content": "## STEP 3 - Merge audios\nSet up Fal.run API credentials for FFmpeg audio merging operations\n\nIMPORTANT: Merge API limit: 5 audios. To overcome this limit, you can use a new Loop and a Code node to merge 5 audios at once and then merge them together. This allows you to potentially create very long audiobooks.\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "9784467e-8888-4011-b022-429fede1b98b",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1424,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 400,
        "content": "## STEP 4 - Google Drive\nUpload the final file on Google Drive\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4fbe2ac6-8ef6-409e-9475-20f32311f5ab",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        -896
      ],
      "parameters": {
        "color": 7,
        "width": 736,
        "height": 736,
        "content": "## MY NEW YOUTUBE CHANNEL\n\ud83d\udc49 [Subscribe to my new **YouTube channel**](https://youtube.com/@n3witalia). Here I\u2019ll share videos and Shorts with practical tutorials and **FREE templates for n8n**.\n\n[![image](https://n3wstorage.b-cdn.net/n3witalia/youtube-n8n-cover.jpg)](https://youtube.com/@n3witalia)"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "90072594-6760-4cb7-b287-5b37e8240bbf",
  "connections": {
    "Get File": {
      "main": [
        [
          {
            "node": "Upload Audiobook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Completed?": {
      "main": [
        [
          {
            "node": "Get final audio url",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait 30 sec.",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get status": {
      "main": [
        [
          {
            "node": "Completed?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get scripts": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Audios": {
      "main": [
        [
          {
            "node": "Wait 30 sec.",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Voice Design": {
      "main": [
        [
          {
            "node": "Update Temp URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 10 sec.": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 30 sec.": {
      "main": [
        [
          {
            "node": "Get status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Set AudioUrls Json",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Voice Design",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Temp URL": {
      "main": [
        [
          {
            "node": "Wait 10 sec.",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set AudioUrls Json": {
      "main": [
        [
          {
            "node": "Merge Audios",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get final audio url": {
      "main": [
        [
          {
            "node": "Get File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Get scripts",
            "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 automates the creation of audiobooks from structured text data using AI-powered text-to-speech and audio processing services.

Source: https://n8n.io/workflows/13030/ — 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

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
Data & Sheets

The workflow automates the process of gathering extensive keyword data for a "Main Keyword." It starts by reading initial parameters from a Google Sheets template, creates a new dedicated Google Sheet

Google Sheets, Google Drive, HTTP Request
Data & Sheets

🔥 March Sale – n8n Community Members Get ideoGener8r for Just $27! (Reg. $47) Use Coupon Code: (Valid until 3/31/2025 for n8n community members)

HTTP Request, Google Drive, Google Sheets
Data & Sheets

📄 Documentation: Notion Guide

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

Overview

Google Sheets, Google Drive, HTTP Request