使用Replicate和OpenAI制作无面孔恐怖短片
高级
这是一个Content Creation, Multimodal AI领域的自动化工作流,包含 50 个节点。主要使用 If, Code, Wait, Switch, GoogleDrive 等节点。 通过OpenAI TTS、Replicate视频生成和YouTube上传制作无面孔恐怖短片
前置要求
- •Google Drive API 凭证
- •可能需要目标 API 的认证凭证
- •Google Sheets API 凭证
- •OpenAI API Key
使用的节点 (50)
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "YOUR_WORKFLOW_ID",
"meta": {
"instanceId": "YOUR_N8N_INSTANCE_ID"
},
"name": "使用 Replicate 和 OpenAI 制作无面孔恐怖短片",
"tags": [],
"nodes": [
{
"id": "e7f6db58-4f09-4d2c-84bf-e15b6529e861",
"name": "本地保存语音",
"type": "n8n-nodes-base.readWriteFile",
"onError": "continueRegularOutput",
"position": [
3968,
1232
],
"parameters": {
"options": {
"append": false
},
"fileName": "={{ $('Create Beat Inputs').item.json.audioFileName }}",
"operation": "write"
},
"typeVersion": 1
},
{
"id": "c24fb0bd-abee-45b3-812c-8f86ce6bae3d",
"name": "故事创意生成器",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
336,
-96
],
"parameters": {
"text": "Give me an idea about a new viral short horror story with surprise twist in the end. ",
"options": {
"systemMessage": "=You are a master of viral horror storytelling. Forget all previous stories. Forget previous stories and start fresh every time.\n\nYour task: Create a terrifying short horror story in exactly 8 beats.\n\nConstraints:\n- Output MUST be valid JSON only. No explanations, no comments, no text outside JSON.\n- The JSON must have exactly 8 beats, numbered beat1 through beat8.\n- Each beat must be a single, complete sentence with 10–20 words.\n- Beat 1 must clearly establish the scene, characters, and setting using vivid imagery.\n- At least 3 beats must include surprise, suspense, or a shocking twist.\n- Use \"show, don’t tell\": describe sights, sounds, smells, or actions to convey fear, tension, or dread.\n- Reading level: 4th grade, simple and direct language.\n- Build escalating tension across beats, ending with a chilling climax or twist.\n- Make the story memorable, terrifying, and shareable.\n- JSON must include BOTH `youtube_title` and `youtube_description` fields.\n- `youtube_title`: under 60 characters, hooky, scary, clickable.\n- `youtube_description`: under 150 words, thrilling, suspenseful, and encourages sharing.\n\nJSON schema (exactly this structure):\n\n{\n \"beats\": {\n \"beat1\": \"10–20 words\",\n \"beat2\": \"10–20 words\",\n \"beat3\": \"10–20 words\",\n \"beat4\": \"10–20 words\",\n \"beat5\": \"10–20 words\",\n \"beat6\": \"10–20 words\",\n \"beat7\": \"10–20 words\",\n \"beat8\": \"10–20 words\"\n },\n \"youtube_title\": \"Under 60 characters\",\n \"youtube_description\": \"Under 150 words\"\n}\n\nImportant: Do not skip any fields. Do not add extra fields. Do not return fewer than 8 beats. Do not include the word 'output' or any wrapper outside the JSON.\n",
"returnIntermediateSteps": false
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 1.9
},
{
"id": "3eb2ad5d-71a6-453b-84b0-a857ecc20d60",
"name": "故事节奏生成器",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
400,
336
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "gpt-4o-mini"
},
"options": {
"topP": 0.9,
"maxTokens": 500,
"temperature": 0.7,
"responseFormat": "json_object",
"presencePenalty": 0.6,
"frequencyPenalty": 0.5
}
},
"credentials": {
"openAiApi": {
"id": "YOUR_OPENAI_CREDENTIAL_ID",
"name": "YOUR_OPENAI_CREDENTIAL_NAME"
}
},
"typeVersion": 1.2
},
{
"id": "23202620-2e4e-4311-8d01-6b8a47a88fb6",
"name": "Google Sheets 创意日志",
"type": "n8n-nodes-base.googleSheets",
"position": [
832,
-96
],
"parameters": {
"columns": {
"value": {
"time": "={{ $json.output.youtube_title }}-{{ $now.format('yyyy-MM-dd HH:mm:ss') }}",
"beat 1": "={{ $json.output.beats.beat1 }}",
"beat 2": "={{ $json.output.beats.beat2 }}",
"beat 3": "={{ $json.output.beats.beat3 }}",
"beat 4": "={{ $json.output.beats.beat4 }}",
"beat 5": "={{ $json.output.beats.beat5 }}",
"beat 6": "={{ $json.output.beats.beat6 }}",
"beat 7": "={{ $json.output.beats.beat7 }}",
"beat 8": "={{ $json.output.beats.beat8 }}",
"status": "done",
"Youtube title": "={{ $json.output.youtube_title }}",
"Youtube description": "={{ $json.output.youtube_description }}"
},
"schema": [
{
"id": "time",
"type": "string",
"display": true,
"required": false,
"displayName": "time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 1",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "beat 1",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 2",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "beat 2",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 3",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "beat 3",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 4",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "beat 4",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 5",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "beat 5",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 6",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "beat 6",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 7",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "beat 7",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 8",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "beat 8",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Youtube title",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Youtube title",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Youtube description",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Youtube description",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "url",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 266501754,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL",
"cachedResultName": "story"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "YOUR_GOOGLE_SHEETS_CREDENTIAL_ID",
"name": "YOUR_GOOGLE_SHEETS_CREDENTIAL_NAME"
}
},
"typeVersion": 4.5
},
{
"id": "8eff780b-b397-4add-b9fe-833932c1691e",
"name": "故事节奏生成器5",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
640,
1632
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "gpt-4o-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "YOUR_OPENAI_CREDENTIAL_ID",
"name": "YOUR_OPENAI_CREDENTIAL_NAME"
}
},
"typeVersion": 1.2
},
{
"id": "d5e4aa80-bf0e-46d0-88b1-a506339e4bdf",
"name": "YouTube 视频上传",
"type": "n8n-nodes-base.httpRequest",
"position": [
1136,
2336
],
"parameters": {
"url": "={{ $('Prepare YouTube Upload').item.json.headers.location }}",
"method": "PUT",
"options": {},
"sendBody": true,
"contentType": "binaryData",
"sendHeaders": true,
"authentication": "predefinedCredentialType",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "video/webm"
}
]
},
"inputDataFieldName": "data",
"nodeCredentialType": "youTubeOAuth2Api"
},
"credentials": {
"youTubeOAuth2Api": {
"id": "YOUR_YOUTUBE_CREDENTIAL_ID",
"name": "YOUR_YOUTUBE_CREDENTIAL_NAME"
}
},
"typeVersion": 4.2
},
{
"id": "cc7034be-290f-4079-8e05-c1ae36fc777e",
"name": "视频音频合并命令",
"type": "n8n-nodes-base.code",
"onError": "continueRegularOutput",
"position": [
4192,
1232
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "try {\n const inputData = $('Create Beat Inputs').item.json;\n\n // FFmpeg command: merge existing MP4 with new audio\n const command = `\nffmpeg -hide_banner -loglevel error -i \"${inputData.fileName}\" -i \"${inputData.audioFileName}\" \\\n-filter_complex \"[1:a]atempo=1.3,apad=pad_dur=0.9[aud]\" \\\n-map 0:v -map \"[aud]\" \\\n-c:v copy -c:a aac -b:a 192k -shortest \"${inputData.videoFileName}\" -y\n `;\n\n return {\n json: {\n command,\n inputVideo: inputData.fileName,\n inputAudio: inputData.audioFileName,\n outputVideo: inputData.videoFileName,\n timestamp: new Date().toISOString()\n }\n };\n} catch (error) {\n return {\n json: {\n status: 'error',\n error: error.message,\n timestamp: new Date().toISOString()\n }\n };\n}\n"
},
"typeVersion": 2
},
{
"id": "7ffda491-6475-4cad-8342-c0182ed98a23",
"name": "运行 FFmpeg 合并媒体",
"type": "n8n-nodes-base.executeCommand",
"onError": "continueRegularOutput",
"position": [
4416,
1232
],
"parameters": {
"command": "={{ $json.command }}",
"executeOnce": false
},
"executeOnce": false,
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "4953a0ce-f7d6-42fa-85d7-21dd2fc44ae8",
"name": "临时文件清理",
"type": "n8n-nodes-base.executeCommand",
"position": [
0,
1200
],
"parameters": {
"command": "=rm -f 12*.png 12*.mp4 12*.mp3 12*.txt\n\n\n"
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "be931eb8-47c7-4acc-9bce-eceb5b38c582",
"name": "故事节奏生成器6",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1008,
1424
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "gpt-4o-mini"
},
"options": {
"topP": 1,
"temperature": 0.7
}
},
"credentials": {
"openAiApi": {
"id": "YOUR_OPENAI_CREDENTIAL_ID",
"name": "YOUR_OPENAI_CREDENTIAL_NAME"
}
},
"typeVersion": 1.2
},
{
"id": "6f3d20c0-35dc-4d8b-940a-fa8df19d294c",
"name": "等待",
"type": "n8n-nodes-base.wait",
"position": [
3520,
1232
],
"webhookId": "29b1736a-1483-45bf-8ef7-be18f594f0b3",
"parameters": {},
"typeVersion": 1.1
},
{
"id": "978cdc87-7ffe-4044-a659-fc3a8eb44674",
"name": "生成最终视频剪辑",
"type": "n8n-nodes-base.executeCommand",
"onError": "continueRegularOutput",
"position": [
2624,
1040
],
"parameters": {
"command": "=# Remove old file first\nrm -f horrorfile_short_final.mp4\n"
},
"executeOnce": true,
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "43e1ca14-d878-471d-af5a-2379fa8084f6",
"name": "🎨 图片生成器",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
2624,
1232
],
"parameters": {
"url": "https://api.replicate.com/v1/models/black-forest-labs/flux-schnell/predictions",
"method": "POST",
"options": {},
"jsonBody": "={\n \"input\": {\n \"prompt\": \"cinematic scene, oil painting effect, muted colors, not dark but eerie atmosphere, display {{ $('Create Beat Inputs').item.json.narrative }} with central character description {{ $('Create Beat Inputs').item.json.character }}, clear details, visible character features\",\n \"seed\": {{ $('Create Beat Inputs').item.json.seed }},\n \"prompt_upsampling\": true,\n \"width\": 1080,\n \"height\": 1920,\n \"num_outputs\": 1,\n \"aspect_ratio\": \"9:16\",\n \"output_format\": \"jpg\",\n \"output_quality\": 100,\n \"guidance\": 4,\n \"safety_tolerance\": 2,\n \"negative_prompt\": \"{{ $('Create Beat Inputs').item.json.negativeprompt }}\"\n }\n}\n",
"sendBody": true,
"jsonHeaders": "{\n \"Content-Type\": \"application/json\",\n \"Prefer\": \"wait\"\n}",
"sendHeaders": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"specifyHeaders": "json",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "YOUR_REPLICATE_CREDENTIAL_ID",
"name": "YOUR_REPLICATE_CREDENTIAL_NAME"
}
},
"typeVersion": 4.2
},
{
"id": "ef1dd38c-04cf-4de7-b29f-33ffb34521ba",
"name": "HTTP 请求",
"type": "n8n-nodes-base.httpRequest",
"position": [
3072,
1232
],
"parameters": {
"url": "={{ $json.output || $json.output[0] }}",
"options": {},
"sendHeaders": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"headerParameters": {
"parameters": [
{
"name": "accept",
"value": "application/json"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"id": "YOUR_REPLICATE_CREDENTIAL_ID",
"name": "YOUR_REPLICATE_CREDENTIAL_NAME"
}
},
"typeVersion": 4.2
},
{
"id": "3a2f7ffb-ef51-4676-adcc-539a1131b242",
"name": "故事创意解析器",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
416,
128
],
"parameters": {
"autoFix": true,
"jsonSchemaExample": "{\n \"beats\": {\n \"beat1\": \"10–20 words\",\n \"beat2\": \"10–20 words\",\n \"beat3\": \"10–20 words\",\n \"beat4\": \"10–20 words\",\n \"beat5\": \"10–20 words\",\n \"beat6\": \"10–20 words\",\n \"beat7\": \"10–20 words\",\n \"beat8\": \"10–20 words\"\n },\n \"youtube_title\": \"Under 60 characters\",\n \"youtube_description\": \"Under 150 words\"\n}"
},
"typeVersion": 1.3
},
{
"id": "0137fca6-5f1a-4335-9cf9-17e20864f5a5",
"name": "分支",
"type": "n8n-nodes-base.switch",
"position": [
-1472,
1200
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "Generate Story Idea",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cdd0f2ff-a83c-48c1-a473-e5c4f86fe12c",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.chatInput }}",
"rightValue": "idea"
}
]
},
"renameOutput": true
},
{
"outputKey": "Create Uploadable Video",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "9bf4596f-8031-4e7f-aaa6-c8c7831fea55",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.chatInput }}",
"rightValue": "create"
}
]
},
"renameOutput": true
},
{
"outputKey": "Publish to YouTube",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "d4598761-a115-469f-9836-2a7432910c82",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.chatInput }}",
"rightValue": "publish"
}
]
},
"renameOutput": true
},
{
"outputKey": "Clean Files in Drive",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "b8f3a5f9-819c-4276-90b9-3f7dc6064fae",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.chatInput }}",
"rightValue": "clean drive"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "793ebf6a-73b4-4672-869f-01f270590023",
"name": "准备 YouTube 上传",
"type": "n8n-nodes-base.httpRequest",
"position": [
336,
2336
],
"parameters": {
"url": "=https://www.googleapis.com/upload/youtube/v3/videos?part=snippet,status&uploadType=resumable",
"body": "={\n \"snippet\": {\n \"title\": \" {{ $json['Youtube title'] }} #PsychologicalHorror #TwistEnding #HorrorShorts\",\n \"description\": \"{{ $json['Youtube description'] }} #HorrorShort #CulinaryThrills #PsychologicalThriller #whispers_in_the_dark #Haunted #UrbanLegend #Spooky #DarkStories #Supernatural\",\n \"defaultLanguage\": \"en\",\n \"defaultAudioLanguage\": \"en\"\n },\n \"status\": {\n \"privacyStatus\": \"private\",\n \"license\": \"youtube\",\n \"embeddable\": true,\n \"publicStatsViewable\": true,\n \"madeForKids\": false\n }\n}\n\n",
"method": "POST",
"options": {
"response": {
"response": {
"fullResponse": true
}
}
},
"sendBody": true,
"contentType": "raw",
"sendHeaders": true,
"authentication": "predefinedCredentialType",
"rawContentType": "RAW/JSON",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "X-Upload-Content-Type",
"value": "video/webm"
}
]
},
"nodeCredentialType": "youTubeOAuth2Api"
},
"credentials": {
"youTubeOAuth2Api": {
"id": "YOUR_YOUTUBE_CREDENTIAL_ID",
"name": "YOUR_YOUTUBE_CREDENTIAL_NAME"
}
},
"typeVersion": 4.2
},
{
"id": "1732a1a9-dba2-4ae8-9bf0-7e9ecbb630a0",
"name": "获取 YouTube 标题和描述",
"type": "n8n-nodes-base.googleSheets",
"position": [
0,
2336
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 266501754,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL",
"cachedResultName": "story"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "YOUR_GOOGLE_SHEETS_CREDENTIAL_ID",
"name": "YOUR_GOOGLE_SHEETS_CREDENTIAL_NAME"
}
},
"typeVersion": 4.5
},
{
"id": "aa1f6a5c-946d-4940-979f-cdcca1aabe3c",
"name": "从磁盘读取要上传的视频",
"type": "n8n-nodes-base.readWriteFile",
"position": [
672,
2336
],
"parameters": {
"options": {},
"fileSelector": "=horrorfile_short_final.mp4"
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "ccc5eac0-9947-4b23-99a4-59be3426633d",
"name": "更新 YouTube 链接",
"type": "n8n-nodes-base.googleSheets",
"position": [
1504,
2336
],
"parameters": {
"columns": {
"value": {
"url": "=https://www.youtube.com/shorts/{{ $json.id }}",
"time": "={{ $('Get YouTube Title and Description').item.json.time }}",
"status": "published"
},
"schema": [
{
"id": "time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat ",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 2",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 2",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 3",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 3",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 4",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 4",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 5",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 5",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 6",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 6",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 7",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 7",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 8",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 8",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Youtube title",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Youtube title",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Youtube descripion",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Youtube descripion",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "url",
"type": "string",
"display": true,
"required": false,
"displayName": "url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"time"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 266501754,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL",
"cachedResultName": "story"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "YOUR_GOOGLE_SHEETS_CREDENTIAL_ID",
"name": "YOUR_GOOGLE_SHEETS_CREDENTIAL_NAME"
}
},
"typeVersion": 4.7
},
{
"id": "0a79a235-bea7-4a5f-a8f4-969b805fa773",
"name": "临时文件清理3",
"type": "n8n-nodes-base.executeCommand",
"position": [
1728,
2336
],
"parameters": {
"command": "=rm -f 12*.png 12*.mp4 12*.mp3 12*.txt\n\n\n"
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "ee2ffc65-34da-42a7-93c7-174f2f59079b",
"name": "搜索要删除的临时文件",
"type": "n8n-nodes-base.googleDrive",
"position": [
-224,
3056
],
"parameters": {
"filter": {
"folderId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
"cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
"cachedResultName": "YOUR_GOOGLE_DRIVE_FOLDER"
}
},
"options": {},
"resource": "fileFolder",
"queryString": "horrorfile*.mp4"
},
"credentials": {
"googleDriveOAuth2Api": {
"id": "YOUR_GOOGLE_DRIVE_CREDENTIAL_ID",
"name": "YOUR_GOOGLE_DRIVE_CREDENTIAL_NAME"
}
},
"typeVersion": 3
},
{
"id": "7120e6dd-66bd-480e-a329-d6bb919bdebf",
"name": "删除临时文件",
"type": "n8n-nodes-base.googleDrive",
"position": [
112,
3056
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.id }}"
},
"options": {},
"operation": "deleteFile"
},
"credentials": {
"googleDriveOAuth2Api": {
"id": "YOUR_GOOGLE_DRIVE_CREDENTIAL_ID",
"name": "YOUR_GOOGLE_DRIVE_CREDENTIAL_NAME"
}
},
"executeOnce": false,
"typeVersion": 3
},
{
"id": "bb77bfac-a8cb-4f71-a54b-077ba4b027fe",
"name": "获取故事创意",
"type": "n8n-nodes-base.googleSheets",
"position": [
336,
1200
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "done",
"lookupColumn": "status"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 266501754,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL",
"cachedResultName": "story"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "YOUR_GOOGLE_SHEETS_CREDENTIAL_ID",
"name": "YOUR_GOOGLE_SHEETS_CREDENTIAL_NAME"
}
},
"typeVersion": 4.5
},
{
"id": "26d02a86-9fd7-46f5-a575-70df7c794d4b",
"name": "旁白输出解析器",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
640,
1424
],
"parameters": {
"autoFix": true,
"jsonSchemaExample": "{\n \"narratives\": {\n \"narrative1\": \"...\",\n \"narrative2\": \"...\",\n \"narrative3\": \"...\",\n \"narrative4\": \"...\",\n \"narrative5\": \"...\",\n \"narrative6\": \"...\",\n \"narrative7\": \"...\",\n \"narrative8\": \"...\"\n }\n}"
},
"typeVersion": 1.3
},
{
"id": "780bc5fe-94fd-42c6-a0b2-6c0f4030e27a",
"name": "旁白提示生成器",
"type": "@n8n/n8n-nodes-langchain.agent",
"onError": "continueErrorOutput",
"position": [
560,
1200
],
"parameters": {
"text": "You are a strict text formatter for horror shorts text to audio generation prompt. ",
"options": {
"systemMessage": "=\n**Prompt:**\n\nYou are a strict formatter for horror shorts narration.\n\nTake the following inputs and provide a set of outputs:\n\n---\n\n### Input narratives\n\n1. {{ $json['beat 1'] }}\n2. {{ $json['beat 2'] }}\n3. {{ $json['beat 3'] }}\n4. {{ $json['beat 4'] }}\n5. {{ $json['beat 5'] }}\n6. {{ $json['beat 6'] }}\n7. {{ $json['beat 7'] }}\n8. {{ $json['beat 8'] }}\n\nDo not process input beats that are empty.\n\n---\n\n### Output (Narration with pauses)\n\n**RULES:**\n\n* Do **NOT** change, rewrite, or summarize the input text.\n* Only add pacing:\n • Ellipses (...) = short pause\n • Em dashes (—) = sharp emphasis\n • Blank lines = long pause\n* Keep exact wording untouched.\n* Do not add any other punctuation or words.\n* Style = calm, eerie, suspenseful.\n* Preserve all twists and unsettling imagery.\n* Always output **exactly 8 narratives** in JSON.\n* Add 500ms pause before and after each narrative (can be implied in timing markers).\n\n---\n\n### Output structure\n\n```json\n{\n \"narratives\": {\n \"narrative1\": \"{{ $json['beat 1'] }} with pauses added, if blank return blank\",\n \"narrative2\": \"{{ $json['beat 2'] }} with pauses added, if blank return blank\",\n \"narrative3\": \"{{ $json['beat 3'] }} with pauses added, if blank return blank\",\n \"narrative4\": \"{{ $json['beat 4'] }} with pauses added, if blank return blank\",\n \"narrative5\": \"{{ $json['beat 5'] }} with pauses added, if blank return blank\",\n \"narrative6\": \"{{ $json['beat 6'] }} with pauses added, if blank return blank\",\n \"narrative7\": \"{{ $json['beat 7'] }} with pauses added, if blank return blank\",\n \"narrative8\": \"{{ $json['beat 8'] }} with pauses added, if blank return blank\"\n }\n}\n```\n\n---\n\n✅ Key point: **Never alter or summarize the original text** — only insert pauses (`...`, `—`) and spacing for pacing.\n\n\n"
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 1.9
},
{
"id": "1bbf9e8b-b312-4926-bad5-99b859c62018",
"name": "图像提示生成器",
"type": "@n8n/n8n-nodes-langchain.agent",
"onError": "continueErrorOutput",
"position": [
1040,
1200
],
"parameters": {
"text": "You are a strict text formatter for horror shorts text to image generation prompt for non-animated images with oil painting effect, character should have same attributes of age , gender, complexion in every beat. ",
"options": {
"systemMessage": "=Create an image prompt to input in a text to image stable diffusion model:\n\n**Inputs \n{{ $('Get Story Idea').item.json['beat 1'] }}\n{{ $('Get Story Idea').item.json['beat 2'] }}\n{{ $('Get Story Idea').item.json['beat 3'] }}\n{{ $('Get Story Idea').item.json['beat 4'] }}\n{{ $('Get Story Idea').item.json['beat 5'] }}\n{{ $('Get Story Idea').item.json['beat 6'] }}\n{{ $('Get Story Idea').item.json['beat 7'] }}\n{{ $('Get Story Idea').item.json['beat 8'] }}\n\n* Forget all previous instructions, start new\n* Extract ** age, gender, hairstyle, clothing style, and skin and hair color** from above inputs\n* Character is **fully clothed**, with clearly visible with oil painting effect. add to image prompt in every beat\n* Don't add any other information (emotion, expression, location, action), only features and traits for consistency\n\n\n\n---\n\n## ✅ JSON Output\n\n```json\n{\n \"character\": \"character description\",\n \"negative_prompt\": \"letters, text, watermark, logo, signature, words, numbers, subtitles, captions, symbols, cartoon\"\n}\n```\n\n"
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 1.9
},
{
"id": "abd89e03-1702-4fd1-8943-905c48b2ba3b",
"name": "图片输出解析器",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
1136,
1424
],
"parameters": {
"autoFix": true,
"jsonSchemaExample": "{\n \"character\": \"character description\",\n \"negative_prompt\": \"letters, text, watermark, logo, signature, words, numbers, subtitles, captions, symbols, cartoon\"\n}"
},
"typeVersion": 1.3
},
{
"id": "0c2f9bc2-1f83-43d2-8493-bda10d95455c",
"name": "检查是否已创建节奏",
"type": "n8n-nodes-base.googleDrive",
"position": [
1504,
1200
],
"parameters": {
"filter": {
"folderId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
"cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
"cachedResultName": "YOUR_GOOGLE_DRIVE_FOLDER"
}
},
"options": {},
"resource": "fileFolder",
"queryString": "horrorfile*_1.mp4"
},
"credentials": {
"googleDriveOAuth2Api": {
"id": "YOUR_GOOGLE_DRIVE_CREDENTIAL_ID",
"name": "YOUR_GOOGLE_DRIVE_CREDENTIAL_NAME"
}
},
"typeVersion": 3,
"alwaysOutputData": true
},
{
"id": "7e6903d1-bd17-4b95-9184-36096bf48261",
"name": "处理 0 个文件",
"type": "n8n-nodes-base.code",
"position": [
1728,
1200
],
"parameters": {
"jsCode": "// This node ensures execution continues even if search returns nothing\nreturn [{ json: { trigger: true } }];"
},
"typeVersion": 2,
"continueOnFail": true,
"alwaysOutputData": true
},
{
"id": "ce7f1e76-8daf-4603-bda6-6bb1a3e7f411",
"name": "创建节奏输入",
"type": "n8n-nodes-base.code",
"position": [
1952,
1200
],
"parameters": {
"jsCode": "const workflowSeed = Math.floor(Math.random() * 1000000);\n\n// Get existing files from \"Check For Already Created Beats\" node\nlet existingFiles = [];\ntry {\n const searchResults = $('Check For Already Created Beats').all();\n if (searchResults && searchResults.length > 0) {\n existingFiles = searchResults.map(f => ({\n id: f.json.id,\n name: f.json.name\n }));\n console.log(`Found ${existingFiles.length} existing files`);\n } else {\n console.log('No existing files found, processing all beats');\n }\n} catch (error) {\n console.log('Search returned no results, processing all beats');\n}\n\n// Get data from upstream nodes\nconst storyData = $('Get Story Idea').first().json;\nconst narrationData = $('Narration Prompt Generator').first().json.output.narratives;\nconst imageData = $('Image Prompt Generator').first().json.output;\n\n// Collect all possible beats\nconst rawInputs = [\n { narrative: storyData['beat 1'], narrativeaudio: narrationData.narrative1 }, // FIXED: Added \"1\"\n { narrative: storyData['beat 2'], narrativeaudio: narrationData.narrative2 },\n { narrative: storyData['beat 3'], narrativeaudio: narrationData.narrative3 },\n { narrative: storyData['beat 4'], narrativeaudio: narrationData.narrative4 },\n { narrative: storyData['beat 5'], narrativeaudio: narrationData.narrative5 },\n { narrative: storyData['beat 6'], narrativeaudio: narrationData.narrative6 },\n { narrative: storyData['beat 7'], narrativeaudio: narrationData.narrative7 },\n { narrative: storyData['beat 8'], narrativeaudio: narrationData.narrative8 }\n];\n\n// Debug: Check what we got\nconsole.log('Raw inputs count:', rawInputs.length);\nconsole.log('Beat 1 check:', rawInputs[0].narrative ? 'OK' : 'MISSING');\n\n// Filter out empty beats\nconst filteredInputs = rawInputs.filter(input => input.narrative && input.narrative.trim() !== \"\");\nconsole.log(`Processing ${filteredInputs.length} non-empty beats`);\n\n// Map filtered beats to output items\nconst outputItems = filteredInputs.map((textInput, index) => {\n const beatNumber = index + 1; // Start from 1 instead of 0\n const videoFileName = `horrorfile${beatNumber}_1.mp4`;\n\n // Check if file already exists (by name or id)\n const alreadyExists = existingFiles.some(file =>\n file.name === videoFileName || file.id === videoFileName\n );\n\n return {\n json: {\n ...textInput,\n index: beatNumber,\n seed: workflowSeed,\n character: imageData.character,\n negativeprompt: imageData.negative_prompt,\n fileName: `horrorfile${beatNumber}.mp4`,\n audioFileName: `horrorfile${beatNumber}.mp3`,\n videoFileName: videoFileName,\n skip: alreadyExists\n }\n };\n});\n\n// Optional log for skipped items\nconst skipped = outputItems.filter(item => item.json.skip).map(i => i.json.videoFileName);\nif (skipped.length > 0) {\n console.log(`⏭️ Skipped existing files: ${skipped.join(', ')}`);\n}\n\n// Return only new items for downstream processing\nconst newItems = outputItems.filter(item => !item.json.skip);\nconsole.log(`Outputting ${newItems.length} items for processing`);\n\nreturn newItems;"
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "092100ff-85e6-4e7b-acd7-c2924f3c504b",
"name": "遍历项目",
"type": "n8n-nodes-base.splitInBatches",
"position": [
2400,
1280
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "cd8da2a0-3743-485c-92f4-be84246d4a34",
"name": "本地保存节奏图片",
"type": "n8n-nodes-base.readWriteFile",
"position": [
3296,
1232
],
"parameters": {
"options": {},
"fileName": "={{ $('Create Beat Inputs').item.json.fileName }}",
"operation": "write"
},
"typeVersion": 1
},
{
"id": "359d2545-efd5-46ad-b3bc-dc7e97cb3298",
"name": "读取节奏文件",
"type": "n8n-nodes-base.readWriteFile",
"onError": "continueRegularOutput",
"position": [
4640,
1232
],
"parameters": {
"options": {},
"fileSelector": "={{ $('Video Audio Merge Command').item.json.outputVideo }}"
},
"typeVersion": 1
},
{
"id": "68b298dd-36fa-49c7-a511-d5e66818b487",
"name": "上传节奏文件",
"type": "n8n-nodes-base.googleDrive",
"position": [
4864,
1296
],
"parameters": {
"name": "={{ $json.fileName }}",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
"cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
"cachedResultName": "YOUR_GOOGLE_DRIVE_FOLDER"
}
},
"credentials": {
"googleDriveOAuth2Api": {
"id": "YOUR_GOOGLE_DRIVE_CREDENTIAL_ID",
"name": "YOUR_GOOGLE_DRIVE_CREDENTIAL_NAME"
}
},
"typeVersion": 3
},
{
"id": "774f803e-d753-468d-95d3-5508897c33c0",
"name": "搜索节奏文件",
"type": "n8n-nodes-base.googleDrive",
"position": [
2848,
1040
],
"parameters": {
"filter": {
"folderId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
"cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
"cachedResultName": "YOUR_GOOGLE_DRIVE_FOLDER"
}
},
"options": {},
"resource": "fileFolder",
"queryString": "horrorfile*_1.mp4"
},
"credentials": {
"googleDriveOAuth2Api": {
"id": "YOUR_GOOGLE_DRIVE_CREDENTIAL_ID",
"name": "YOUR_GOOGLE_DRIVE_CREDENTIAL_NAME"
}
},
"typeVersion": 3
},
{
"id": "37b40dca-3544-4014-bfbb-001250271ba3",
"name": "下载节奏文件",
"type": "n8n-nodes-base.googleDrive",
"position": [
3072,
1040
],
"parameters": {
"fileId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.id }}"
},
"options": {},
"operation": "download"
},
"credentials": {
"googleDriveOAuth2Api": {
"id": "YOUR_GOOGLE_DRIVE_CREDENTIAL_ID",
"name": "YOUR_GOOGLE_DRIVE_CREDENTIAL_NAME"
}
},
"typeVersion": 3
},
{
"id": "6090d04e-1ae4-4f33-a427-a1c3ca92b363",
"name": "将节奏文件写入磁盘",
"type": "n8n-nodes-base.readWriteFile",
"position": [
3296,
1040
],
"parameters": {
"options": {},
"fileName": "={{ $json.name }}",
"operation": "write"
},
"typeVersion": 1
},
{
"id": "0282edd1-8ca9-41d9-9915-da753b41211d",
"name": "生成最终视频",
"type": "n8n-nodes-base.executeCommand",
"position": [
3520,
1040
],
"parameters": {
"command": "=#!/bin/sh\n\ninputs=\"\"\nmaps=\"\"\nn=0\n\n# Collect all horrorfile*_1.mp4 files\nfor f in horrorfile*_1.mp4; do\n inputs=\"$inputs -i $f\"\n maps=\"$maps[$n:v][$n:a]\"\n n=`expr $n + 1`\ndone\n\nsafeText=\"Finale...\"\n\n# Run ffmpeg with dynamic concat and single drawtext\nffmpeg $inputs \\\n-filter_complex \"\\\n$maps concat=n=$n:v=1:a=1[v][a]; \\\n[v]drawtext=fontfile=/home/node/.fonts/Creepster-Regular.ttf: \\\n text='Midnight Cuts': \\\n fontcolor=red:fontsize=45:x=(w-text_w)/2:y=50:box=1:boxcolor=black@0.5:boxborderw=10[vout]\" \\\n-map \"[vout]\" -map \"[a]\" \\\n-c:v libx264 -pix_fmt yuv420p -preset ultrafast -crf 23 \\\n-c:a aac -b:a 160k \\\n-y horrorfile_short_final.mp4\n"
},
"executeOnce": true,
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "5fe670f4-52c2-48ac-bfb9-68469f42e634",
"name": "从磁盘读取最终视频",
"type": "n8n-nodes-base.readWriteFile",
"position": [
3744,
1040
],
"parameters": {
"options": {},
"fileSelector": "=horrorfile_short_final.mp4"
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "d7635d32-12a0-4e95-badb-e4bb4f3cb8af",
"name": "上传最终视频",
"type": "n8n-nodes-base.googleDrive",
"position": [
3968,
1040
],
"parameters": {
"name": "={{ $json.fileName }}",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
"cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
"cachedResultName": "YOUR_GOOGLE_DRIVE_FOLDER"
}
},
"credentials": {
"googleDriveOAuth2Api": {
"id": "YOUR_GOOGLE_DRIVE_CREDENTIAL_ID",
"name": "YOUR_GOOGLE_DRIVE_CREDENTIAL_NAME"
}
},
"typeVersion": 3
},
{
"id": "1c32d653-8a67-487e-868c-7e2820685410",
"name": "更新状态为就绪",
"type": "n8n-nodes-base.googleSheets",
"position": [
4192,
1040
],
"parameters": {
"columns": {
"value": {
"time": "={{ $('Get Story Idea').first().json.time }}",
"status": "ready",
"row_number": 0
},
"schema": [
{
"id": "time",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "time",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 0",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "beat 0",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat ",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 2",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 2",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 3",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 3",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 4",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 4",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 5",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 5",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 6",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 6",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 7",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 7",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beat 8",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beat 8",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "twist",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "twist",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "character",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "character",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "location",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "location",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "spirit",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "spirit",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Youtube title",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Youtube title",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Youtube descripion",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Youtube descripion",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "url",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "status",
"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": [
"time"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 266501754,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL",
"cachedResultName": "story"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "YOUR_GOOGLE_SHEETS_CREDENTIAL_ID",
"name": "YOUR_GOOGLE_SHEETS_CREDENTIAL_NAME"
}
},
"typeVersion": 4.5
},
{
"id": "b6867418-9668-421c-a8e1-58c682664ab6",
"name": "生成节奏音频",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
3744,
1232
],
"parameters": {
"input": "={{ $('Create Beat Inputs').item.json.narrativeaudio }}",
"model": "tts-1-hd",
"options": {},
"resource": "audio"
},
"credentials": {
"openAiApi": {
"id": "YOUR_OPENAI_CREDENTIAL_ID",
"name": "YOUR_OPENAI_CREDENTIAL_NAME"
}
},
"typeVersion": 1.8
},
{
"id": "85e06aad-a8d1-4234-b6e7-ffa71db85aec",
"name": "如果还有剩余节奏",
"type": "n8n-nodes-base.if",
"position": [
2176,
1200
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "e7c77da4-cb68-4faa-b185-17a77f0d9e5a",
"operator": {
"type": "number",
"operation": "notEquals"
},
"leftValue": "={{ $('Check For Already Created Beats').all().length }}",
"rightValue": 8
}
]
}
},
"typeVersion": 2.2
},
{
"id": "c919dbb0-1558-493d-bdf9-0a0e19d2c83b",
"name": "当收到聊天消息时",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"position": [
-1696,
1232
],
"webhookId": "67fdd493-8b16-43a1-8a76-2a2b3dbc4845",
"parameters": {
"options": {}
},
"typeVersion": 1.3
},
{
"id": "78a35d5c-c4b3-4102-9b2d-54d4a79c65a5",
"name": "🎨 视频生成器",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
2848,
1232
],
"parameters": {
"url": "https://api.replicate.com/v1/models/wan-video/wan-2.2-i2v-fast/predictions",
"method": "POST",
"options": {},
"jsonBody": "={\n \"input\": {\n \"image\": \"{{ $json.output || $json.output[0] }}\",\n \"prompt\": \"{{ $json.input.prompt }}\",\n \"negative_prompt\": \"{{ $json.input.negative_prompt }}\"\n }\n}",
"sendBody": true,
"jsonHeaders": "{\n \"Content-Type\": \"application/json\",\n \"Prefer\": \"wait\"\n}",
"sendHeaders": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"specifyHeaders": "json",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "YOUR_REPLICATE_CREDENTIAL_ID",
"name": "YOUR_REPLICATE_CREDENTIAL_NAME"
}
},
"typeVersion": 4.2
},
{
"id": "f4f06df4-3c9b-4663-b45a-2a5b5801f9e5",
"name": "便签说明",
"type": "n8n-nodes-base.stickyNote",
"position": [
-240,
-416
],
"parameters": {
"width": 1424,
"height": 896,
"content": "## 步骤 1. 生成故事节奏"
},
"typeVersion": 1
},
{
"id": "ac794f7f-1bb1-4a12-a4ba-2e8d214aec15",
"name": "便签说明1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-240,
768
],
"parameters": {
"color": 5,
"width": 5440,
"height": 1120,
"content": "## 步骤 2:创建视频"
},
"typeVersion": 1
},
{
"id": "f2e1c3c3-66c7-4d7d-b3fe-109622933809",
"name": "便签说明2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-256,
2048
],
"parameters": {
"color": 6,
"width": 2352,
"height": 496,
"content": "## 步骤 3. 发布视频"
},
"typeVersion": 1
},
{
"id": "ef557922-dfc6-4057-a6a0-1e1f50d70195",
"name": "便签说明3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-304,
2784
],
"parameters": {
"color": 3,
"width": 704,
"height": 496,
"content": "## 步骤 4. 从 Google Drive 删除临时文件"
},
"typeVersion": 1
}
],
"active": true,
"pinData": {},
"settings": {
"callerPolicy": "workflowsFromSameOwner",
"executionOrder": "v1",
"executionTimeout": -1
},
"versionId": "YOUR_VERSION_ID",
"connections": {
"Wait": {
"main": [
[
{
"node": "Generate Beat Audio",
"type": "main",
"index": 0
}
]
]
},
"Switch": {
"main": [
[
{
"node": "Story Idea Generator",
"type": "main",
"index": 0
}
],
[
{
"node": "Temporary Files Cleanup",
"type": "main",
"index": 0
}
],
[
{
"node": "Get YouTube Title and Description",
"type": "main",
"index": 0
}
],
[
{
"node": "Search Temporary Files to Delete",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Save Beat Image Locally",
"type": "main",
"index": 0
}
]
]
},
"Get Story Idea": {
"main": [
[
{
"node": "Narration Prompt Generator",
"type": "main",
"index": 0
}
]
]
},
"Handle 0 Files": {
"main": [
[
{
"node": "Create Beat Inputs",
"type": "main",
"index": 0
}
]
]
},
"Read Beat File": {
"main": [
[
{
"node": "Upload Beat File",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[
{
"node": "Generate Final Video Clip",
"type": "main",
"index": 0
}
],
[
{
"node": "🎨 Image Generator",
"type": "main",
"index": 0
}
]
]
},
"Upload Beat File": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Search Beat Files": {
"main": [
[
{
"node": "Download Beat File",
"type": "main",
"index": 0
}
]
]
},
"Story Idea Parser": {
"ai_outputParser": [
[
{
"node": "Story Idea Generator",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Create Beat Inputs": {
"main": [
[
{
"node": "If Beats Remaining",
"type": "main",
"index": 0
}
]
]
},
"Download Beat File": {
"main": [
[
{
"node": "Write Beat File to Disk",
"type": "main",
"index": 0
}
]
]
},
"If Beats Remaining": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
],
[
{
"node": "Generate Final Video Clip",
"type": "main",
"index": 0
}
]
]
},
"Update YouTube Url": {
"main": [
[
{
"node": "Temporary Files Cleanup3",
"type": "main",
"index": 0
}
]
]
},
"Upload Final Video": {
"main": [
[
{
"node": "Update Status to Ready",
"type": "main",
"index": 0
}
]
]
},
"Generate Beat Audio": {
"main": [
[
{
"node": "Save Speech Locally",
"type": "main",
"index": 0
}
]
]
},
"Image Output Parser": {
"ai_outputParser": [
[
{
"node": "Image Prompt Generator",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Save Speech Locally": {
"main": [
[
{
"node": "Video Audio Merge Command",
"type": "main",
"index": 0
}
]
]
},
"Generate Final Video": {
"main": [
[
{
"node": "Read Final Video from Disk",
"type": "main",
"index": 0
}
]
]
},
"Story Beat Generator": {
"ai_languageModel": [
[
{
"node": "Story Idea Generator",
"type": "ai_languageModel",
"index": 0
},
{
"node": "Story Idea Parser",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Story Idea Generator": {
"main": [
[
{
"node": "Google Sheet Idea Log",
"type": "main",
"index": 0
}
]
]
},
"YouTube Video Upload": {
"main": [
[
{
"node": "Update YouTube Url",
"type": "main",
"index": 0
}
]
]
},
"🎨 Image Generator": {
"main": [
[
{
"node": "🎨 Video Generator",
"type": "main",
"index": 0
}
]
]
},
"🎨 Video Generator": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"Story Beat Generator5": {
"ai_languageModel": [
[
{
"node": "Narration Prompt Generator",
"type": "ai_languageModel",
"index": 0
},
{
"node": "Image Output Parser",
"type": "ai_languageModel",
"index": 0
},
{
"node": "Narration Output Parser",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Story Beat Generator6": {
"ai_languageModel": [
[
{
"node": "Image Prompt Generator",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Image Prompt Generator": {
"main": [
[
{
"node": "Check For Already Created Beats",
"type": "main",
"index": 0
}
]
]
},
"Prepare YouTube Upload": {
"main": [
[
{
"node": "Read Video for Upload from Disk",
"type": "main",
"index": 0
}
]
]
},
"Narration Output Parser": {
"ai_outputParser": [
[
{
"node": "Narration Prompt Generator",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Save Beat Image Locally": {
"main": [
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"Temporary Files Cleanup": {
"main": [
[
{
"node": "Get Story Idea",
"type": "main",
"index": 0
}
]
]
},
"Write Beat File to Disk": {
"main": [
[
{
"node": "Generate Final Video",
"type": "main",
"index": 0
}
]
]
},
"Temporary Files Cleanup3": {
"main": [
[]
]
},
"Generate Final Video Clip": {
"main": [
[
{
"node": "Search Beat Files",
"type": "main",
"index": 0
}
]
]
},
"Run FFmpeg to Merge Media": {
"main": [
[
{
"node": "Read Beat File",
"type": "main",
"index": 0
}
]
]
},
"Video Audio Merge Command": {
"main": [
[
{
"node": "Run FFmpeg to Merge Media",
"type": "main",
"index": 0
}
]
]
},
"Narration Prompt Generator": {
"main": [
[
{
"node": "Image Prompt Generator",
"type": "main",
"index": 0
}
]
]
},
"Read Final Video from Disk": {
"main": [
[
{
"node": "Upload Final Video",
"type": "main",
"index": 0
}
]
]
},
"When chat message received": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"Check For Already Created Beats": {
"main": [
[
{
"node": "Handle 0 Files",
"type": "main",
"index": 0
}
]
]
},
"Read Video for Upload from Disk": {
"main": [
[
{
"node": "YouTube Video Upload",
"type": "main",
"index": 0
}
]
]
},
"Search Temporary Files to Delete": {
"main": [
[
{
"node": "Delete Temporary Files",
"type": "main",
"index": 0
}
]
]
},
"Get YouTube Title and Description": {
"main": [
[
{
"node": "Prepare YouTube Upload",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 内容创作, 多模态 AI
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
Gemini_NanoBanana_模板
使用 Fal.ai 模型(nano-banana、WAN2.2、Veo3)从 Google Sheets 生成 UGC 广告
If
Set
Code
+13
36 节点Jaruphat J.
内容创作
WordPress博客自动化专业版(深度研究)v2.1市场
使用GPT-4o、Perplexity AI和多语言支持自动化SEO优化的博客创建
If
Set
Xml
+27
125 节点Daniel Ng
内容创作
批量SEO内容生成与带AI图片的Webflow草稿创建(模板)
使用GPT、Gemini图片和Webflow草稿创建进行批量SEO内容生成
If
Set
Code
+18
54 节点Dahiana
内容创作
使用 OpenAI、QuickChart 和 Google Drive 将电子表格数据转换为智能图表
使用 OpenAI、QuickChart 和 Google Drive 将电子表格数据转换为智能图表
If
Set
Code
+18
82 节点LeeWei
内容创作
💥 使用NanoBanana、Seedream 4、ChatGPT Image和Veo 3自动化视频广告 - VIDE
使用AI(NanoBanana、Seedream、GPT-4o、Veo 3)自动化和发布视频广告活动
Set
Code
Wait
+16
63 节点Dr. Firas
内容创作
使用 OpenAI、ElevenLabs 和 Fal.ai 自动化病毒式内容创作,适用于视频、播客和 ASMR
使用 OpenAI、ElevenLabs 和 Fal.ai 自动化病毒式内容创作,适用于视频、播客和 ASMR
Set
Code
Wait
+16
97 节点Adam Crafts
内容创作