8
n8n 中文网amn8n.com

旅行故事讲述器

高级

这是一个Content Creation, Multimodal AI领域的自动化工作流,包含 19 个节点。主要使用 Set, Code, Merge, Webhook, SplitOut 等节点。 使用GPT-4O Vision将旅行照片转换为叙事故事

前置要求
  • HTTP Webhook 端点(n8n 会自动生成)
  • OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "LvEhaVWxPx14FYiD",
  "meta": {
    "instanceId": "3c35a703d75886d08705c211ee107a7513430dd05494ec0c569f28570a3768fa",
    "templateCredsSetupCompleted": true
  },
  "name": "TripTeller",
  "tags": [
    {
      "id": "TOmp11D0RTZnlXKe",
      "name": "Creator Hub",
      "createdAt": "2025-07-27T06:39:31.509Z",
      "updatedAt": "2025-07-27T06:39:31.509Z"
    }
  ],
  "nodes": [
    {
      "id": "split-photos",
      "name": "拆分照片数组",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        384,
        112
      ],
      "parameters": {
        "options": {
          "destinationFieldName": "data"
        },
        "fieldToSplitOut": "photos"
      },
      "typeVersion": 1
    },
    {
      "id": "analyze-image",
      "name": "视觉分析",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        896,
        -16
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o"
        },
        "options": {},
        "resource": "image",
        "inputType": "base64",
        "operation": "analyze"
      },
      "credentials": {
        "openAiApi": {
          "id": "PzzLblAykQPFIDZf",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "generate-story",
      "name": "生成旅行故事",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1600,
        112
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1",
          "cachedResultName": "GPT-4.1"
        },
        "options": {
          "topP": 1,
          "temperature": 0.7,
          "presence_penalty": 0,
          "frequency_penalty": 0
        },
        "messages": {
          "values": [
            {
              "content": "=Based on these trip photos and analysis, create an engaging travel story:\n\n{{ JSON.stringify($json.tripDays, null, 2) }}\n\nFormat the output as a structured story with:\n\n1. Trip title\n2. Brief introduction\n3. Day-by-day narrative with titles\n4. Memorable moments highlights\n5. Closing reflection"
            },
            {
              "role": "system",
              "content": "=You are a professional storyteller crafting a first-person narrative using the user's photo sequence. Write in a narrative style that brings the journey to life. Include sensory details, emotions, and cultural observations. \n\n**Structure the story by days** with creative titles for each day. Make it personal and immersive. \n\n**Context Summary**\n- Submission Time: {{ $now.toUTC()}}\n- Number of Photos: {{ $json.totalPhotos }}\n- Time Range: {{ $json.dateRange.start }} to {{ $json.dateRange.end }}\n\n**Photos Provided (chronological order):**\n\n\n**Your Task**\n- Create an immersive travel or personal story based on the moments captured in the photos\n- Title the story creatively and meaningfully\n- Write in **first-person past tense**\n- Include **sensory details** (sights, sounds, feelings, etc.)\n- Format using **Markdown**: use headings, paragraphs, and line breaks\n- Do **not** reference filenames or technical details\n- **focus** on emotion, story, and setting\n- Conclude with a reflective insight or emotional takeaway\n\n**Tone & Style Options**\nChoose one based on image mood:\n- Warm and nostalgic\n- Playful and lighthearted\n- Poetic and introspective\n- Adventurous and energetic\n\n**Output Format**\nTitle: <Title for Day 1>\n<Story for the tripDay 1>\n\nTitle: <Title for Day 2>\n<Story for the tripDay 2>\n\nTitle: <Title for Day 3>\n<Story for the tripDay 3>\n\nSummary: <Summarize all trip days in less than 500 words>\n\n"
            }
          ]
        },
        "jsonOutput": true
      },
      "credentials": {
        "openAiApi": {
          "id": "PzzLblAykQPFIDZf",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "format-response",
      "name": "格式化最终响应",
      "type": "n8n-nodes-base.set",
      "position": [
        2016,
        112
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "success",
              "name": "success",
              "type": "boolean",
              "value": true
            },
            {
              "id": "storybook",
              "name": "storybook",
              "type": "object",
              "value": "={{ $json.message.content }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "1bc0b873-5253-4768-8c82-5e33e8834a25",
      "name": "转换为文件",
      "type": "n8n-nodes-base.convertToFile",
      "position": [
        656,
        -16
      ],
      "parameters": {
        "options": {
          "fileName": "={{ $json.data.filename }}"
        },
        "operation": "toBinary",
        "sourceProperty": "data.data"
      },
      "typeVersion": 1.1
    },
    {
      "id": "edit-fields",
      "name": "获取照片数组",
      "type": "n8n-nodes-base.set",
      "position": [
        112,
        112
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "photos",
              "name": "photos",
              "type": "array",
              "value": "={{ $item(\"0\").$node[\"Photo Upload Webhook\"].json[\"body\"][\"photos\"] }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ed9d8186-d2fe-462d-bc6d-1471e7ef59ce",
      "name": "设置照片属性",
      "type": "n8n-nodes-base.set",
      "position": [
        656,
        384
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "df19c366-e65d-4614-a3c5-f1a317b3c1e7",
              "name": "filename",
              "type": "string",
              "value": "={{ $json.data.filename }}"
            },
            {
              "id": "1177488a-ba24-4a04-9cfc-fde61cbfbeb0",
              "name": "size",
              "type": "number",
              "value": "={{ $json.data.size }}"
            },
            {
              "id": "6c83cb35-d22e-4074-b685-a5a229f3edb0",
              "name": "timestamp",
              "type": "string",
              "value": "={{ $json.data.lastModified }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "9108850e-3a7a-482d-9f6c-de02e39d2da1",
      "name": "合并",
      "type": "n8n-nodes-base.merge",
      "position": [
        1136,
        112
      ],
      "parameters": {
        "mode": "combine",
        "options": {
          "clashHandling": {
            "values": {
              "resolveClash": "preferLast"
            }
          }
        },
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "0dfdbab7-3250-4f33-9340-7ee247b0d30c",
      "name": "按日期分组照片",
      "type": "n8n-nodes-base.code",
      "position": [
        1344,
        112
      ],
      "parameters": {
        "jsCode": "// Group photos by date\nconst photosByDate = {};\n\nfor (const item of $input.all()) {\n  const dateFormatted = new Date (item.json.timestamp).toDateString();\n  const date = dateFormatted;\n  if (!photosByDate[date]) {\n    photosByDate[date] = [];\n  }\n  photosByDate[date].push(item.json);\n}\n\n// Sort dates and create day entries\nconst sortedDates = Object.keys(photosByDate).sort();\nconst dayEntries = [];\n\nfor (const date of sortedDates) {\n  const photos = photosByDate[date];\n  \n  // Sort photos by timestamp within each day\n  photos.sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));\n  \n  // Extract themes for the day\n  const dayThemes = [...new Set(photos.flatMap(p => p.themes))];\n  \n  dayEntries.push({\n    date: date,\n    dayNumber: sortedDates.indexOf(date) + 1,\n    photos: photos,\n    themes: dayThemes,\n    photoCount: photos.length\n  });\n}\n\nreturn [{\n  json: {\n    tripDays: dayEntries,\n    totalDays: dayEntries.length,\n    totalPhotos: $input.all().length,\n    dateRange: {\n      start: sortedDates[0],\n      end: sortedDates[sortedDates.length - 1]\n    }\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "1867d2c7-1505-4ac6-926a-d072a5dcc219",
      "name": "照片上传 Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -160,
        112
      ],
      "webhookId": "9b3252c9-6cc8-4ac4-9723-0334a8a76923",
      "parameters": {
        "path": "tripteller-upload",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "3e8ff04a-792d-4a04-99d7-e6b10c8aa105",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -256,
        -112
      ],
      "parameters": {
        "width": 304,
        "height": 416,
        "content": "📌 入口点"
      },
      "typeVersion": 1
    },
    {
      "id": "c35d16d4-226b-4a38-9214-3b9bbc7aca47",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        64,
        -112
      ],
      "parameters": {
        "height": 416,
        "content": "📌 数据提取"
      },
      "typeVersion": 1
    },
    {
      "id": "617d4322-bddb-4c82-92aa-649c85ebc714",
      "name": "便签2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        -112
      ],
      "parameters": {
        "height": 416,
        "content": "📌 照片分离"
      },
      "typeVersion": 1
    },
    {
      "id": "fe77f420-c0b9-4a87-8c83-9b98b4530fdf",
      "name": "便签3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        576,
        -256
      ],
      "parameters": {
        "height": 400,
        "content": "📌 二进制转换"
      },
      "typeVersion": 1
    },
    {
      "id": "54a27f54-7b44-48ff-ad0c-b00e402a641d",
      "name": "便签4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        576,
        160
      ],
      "parameters": {
        "height": 368,
        "content": "📌 元数据提取"
      },
      "typeVersion": 1
    },
    {
      "id": "9ffe7801-4a33-4015-b2cd-22a1b7a9874d",
      "name": "便签5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        832,
        -256
      ],
      "parameters": {
        "height": 400,
        "content": "📌 AI 图像分析"
      },
      "typeVersion": 1
    },
    {
      "id": "e1619f17-e377-43fd-8c92-c9b7ecd65cda",
      "name": "便签6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1264,
        -256
      ],
      "parameters": {
        "width": 256,
        "height": 544,
        "content": "📌 时间顺序组织"
      },
      "typeVersion": 1
    },
    {
      "id": "b073140d-6aec-4314-8f4f-35cbe692aae9",
      "name": "便签7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1536,
        -256
      ],
      "parameters": {
        "width": 352,
        "height": 544,
        "content": "📌 AI 故事创作"
      },
      "typeVersion": 1
    },
    {
      "id": "59dcd8e4-8970-464c-a002-aef80df9dd49",
      "name": "便签8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1904,
        -48
      ],
      "parameters": {
        "width": 304,
        "height": 336,
        "content": "📌 输出格式化"
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "pinData": {},
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "executionOrder": "v1",
    "executionTimeout": 300,
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "all"
  },
  "versionId": "496dfebf-ab04-45dd-a011-2695e4baaa83",
  "connections": {
    "Combine": {
      "main": [
        [
          {
            "node": "Group Photos by Day",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to File": {
      "main": [
        [
          {
            "node": "Vision Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Vision Analysis": {
      "main": [
        [
          {
            "node": "Combine",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Photos Array": {
      "main": [
        [
          {
            "node": "Split Photos Array",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Photo Attribs": {
      "main": [
        [
          {
            "node": "Combine",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Split Photos Array": {
      "main": [
        [
          {
            "node": "Convert to File",
            "type": "main",
            "index": 0
          },
          {
            "node": "Set Photo Attribs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Group Photos by Day": {
      "main": [
        [
          {
            "node": "Generate Travel Story",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Photo Upload Webhook": {
      "main": [
        [
          {
            "node": "Get Photos Array",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Final Response": {
      "main": [
        []
      ]
    },
    "Generate Travel Story": {
      "main": [
        [
          {
            "node": "Format Final Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

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

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

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

需要付费吗?

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

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

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

作者
inderjeet Bhambra

inderjeet Bhambra

@idsinghbhambra

I am on a journey to learn and spread the automations through n8n workflows.

外部链接
在 n8n.io 查看

分享此工作流