{
  "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
          }
        ]
      ]
    }
  }
}