8
n8n 中文网amn8n.com

电子书转有声书

高级

这是一个Content Creation, Multimodal AI领域的自动化工作流,包含 19 个节点。主要使用 Code, Wait, FormTrigger, GoogleDrive, HttpRequest 等节点。 使用MiniMax和FFmpeg将电子书转换为有声书

前置要求
  • Google Drive API 凭证
  • 可能需要目标 API 的认证凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "bX6cyG6u0dUYo1gM",
  "meta": {
    "instanceId": "90d03af248d07e2ebe7c0ecf1b18f488f6465e5560f151e375f9e5ab447ab951",
    "templateCredsSetupCompleted": true
  },
  "name": "电子书",
  "tags": [],
  "nodes": [
    {
      "id": "7d65ca00-5f29-4e11-aaa8-77f8680add0c",
      "name": "保存音频片段",
      "type": "n8n-nodes-base.readWriteFile",
      "position": [
        64,
        0
      ],
      "parameters": {
        "options": {},
        "fileName": "=/tmp/audio {{$itemIndex}}.mp3",
        "operation": "write",
        "dataPropertyName": "=audio {{ $itemIndex }}"
      },
      "typeVersion": 1
    },
    {
      "id": "0adc9201-3479-450f-8b5e-6bbf16cf01d2",
      "name": "生成 `concat_list.txt`",
      "type": "n8n-nodes-base.code",
      "position": [
        -240,
        192
      ],
      "parameters": {
        "jsCode": "/**\n * This Code node will:\n * 1. Gather all file paths from the incoming items (assuming each item has `item.json.filePath`).\n * 2. Build a single text string, each line in FFmpeg concat format: `file '/path/to/audio.mp3'`\n * 3. Convert that text to binary (Base64) so the next node (\"Write Binary File\") can save it as `concat_list.txt`.\n */\n\nconst items = $input.all();\n\n// Build the concat list\nlet concatListText = '';\n\nitems.forEach((item, index) => {\n  let filePath;\n\n\n  // Use only fileName for the rest\n    filePath = item.json.fileName;\n\n\n  if (filePath) {\n    concatListText += `file '${filePath}'\\n`;\n  }\n});\n\n// Convert the text to a Buffer, then to Base64\nconst buffer = Buffer.from(concatListText, 'utf-8');\nconst base64Data = buffer.toString('base64');\n\n// Return a single item containing the binary data\nreturn [\n  {\n    json: {},\n    binary: {\n      data: {\n        data: base64Data,\n        mimeType: 'text/plain',\n        fileName: 'concat_list.txt'\n      }\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "c9aa3a38-449f-44a4-92d3-f28c1c29114c",
      "name": "保存 concat_list",
      "type": "n8n-nodes-base.readWriteFile",
      "position": [
        96,
        192
      ],
      "parameters": {
        "options": {},
        "fileName": "/tmp/concat_list.txt",
        "operation": "write"
      },
      "typeVersion": 1
    },
    {
      "id": "956de46d-86b8-40ec-81c0-91fe87113d75",
      "name": "合并音频片段并删除所有文件",
      "type": "n8n-nodes-base.executeCommand",
      "position": [
        -240,
        400
      ],
      "parameters": {
        "command": "ffmpeg -y -f concat -safe 0 -i /tmp/concat_list.txt \\\n-c copy /tmp/final_merged.mp3\n\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1405b1fb-7a4f-45d9-976c-121437ece794",
      "name": "读取 final_merged",
      "type": "n8n-nodes-base.readWriteFile",
      "position": [
        96,
        400
      ],
      "parameters": {
        "options": {},
        "fileSelector": "/tmp/final_merged.mp3"
      },
      "typeVersion": 1
    },
    {
      "id": "13749486-4e35-4444-9734-3be869668540",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1680,
        -144
      ],
      "parameters": {
        "color": 4,
        "width": 560,
        "height": 1024,
        "content": "## 电子书提取模块"
      },
      "typeVersion": 1
    },
    {
      "id": "f7a4e41c-3d00-4918-af1c-e1a772905671",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1088,
        -144
      ],
      "parameters": {
        "color": 3,
        "width": 704,
        "height": 1024,
        "content": "## 电子书转有声书转换模块"
      },
      "typeVersion": 1
    },
    {
      "id": "cf4982e5-e3ac-4ade-8fac-557a54c93a68",
      "name": "便签2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -352,
        -144
      ],
      "parameters": {
        "color": 5,
        "width": 656,
        "height": 1024,
        "content": "## 音频合并模块"
      },
      "typeVersion": 1
    },
    {
      "id": "0b98b51d-f5a1-4107-903d-7d419cd6b75e",
      "name": "便签3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        336,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 400,
        "content": "## 将电子书上传至云端硬盘"
      },
      "typeVersion": 1
    },
    {
      "id": "57a896d1-6d7e-4cba-b55a-d3ab31742f7c",
      "name": "表单",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -1632,
        -48
      ],
      "webhookId": "d95584f4-a526-4218-8f75-2b17272ebba9",
      "parameters": {
        "options": {
          "appendAttribution": false
        },
        "formTitle": "Ebook to Audiobook",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "UPLOAD",
              "multipleFiles": false,
              "requiredField": true
            }
          ]
        },
        "formDescription": "Upload your Ebook here"
      },
      "typeVersion": 2.3
    },
    {
      "id": "ad8b130e-e51d-40ad-85a1-9ce98e978422",
      "name": "提取文本",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -1456,
        -48
      ],
      "parameters": {
        "options": {},
        "operation": "pdf",
        "binaryPropertyName": "UPLOAD"
      },
      "typeVersion": 1
    },
    {
      "id": "3e47b303-ea16-4b57-9df3-227a4c3f7566",
      "name": "根据规则分割文本",
      "type": "n8n-nodes-base.code",
      "position": [
        -1264,
        -48
      ],
      "parameters": {
        "jsCode": "const rawText = $input.first().json.text || \"\";\n\n// Clean function for JSON/TTS\nfunction cleanText(str) {\n    return str\n        .replace(/\\\\\\\\n/g, \" \")\n        .replace(/\\\\n/g, \" \")\n        .replace(/\\\\/g, \"\\\\\\\\\")\n        .replace(/\"/g, '\\\\\"')\n        .replace(/(\\r\\n|\\r|\\n)+/g, \" \")\n        .replace(/\\s+/g, \" \")\n        .trim();\n}\n\nconst text = cleanText(rawText);\n\nconst sentences = text.split(/(?<=[.!?])\\s+/).filter(Boolean);\n\nconst maxChars = 500;\nlet parts = [];\nlet chunk = \"\";\n\nfor (let sentence of sentences) {\n    if (sentence.length > maxChars) {\n        // Split very long sentence into smaller pieces\n        let start = 0;\n        while (start < sentence.length) {\n            const sub = sentence.slice(start, start + maxChars);\n            if (chunk) parts.push(chunk);\n            parts.push(sub);\n            chunk = \"\";\n            start += maxChars;\n        }\n        continue;\n    }\n\n    const space = chunk ? \" \" : \"\";\n    if ((chunk + space + sentence).length > maxChars) {\n        if (chunk) parts.push(chunk);\n        chunk = sentence;\n    } else {\n        chunk += space + sentence;\n    }\n}\n\nif (chunk) parts.push(chunk);\nconst result = parts.map((p, i) => ({ order: i + 1, text: p }));\n\nreturn result.map(r => ({ json: r }));\n"
      },
      "typeVersion": 2
    },
    {
      "id": "40d0a3d3-e4d0-4b0a-82d4-393aa5ad3aa2",
      "name": "遍历文本块(每次5个)",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -1024,
        144
      ],
      "parameters": {
        "options": {},
        "batchSize": 5
      },
      "typeVersion": 3
    },
    {
      "id": "2c369974-0d97-405d-9121-cbcb5648c00c",
      "name": "等待5秒",
      "type": "n8n-nodes-base.wait",
      "position": [
        -544,
        208
      ],
      "webhookId": "865809f7-7aea-40bd-9a0e-104a2ee18d73",
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "c606fc3d-c0fc-41f7-a646-8f369ebea7ea",
      "name": "将 URL 转换为音频文件",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -800,
        0
      ],
      "parameters": {
        "url": "={{ $json.output }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "78cec513-0fe5-4325-93aa-198f63afdcd8",
      "name": "为音频文件添加索引",
      "type": "n8n-nodes-base.code",
      "position": [
        -240,
        0
      ],
      "parameters": {
        "jsCode": "return items.map((item, index) => {\n  // Make a new item\n  const newItem = { json: {}, binary: {} };\n\n  // Copy the JSON data if you have any\n  newItem.json = { ...item.json };\n\n  // Loop through all binary properties\n  for (let key in item.binary) {\n    // Rename the binary key\n    const newKey = `audio ${index}`;\n\n    // Copy the binary data\n    newItem.binary[newKey] = { ...item.binary[key] };\n\n    // Rename the file itself\n    newItem.binary[newKey].fileName = `${newKey}.mp3`; // change extension if needed\n  }\n\n  return newItem;\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "d7b3d611-98d0-44fc-8ded-597f1e5ad916",
      "name": "上传电子书",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        432,
        0
      ],
      "parameters": {
        "name": "audiobook.mp3",
        "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": "11eIODBtLZwiUjUVJvK97_Z42uPmEnMMu",
          "cachedResultUrl": "https://drive.google.com/drive/folders/11eIODBtLZwiUjUVJvK97_Z42uPmEnMMu",
          "cachedResultName": "Audiobook"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "4pJ4FbSsj82fOkbU",
          "name": "Gridve"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "33160ec4-53df-4a5c-95be-029065d4e2f7",
      "name": "MINIMAX 文本转语音",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -768,
        208
      ],
      "parameters": {
        "url": "https://api.replicate.com/v1/models/minimax/speech-02-hd/predictions",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"input\": {\n    \"text\": \"{{ $json.text }}\",\n    \"pitch\": 0,\n    \"speed\": 1,\n    \"volume\": 1,\n    \"bitrate\": 128000,\n    \"channel\": \"mono\",\n    \"emotion\": \"happy\",\n    \"voice_id\": \"Friendly_Person\",\n    \"sample_rate\": 32000,\n    \"language_boost\": \"English\",\n    \"english_normalization\": true\n  }\n} ",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Prefer",
              "value": "wait"
            }
          ]
        }
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "w56BeWYVDLf1uQQ9",
          "name": "Bearer YOUR_TOKEN_HERE account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "88c3f2dc-5690-45ac-90d6-86c27bfeb04e",
      "name": "便签4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2256,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 528,
        "height": 528,
        "content": "# 观看 [YouTube 演示视频](https://img.youtube.com/vi/xKqkjXIPZoM/0.jpg)"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "d82d1c3b-0657-4fc5-8691-40ef2fe01121",
  "connections": {
    "FORM": {
      "main": [
        [
          {
            "node": "EXTRACT TEXT",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "MINIMAX TTS": {
      "main": [
        [
          {
            "node": "WAITS FOR 5 SECONDS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "EXTRACT TEXT": {
      "main": [
        [
          {
            "node": "SPLITS THE TEXT ACCORGING TO RULES",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save concat_list": {
      "main": [
        [
          {
            "node": "Join audio chucks and delete all files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Audio Chucks": {
      "main": [
        [
          {
            "node": "Generate `concat_list.txt`",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "read final_merged": {
      "main": [
        [
          {
            "node": "Uploads Ebook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WAITS FOR 5 SECONDS": {
      "main": [
        [
          {
            "node": "Loop Over Text chunks (5) at a time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate `concat_list.txt`": {
      "main": [
        [
          {
            "node": "Save concat_list",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CONVERTS URL TO AUDIO FILES": {
      "main": [
        [
          {
            "node": "GIVES INDEXES TO AUDIO FILES",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GIVES INDEXES TO AUDIO FILES": {
      "main": [
        [
          {
            "node": "Save Audio Chucks",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SPLITS THE TEXT ACCORGING TO RULES": {
      "main": [
        [
          {
            "node": "Loop Over Text chunks (5) at a time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Text chunks (5) at a time": {
      "main": [
        [
          {
            "node": "CONVERTS URL TO AUDIO FILES",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "MINIMAX TTS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Join audio chucks and delete all files": {
      "main": [
        [
          {
            "node": "read final_merged",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

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

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

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

需要付费吗?

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

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

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

作者
Jay Emp0

Jay Emp0

@jay-emp0

AI and Automation developer. Im implementing n8n and ai tools to automate marketing and sales in companies

外部链接
在 n8n.io 查看

分享此工作流