使用GPT-4创建播放列表和控制Spotify播放器
高级
这是一个Personal Productivity, AI Chatbot领域的自动化工作流,包含 29 个节点。主要使用 Set, Code, Spotify, SplitOut, SpotifyTool 等节点。 通过GPT-4创建播放列表并控制Spotify播放器
前置要求
- •OpenAI API Key
使用的节点 (29)
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"nodes": [
{
"id": "339943be-a10f-4749-8329-5e5b0322b7da",
"name": "OpenAI 聊天模型2",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
800,
1820
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini",
"cachedResultName": "gpt-4.1-mini"
},
"options": {
"responseFormat": "json_object"
}
},
"credentials": {
"openAiApi": {
"id": "G6pwE0s12sGlHRe3",
"name": "Plan A's OpenAI"
}
},
"typeVersion": 1.2
},
{
"id": "b3e4c3c9-7c39-457f-821a-588108b5a80d",
"name": "获取音轨ID",
"type": "n8n-nodes-base.set",
"position": [
2020,
1600
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a35cb340-5917-4981-9627-6c6189a0a0f4",
"name": "Track ID",
"type": "string",
"value": "={{ $json.id }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "79061ff4-a47d-430e-b964-80a3bf3945b5",
"name": "创建播放列表",
"type": "n8n-nodes-base.spotify",
"notes": "Create a blank playlist with the chosen name.",
"position": [
1140,
1600
],
"parameters": {
"name": "={{ $json.output.playlistName }}",
"resource": "playlist",
"operation": "create",
"additionalFields": {
"public": true
}
},
"credentials": {
"spotifyOAuth2Api": {
"id": "cF3ccMo4DndHdIe1",
"name": "Spotify account"
}
},
"notesInFlow": true,
"retryOnFail": true,
"typeVersion": 1
},
{
"id": "983f116f-9542-469e-8e09-7da7fe510c5b",
"name": "构思播放列表",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
780,
1600
],
"parameters": {
"text": "=# Playlist guidelines\n\n{{ $json['Playlist guidelines'] }}\n\n\n# Number of songs to include\n\n{{ $json['Number of tracks'] }}",
"messages": {
"messageValues": [
{
"message": "=# Role\n\nYou are a very experienced DJ and your task is to create a playlist of {{ $json['Number of tracks'] }} tracks and give it a name, based on the user message which contains the playlist instructions and number of tracks to include. \n\n# How to find the {{ $json['Number of tracks'] }} tracks to include within a playlist\n\nYou'll recommend an interesting and relevant mix of tracks, exactly {{ $json['Number of tracks'] }} tracks - ideally not from the same artist (except if the instructions tell so), nailing implementing the instructions given by the user message.\nFor each track you will (and this will be detailed later) provide the artist name and the title of the track.\n\nEvery artists and song should really exist. They have to be real songs reference - usually famous - but mix the styles.\n\n\n# How to craft the playlist title\n\nBased on the user message and the songs to fit into the playlist, the playlist name should be between 5 and 9 words and perfectly fit for a playlist name.\nIt is possible that the user message contains more direct instructions for the title.\n\n# Strict output format:\n\nHere's an example of your output so you have a good idea of the schema of the JSON output and a little idea of how the values can look like in the case of a 5-track playlist (but adapt the values to the user message!):\n\n\n{\n \"playlistName\":\"Summer dancing with a Spritz and attitude\",\n \"tracks\":[\n {\n \"artist\":\"David Guetta, Sia\",\n \"title\":\"Beautiful People\"\n },\n {\n \"artist\":\"Ed Sheeran\",\n \"title\":\"Azizam\"\n },\n {\n \"artist\":\"Doechii\",\n \"title\":\"Anxiety\"\n },\n {\n \"artist\":\"OneRepublic\",\n \"title\":\"Nobody (from Kaiju No.8)\"\n },\n {\n \"artist\":\"The Weeknd\",\n \"title\":\"Cry For Me\"\n }\n ]\n}\n\n\n"
}
]
},
"promptType": "define",
"hasOutputParser": true
},
"retryOnFail": true,
"typeVersion": 1.6
},
{
"id": "b82072f8-6326-4a13-871d-6bfe31e88ed3",
"name": "拆分音轨",
"type": "n8n-nodes-base.splitOut",
"position": [
1580,
1600
],
"parameters": {
"options": {},
"fieldToSplitOut": "Tracks"
},
"typeVersion": 1
},
{
"id": "0a6bc27b-77a0-4140-9169-c169f7d63f73",
"name": "获取音轨数组",
"type": "n8n-nodes-base.set",
"position": [
1360,
1600
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "c03ede2c-3d1a-4b94-ba72-d9ac518300d3",
"name": "Tracks",
"type": "array",
"value": "={{ $('Ideate playlist').item.json.output.tracks }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "a46ab606-6c84-4d48-bec6-cccac01c36d3",
"name": "OpenAI 聊天模型",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
760,
1100
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini",
"cachedResultName": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"id": "G6pwE0s12sGlHRe3",
"name": "Plan A's OpenAI"
}
},
"typeVersion": 1.2
},
{
"id": "26b67f87-659e-4e4c-a205-4b3d93288825",
"name": "当收到聊天消息时",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"position": [
580,
780
],
"webhookId": "e91b8adb-5fad-4414-aaae-fefd42178283",
"parameters": {
"public": true,
"options": {
"title": "Spotify Agent",
"subtitle": "Start a chat. We're here to play 24/7."
},
"initialMessages": "Hi there! 👋\nI'm your Spotify agent. What should I play for you today?"
},
"typeVersion": 1.1
},
{
"id": "27e65e5e-a9cf-4a02-89a5-c392ca4307e3",
"name": "简单记忆",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
1040,
1040
],
"parameters": {
"contextWindowLength": 6
},
"typeVersion": 1.3
},
{
"id": "21e3ed29-0a45-4d70-9aa5-b61f696491aa",
"name": "当被其他工作流执行时",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"position": [
560,
1600
],
"parameters": {
"workflowInputs": {
"values": [
{
"name": "Playlist guidelines"
},
{
"name": "Number of tracks",
"type": "number"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "d506e762-782e-4bc2-bbf6-c3d1b44c5bf1",
"name": "添加音轨到播放列表",
"type": "n8n-nodes-base.spotify",
"position": [
2240,
1600
],
"parameters": {
"id": "=spotify:playlist:{{ $('Create playlist').first().json.id }}",
"trackID": "=spotify:track:{{ $json[\"Track ID\"] }}",
"resource": "playlist",
"additionalFields": {}
},
"credentials": {
"spotifyOAuth2Api": {
"id": "cF3ccMo4DndHdIe1",
"name": "Spotify account"
}
},
"retryOnFail": true,
"typeVersion": 1
},
{
"id": "b1c48119-9e70-4424-8bad-34a347275ca8",
"name": "结构化输出解析器",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
920,
1820
],
"parameters": {
"jsonSchemaExample": "{\n \"playlistName\":\"Summer dancing with a Spritz and attitude\",\n \"tracks\":[\n {\n \"artist\":\"David Guetta, Sia\",\n \"title\":\"Beautiful People\"\n },\n {\n \"artist\":\"Ed Sheeran\",\n \"title\":\"Azizam\"\n },\n {\n \"artist\":\"Doechii\",\n \"title\":\"Anxiety\"\n },\n {\n \"artist\":\"OneRepublic\",\n \"title\":\"Nobody (from Kaiju No.8)\"\n },\n {\n \"artist\":\"The Weeknd\",\n \"title\":\"Cry For Me\"\n }\n ]\n}\n"
},
"typeVersion": 1.2
},
{
"id": "b7e89f85-4ad3-4675-bcec-06573f708842",
"name": "Spotify代理",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1040,
780
],
"parameters": {
"options": {
"systemMessage": "=You are a spotify assistant and are logged in to a spotify player.\n\n# Capacities\n\nYou have 2 sets of capacities, one is about controling the Spotify player of the user (play, pause, next) and one about managing playlist (creating, searching, playing).\n\n## Resume the player\n\nIf the user seems to ask you to resume the spotify player, use the tool \"Resume player\".\n\n## Pause the player\n\nIf the user seems to ask you to pause the spotify player, use the tool \"Pause player\"\n\n## Playing the next song\n\nIf the user is asking you to play the next song, use the tool \"Next song\" to play it in the user's Spotify player.\n\n\n## Creating a new playlist\n\nIf the user asks to create a new playlist, use the tool \"Create new playlist\" and pass the right guidelines so the playlist can be created. If you feel like you could use some more details from the user before creating it, feel free to ask or to ask to confirm what you had in mind before calling the tool.\nWhen you're done, it's always nice to inform the user about what has been put in.\n\n\n## Finding the user's current playlist\n\nIt can be useful to find the user's current playlists for example when they ask to play a previously created playlist for which you don't have the ID anymore (as the ID is required to play a playlist).\nTo achieve that, use the tool \"Get user playlists\".\n\n\n## Play a playlist\n\nTo play a playlist, you need to have the exact ID of the playlist to play which might require to call specific tools and once you have it you will call the tool \"Play a playlist\" and pass the right ID.\nNB: if the user asks you to play a playlist you had created in the previous message, you'll have to call the tool to find the user's playlist to get the ID of that playlist to play it.\n\n\n# Additional guidelines\n\nIt can happen that the user request requires to use multiple tools in a chain. For example if you're asked about playing a new playlist to create, you'll first create that playlist (using the right tool) and then play it (tool call) based on the ID received after creating that playlist.\nBe smart about managing those cases to provide the smoothest experience.\n\nIf you're not sure about the action you're supposed to do, feel free to suggest to ask for confirmation (but only do that when it's not clear - otherwise, execute).\n\n\n# Output tone and guidelines\n\nAs a Spotify assistant, your answers are concise, friendly, and only include the right level of information (don't mention playlist of track IDs but rather mention names, artists, authors when needed)."
}
},
"typeVersion": 1.9
},
{
"id": "ac1dcb16-a396-4d7f-b8f4-a3a4b5825fec",
"name": "获取最终播放列表",
"type": "n8n-nodes-base.spotify",
"position": [
2460,
1600
],
"parameters": {
"id": "=spotify:playlist:{{ $('Create playlist').item.json.id }}",
"resource": "playlist",
"operation": "get"
},
"credentials": {
"spotifyOAuth2Api": {
"id": "cF3ccMo4DndHdIe1",
"name": "Spotify account"
}
},
"executeOnce": true,
"typeVersion": 1
},
{
"id": "58581a2e-d7c1-45a7-bca7-c81ef11e6361",
"name": "清理数据以与代理共享",
"type": "n8n-nodes-base.code",
"notes": "This code simplifies the schema of the playlist we've just created to ensure that the AI agent gets clean information to process, balancing between context token savings and context.",
"position": [
2680,
1600
],
"parameters": {
"jsCode": "// The Get Playlist node returns an array, so we take the first item.\nconst playlistData = items[0].json;\n\n// Extract the playlist ID, name, and the direct public URL.\nconst playlistId = playlistData.id;\nconst playlistName = playlistData.name;\nconst publicUrl = playlistData.external_urls.spotify;\n\n// Create a simplified array of tracks.\nconst tracks = playlistData.tracks.items.map(item => {\n return {\n trackName: item.track.name,\n artist: item.track.artists[0].name,\n album: item.track.album.name,\n uri: item.track.uri\n };\n});\n\n// Return a new object with the final, simplified structure.\nreturn [{\n json: {\n playlistId,\n playlistName,\n publicUrl,\n tracks\n }\n}];"
},
"notesInFlow": true,
"typeVersion": 2
},
{
"id": "8769da3a-d7dc-4c4c-b80d-1f0360ab8b08",
"name": "播放播放列表",
"type": "n8n-nodes-base.spotifyTool",
"position": [
1240,
1040
],
"parameters": {
"id": "=spotify:playlist:{{ $fromAI('playlist_ID', `The exact ID of the playlist to play`, 'string') }}",
"operation": "startMusic",
"descriptionType": "manual",
"toolDescription": "Play a playlist based on its ID (don't call this tool until you have the Spotify ID of the playlist to play - this can require using other tools before)."
},
"credentials": {
"spotifyOAuth2Api": {
"id": "cF3ccMo4DndHdIe1",
"name": "Spotify account"
}
},
"typeVersion": 1
},
{
"id": "7054d5c8-97a0-45e9-8473-c9da361f3d07",
"name": "暂停播放器",
"type": "n8n-nodes-base.spotifyTool",
"position": [
1360,
1040
],
"parameters": {
"operation": "pause",
"descriptionType": "manual",
"toolDescription": "Use this tool to pose the player"
},
"credentials": {
"spotifyOAuth2Api": {
"id": "cF3ccMo4DndHdIe1",
"name": "Spotify account"
}
},
"typeVersion": 1
},
{
"id": "a28c277d-4c52-40ba-baac-e0539951fa88",
"name": "恢复播放器",
"type": "n8n-nodes-base.spotifyTool",
"position": [
1480,
1040
],
"parameters": {
"operation": "resume",
"descriptionType": "manual",
"toolDescription": "Use this tool to resume the player"
},
"credentials": {
"spotifyOAuth2Api": {
"id": "cF3ccMo4DndHdIe1",
"name": "Spotify account"
}
},
"typeVersion": 1
},
{
"id": "61d01ce7-fbf6-4471-8f1e-05690592c644",
"name": "下一首歌曲",
"type": "n8n-nodes-base.spotifyTool",
"position": [
1600,
1040
],
"parameters": {
"operation": "nextSong",
"descriptionType": "manual",
"toolDescription": "Use this tool to play the next song"
},
"credentials": {
"spotifyOAuth2Api": {
"id": "cF3ccMo4DndHdIe1",
"name": "Spotify account"
}
},
"typeVersion": 1
},
{
"id": "6d5b125c-9be0-4020-8fe5-17a4653bc5ca",
"name": "获取用户播放列表",
"type": "n8n-nodes-base.spotifyTool",
"position": [
1720,
1040
],
"parameters": {
"resource": "playlist",
"operation": "getUserPlaylists",
"returnAll": true,
"descriptionType": "manual",
"toolDescription": "Use this tool to get the user's playlists in Spotify"
},
"credentials": {
"spotifyOAuth2Api": {
"id": "cF3ccMo4DndHdIe1",
"name": "Spotify account"
}
},
"typeVersion": 1
},
{
"id": "95b32527-6992-4e04-b029-72b12eb424df",
"name": "创建新播放列表",
"type": "@n8n/n8n-nodes-langchain.toolWorkflow",
"position": [
1840,
1040
],
"parameters": {
"workflowId": {
"__rl": true,
"mode": "list",
"value": "PuNFGX6C0QCHB4cq",
"cachedResultName": "TEMPLATE - Spotify agent"
},
"description": "如果用户表达了创建新播放列表的需求,调用此工具获取播放列表创建器为用户创建播放列表。",
"workflowInputs": {
"value": {
"Number of tracks": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Number_of_tracks', `The number of tracks to include in the playlist. If no indication was given by the user, default to 10.`, 'number') }}",
"Playlist guidelines": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Playlist_guidelines', `Guidelines to help the playlist creator create this playlist. Keep it short, but include anything important to be able to create this playlist based on what the user requested (vibe, genre, artists if mentioned, etc).`, 'string') }}"
},
"schema": [
{
"id": "Playlist guidelines",
"type": "string",
"display": true,
"required": false,
"displayName": "Playlist guidelines",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Number of tracks",
"type": "number",
"display": true,
"required": false,
"displayName": "Number of tracks",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
}
},
"typeVersion": 2.2
},
{
"id": "c212fc80-f3c7-4af7-a684-7263786b5cf6",
"name": "搜索音轨",
"type": "n8n-nodes-base.spotify",
"position": [
1800,
1600
],
"parameters": {
"limit": 1,
"query": "={{ $json.artist }} - {{ $json.title }}",
"filters": {},
"resource": "track",
"operation": "search"
},
"credentials": {
"spotifyOAuth2Api": {
"id": "cF3ccMo4DndHdIe1",
"name": "Spotify account"
}
},
"retryOnFail": true,
"typeVersion": 1
},
{
"id": "31f5d94d-537c-4884-8b47-e92855dc4c74",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
-100,
640
],
"parameters": {
"width": 500,
"height": 820,
"content": "## 试试看!"
},
"typeVersion": 1
},
{
"id": "28f5c61a-e68a-480a-8397-07859e22bfec",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
480,
640
],
"parameters": {
"color": 7,
"width": 260,
"height": 300,
"content": "## 聊天触发器和界面"
},
"typeVersion": 1
},
{
"id": "4d5cf43a-adbf-48b7-9d03-6829ebc3df06",
"name": "便签2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1220,
1000
],
"parameters": {
"color": 7,
"width": 760,
"height": 280,
"content": ""
},
"typeVersion": 1
},
{
"id": "808d74d1-2cb5-40a1-a676-48ed0b96eb2f",
"name": "便签3",
"type": "n8n-nodes-base.stickyNote",
"position": [
960,
640
],
"parameters": {
"color": 7,
"width": 760,
"height": 280,
"content": "## 代理工具"
},
"typeVersion": 1
},
{
"id": "c732f125-979f-4b7a-a6cd-c0da989e3f35",
"name": "便签4",
"type": "n8n-nodes-base.stickyNote",
"position": [
760,
1420
],
"parameters": {
"color": 7,
"width": 300,
"height": 500,
"content": "## AI代理工具"
},
"typeVersion": 1
},
{
"id": "eaa0799a-c0e4-47d6-95ab-5f6f22d4cd58",
"name": "便签5",
"type": "n8n-nodes-base.stickyNote",
"position": [
480,
1340
],
"parameters": {
"color": 7,
"width": 2400,
"height": 660,
"content": "## AI步骤规划播放列表"
},
"typeVersion": 1
},
{
"id": "ff704841-7686-485b-b53f-afb220c809a5",
"name": "便签6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1540,
1460
],
"parameters": {
"color": 7,
"width": 840,
"height": 320,
"content": "## 播放列表创建子工作流"
},
"typeVersion": 1
}
],
"connections": {
"Next song": {
"ai_tool": [
[
{
"node": "Spotify Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Pause player": {
"ai_tool": [
[
{
"node": "Spotify Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Get track IDs": {
"main": [
[
{
"node": "Add track to playlist",
"type": "main",
"index": 0
}
]
]
},
"Resume player": {
"ai_tool": [
[
{
"node": "Spotify Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[
{
"node": "Spotify Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Create playlist": {
"main": [
[
{
"node": "Get tracks array",
"type": "main",
"index": 0
}
]
]
},
"Ideate playlist": {
"main": [
[
{
"node": "Create playlist",
"type": "main",
"index": 0
}
]
]
},
"Play a playlist": {
"ai_tool": [
[
{
"node": "Spotify Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Get tracks array": {
"main": [
[
{
"node": "Split out tracks",
"type": "main",
"index": 0
}
]
]
},
"Search the track": {
"main": [
[
{
"node": "Get track IDs",
"type": "main",
"index": 0
}
]
]
},
"Split out tracks": {
"main": [
[
{
"node": "Search the track",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "Spotify Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Get user playlists": {
"ai_tool": [
[
{
"node": "Spotify Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"OpenAI Chat Model2": {
"ai_languageModel": [
[
{
"node": "Ideate playlist",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Create new playlist": {
"ai_tool": [
[
{
"node": "Spotify Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Add track to playlist": {
"main": [
[
{
"node": "Get the final playlist",
"type": "main",
"index": 0
}
]
]
},
"Get the final playlist": {
"main": [
[
{
"node": "Clean data to share with agent",
"type": "main",
"index": 0
}
]
]
},
"Structured Output Parser": {
"ai_outputParser": [
[
{
"node": "Ideate playlist",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"When chat message received": {
"main": [
[
{
"node": "Spotify Agent",
"type": "main",
"index": 0
}
]
]
},
"When Executed by Another Workflow": {
"main": [
[
{
"node": "Ideate playlist",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 个人效率, AI 聊天机器人
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
在可视化参考库中探索n8n节点
在可视化参考库中探索n8n节点
If
Ftp
Set
+93
113 节点I versus AI
其他
上下文混合RAG AI文案
Google Drive到Supabase上下文向量数据库同步用于RAG应用
If
Set
Code
+25
76 节点Michael Taleb
AI RAG 检索增强
构建基于Supabase和GPT-5的高级多查询RAG系统
构建基于Supabase和GPT-5的高级多查询RAG系统
If
Set
Filter
+13
22 节点Guillaume Duvernay
AI RAG 检索增强
BambooHR AI 驱动的公司政策和福利聊天机器人
BambooHR AI 驱动的公司政策和福利聊天机器人
Set
Filter
Bamboo Hr
+20
50 节点Ludwig
人力资源
使用GPT-4和可复用思考工具创建多步推理AI代理
使用GPT-4和可复用思考工具创建多步推理AI代理
Agent
Chat Trigger
Lm Chat Open Ai
+4
11 节点Guillaume Duvernay
工程
文档代理模板
使用Gemini和Google Drive从模板创建自定义PDF文档
If
Set
Code
+13
36 节点Ozgur Karateke
文档提取