8
n8n 中文网amn8n.com

从脚本生成AI语音并上传到Google云端硬盘

高级

这是一个Content Creation, Multimodal AI领域的自动化工作流,包含 20 个节点。主要使用 Set, Code, Filter, GoogleDrive, HttpRequest 等节点。 使用Gemini TTS从脚本生成AI语音并上传到Google云端硬盘

前置要求
  • Google Drive API 凭证
  • 可能需要目标 API 的认证凭证
  • Google Sheets API 凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "sJP7yYyMUuFkBxhP",
  "meta": {
    "instanceId": "8506a10572bce7322328454a2dc9c1df792a29ed1e0b40db7be90cf055b03a5a",
    "templateCredsSetupCompleted": true
  },
  "name": "从脚本生成AI语音并上传到Google Drive",
  "tags": [],
  "nodes": [
    {
      "id": "b77d0479-251b-4dde-a8db-70dd5c1dcde9",
      "name": "当点击\"执行工作流\"时",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -656,
        0
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "420b8504-2cc1-4947-b53d-29fd0ae53d4b",
      "name": "转换为文件",
      "type": "n8n-nodes-base.convertToFile",
      "position": [
        592,
        32
      ],
      "parameters": {
        "options": {
          "fileName": "={{ $('Code1').item.json.safeFilename }}.pcm",
          "mimeType": "={{ $json.candidates[0].content.parts[0].inlineData.mimeType }}"
        },
        "operation": "toBinary",
        "sourceProperty": "candidates[0].content.parts[0].inlineData.data"
      },
      "typeVersion": 1.1
    },
    {
      "id": "3905f225-4b9d-4e47-bda4-b08002ed635b",
      "name": "从磁盘读取/写入文件",
      "type": "n8n-nodes-base.readWriteFile",
      "position": [
        784,
        32
      ],
      "parameters": {
        "options": {},
        "fileName": "=/Users/INSERT_YOUR_LOCAL_STORAGE_HERE/{{ $('Code1').item.json.safeFilename }}.pcm",
        "operation": "write"
      },
      "typeVersion": 1
    },
    {
      "id": "88b59cbf-7949-4fb4-84cb-d36a866bbf43",
      "name": "代码1",
      "type": "n8n-nodes-base.code",
      "position": [
        176,
        32
      ],
      "parameters": {
        "jsCode": "// Get all the items coming into this node\nconst items = $items();\n\n// Loop through each item (this code works even if there's only one)\nfor (const item of items) {\n  \n  // 1. Get the original script text from the 'full_script_text' field.\n  const originalScript = item.json.full_script_text;\n  \n  // Get the row number to make the filename unique\n  const rowNumber = item.json.row_number;\n\n  // 2. Create the clean filename\n  //    - Convert to lowercase for consistency\n  //    - Replace any character that is NOT a letter or number with an underscore\n  //    - Shorten it to the first 60 characters to prevent it from being too long\n  const sanitizedScriptPart = originalScript\n    .toLowerCase()\n    .replace(/[^a-z0-9]/g, '_') \n    .substring(0, 60);\n\n  // 3. Combine the row number and the sanitized text to create a final, unique filename\n  const safeFilename = `${rowNumber}_${sanitizedScriptPart}`;\n\n  // 4. Add the new, safe filename back to the data\n  item.json.safeFilename = safeFilename;\n}\n\n// Return the modified data to the next node\nreturn items;"
      },
      "typeVersion": 2
    },
    {
      "id": "383050a4-5d1a-4f80-9ac3-8ab99dd6c121",
      "name": "遍历项目",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -64,
        0
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "8f194775-656e-4687-afbb-507226a8fdb3",
      "name": "过滤器",
      "type": "n8n-nodes-base.filter",
      "position": [
        -272,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "51e34efc-ba22-404f-835a-4324f403bcbe",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json['Voice Generated?'] }}",
              "rightValue": "Yes"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "be5453fc-c5e8-4591-b7d9-cd5a35b9582a",
      "name": "获取视频脚本",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -464,
        0
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 539540410,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tFC1EC863ZwJB0GffCM9BzU5kYo1wITwFoESZ130oP4/edit#gid=539540410",
          "cachedResultName": "Text Overlays"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1tFC1EC863ZwJB0GffCM9BzU5kYo1wITwFoESZ130oP4/edit?gid=539540410#gid=539540410"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "0XPHdQQ1kHd7hjJ5",
          "name": "thamjiangjun@gmail.com google sheet"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "1decede0-d000-4a68-838c-ce708fc49b55",
      "name": "HTTP请求生成语音",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        384,
        32
      ],
      "parameters": {
        "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-tts:generateContent\n",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"contents\": [\n    {\n      \"parts\": [\n        {\n          \"text\": \"Say this script in a neutral <INSERT YOUR DESIRED ACCENT HERE> professional accent at a face pace enthusiastically: {{ $json.full_script_text }}\"\n        }\n      ]\n    }\n  ],\n  \"generationConfig\": {\n    \"responseModalities\": [\n      \"AUDIO\"\n    ],\n    \"speechConfig\": {\n      \"voiceConfig\": {\n        \"prebuiltVoiceConfig\": {\n          \"voiceName\": \"Kore\"\n        }\n      }\n    }\n  },\n  \"model\": \"gemini-2.5-flash-preview-tts\"\n}",
        "sendBody": true,
        "sendQuery": true,
        "specifyBody": "json",
        "queryParameters": {
          "parameters": [
            {
              "name": "key",
              "value": "INSERT YOUR API KEY HERE"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "3323cc73-9026-48bd-b951-763101a44280",
      "name": "提取文件名",
      "type": "n8n-nodes-base.set",
      "position": [
        960,
        32
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "fe124702-e115-4be8-b5da-df6d01e1ddbe",
              "name": "fileName",
              "type": "string",
              "value": "={{ $json.fileName }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "648b7a61-af32-43d9-97f1-2189560cc47e",
      "name": "运行本地FFMPEG代码更改文件格式",
      "type": "n8n-nodes-base.code",
      "position": [
        1152,
        32
      ],
      "parameters": {
        "jsCode": "// Get the input data from the previous node\nconst inputData = $input.all()[0].json;\n\n// Use the EXISTING PCM file path from the input\nconst pcmFilePath = inputData.fileName; // \"/Users/jjtham/3_dream_of_a_marriage_free_from_painful_surprises__imagine_a_f.pcm\"\n\n// Generate the WAV output path by replacing .pcm with .wav\nconst wavFilePath = pcmFilePath.replace('.pcm', '.wav');\n\n// Build the ffmpeg command (quotes handle spaces in paths)\nconst ffmpegCommand = `ffmpeg -y -f s16le -ar 24000 -ac 1 -i \"${pcmFilePath}\" \"${wavFilePath}\"`;\n\nreturn {\n  json: {\n    pcmPath: pcmFilePath,\n    wavPath: wavFilePath,\n    command: ffmpegCommand\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "da306259-3612-41bd-99b0-91408c63e400",
      "name": "运行FFMPEG代码",
      "type": "n8n-nodes-base.executeCommand",
      "position": [
        1328,
        32
      ],
      "parameters": {
        "command": "={{ $json.command }}"
      },
      "typeVersion": 1
    },
    {
      "id": "2fabed55-983e-4420-b16c-f822697cadfa",
      "name": "将文件输出写入磁盘",
      "type": "n8n-nodes-base.readWriteFile",
      "position": [
        1520,
        32
      ],
      "parameters": {
        "options": {},
        "fileSelector": "={{ $('Running FFMPEG Local Code To Change Format Of File').item.json.wavPath }}"
      },
      "typeVersion": 1
    },
    {
      "id": "bbc88d97-1edb-4430-8749-2df5594c9dcd",
      "name": "上传Wav文件",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1712,
        32
      ],
      "parameters": {
        "name": "={{ $('Code1').item.json.safeFilename }}.wav",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive",
          "cachedResultUrl": "https://drive.google.com/drive/my-drive",
          "cachedResultName": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "root",
          "cachedResultUrl": "https://drive.google.com/drive",
          "cachedResultName": "/ (Root folder)"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "0cagYS3ULKYU3G1N",
          "name": "Quiverx Google Drive Account"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "d38711cb-420b-4a70-8ec5-b6df27207caf",
      "name": "将文件的Google Drive链接上传到Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1920,
        32
      ],
      "parameters": {
        "columns": {
          "value": {
            "Voice Link": "={{ $json.webViewLink }}",
            "Google Drive ID": "={{ $json.id }}",
            "Voice Generated?": "Yes",
            "full_script_text": "={{ $('Loop Over Items').item.json.full_script_text }}",
            "Computer File Name": "={{ $('Writing File Output Onto Disk').item.json.fileName }}",
            "Google Drive Download Link": "={{ $json.webContentLink }}"
          },
          "schema": [
            {
              "id": "script_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "script_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "psychological_angle",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "psychological_angle",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "full_script_text",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "full_script_text",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "script_breakdown",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "script_breakdown",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Bucket",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Bucket",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "strategyPillar",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "strategyPillar",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "psychologicalAngle",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "psychologicalAngle",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Voice Generated?",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Voice Generated?",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Voice Link",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Voice Link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Google Drive ID",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Google Drive ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Google Drive Download Link",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Google Drive Download Link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "File Location",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "File Location",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Computer File Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Computer File Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Editing Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Editing Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "full_script_text"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 539540410,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tFC1EC863ZwJB0GffCM9BzU5kYo1wITwFoESZ130oP4/edit#gid=539540410",
          "cachedResultName": "Text Overlays"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1tFC1EC863ZwJB0GffCM9BzU5kYo1wITwFoESZ130oP4/edit?gid=539540410#gid=539540410"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "0XPHdQQ1kHd7hjJ5",
          "name": "thamjiangjun@gmail.com google sheet"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "39ec1f9e-a5be-4e9c-b1cf-aa2f958694d7",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1408,
        -224
      ],
      "parameters": {
        "width": 704,
        "height": 1120,
        "content": "## 从脚本生成AI语音并上传到Google Drive"
      },
      "typeVersion": 1
    },
    {
      "id": "1cc5dc7d-55c4-4d0a-b356-a8458169dd96",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -528,
        -256
      ],
      "parameters": {
        "color": 2,
        "width": 432,
        "height": 240,
        "content": "**👇 步骤1:连接到您的脚本**"
      },
      "typeVersion": 1
    },
    {
      "id": "a7250930-1359-44ad-865f-48c21f641cf9",
      "name": "便签2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        176,
        -192
      ],
      "parameters": {
        "color": 4,
        "width": 496,
        "height": 176,
        "content": "**🧠 步骤2:配置AI语音**"
      },
      "typeVersion": 1
    },
    {
      "id": "c53a760c-aaaf-4c39-a564-6b30b8bf52d3",
      "name": "便签3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        544,
        272
      ],
      "parameters": {
        "color": 5,
        "width": 432,
        "height": 224,
        "content": "**⚠️ 步骤3:配置本地文件处理**"
      },
      "typeVersion": 1
    },
    {
      "id": "7b792b51-908d-485e-8b9b-7066bf344898",
      "name": "便签4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1216,
        -192
      ],
      "parameters": {
        "color": 6,
        "width": 576,
        "height": 192,
        "content": "**✅ 步骤4:设置上传目标**"
      },
      "typeVersion": 1
    },
    {
      "id": "6ccd0f26-1155-420b-9cad-f140b2d82e13",
      "name": "便利贴5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1840,
        240
      ],
      "parameters": {
        "width": 432,
        "height": 128,
        "content": "**🚀 步骤5:更新跟踪表格**"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "8d66a2a2-0e5f-47ba-883d-1a4c6da2d14d",
  "connections": {
    "Code1": {
      "main": [
        [
          {
            "node": "HTTP Request To Generate Voice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to File": {
      "main": [
        [
          {
            "node": "Read/Write Files from Disk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Code1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Uploading Wav File": {
      "main": [
        [
          {
            "node": "Uploading Google Drive Link of File To Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extracting fileName": {
      "main": [
        [
          {
            "node": "Running FFMPEG Local Code To Change Format Of File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Running FFMPEG Code": {
      "main": [
        [
          {
            "node": "Writing File Output Onto Disk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Getting Video Scripts": {
      "main": [
        [
          {
            "node": "Filter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read/Write Files from Disk": {
      "main": [
        [
          {
            "node": "Extracting fileName",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Writing File Output Onto Disk": {
      "main": [
        [
          {
            "node": "Uploading Wav File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request To Generate Voice": {
      "main": [
        [
          {
            "node": "Convert to File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking ‘Execute workflow’": {
      "main": [
        [
          {
            "node": "Getting Video Scripts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Running FFMPEG Local Code To Change Format Of File": {
      "main": [
        [
          {
            "node": "Running FFMPEG Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Uploading Google Drive Link of File To Google Sheet": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

高级 - 内容创作, 多模态 AI

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量20
分类2
节点类型12
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

作者
JJ Tham

JJ Tham

@jj-tham

Founder of Osinity. I build AI-powered n8n automations that save businesses 10+ hours a week and grow their revenue. We guarantee results with a 30-day risk-free trial—you only pay when we hit your targets.

外部链接
在 n8n.io 查看

分享此工作流