让故事拥有自己的配乐:一个会编排“音乐旅程”的开源 AI 助手
你有没有想过,一期播客、一场展览、甚至你普通的一天,都可以拥有一条专属的「音乐时间线」?我做了一个开源的音乐推荐 Agent:用一句自然语言描述心情或故事,系统会自动理解情绪曲线、拆分阶段,并通过 Spotify / 网络搜索为每一段挑选合适的歌曲,实时以流式形式展示整条音乐旅程。本文会介绍它的设计思路、核心实现,以及 GitHub 仓库,欢迎拿去魔改成你的作品。
写在前面:为什么我想做一个「音乐旅程」推荐器?
日常我们用的音乐应用,大多停留在「单首歌推荐 / 歌单推荐」层面:
今天想听点轻松的、来点运动节奏、或者按歌手/风格随便刷一刷。
但很多场景,其实更接近一段「旅程」而不是一个静态列表,比如:
- 一天的情绪曲线:通勤 → 工作专注 → 下班放松 → 夜晚窗边发呆
- 一场展览或活动:开场铺垫 → 氛围拉满 → 收尾平静
- 一期播客/视频:从讲述故事,到情绪爆点,再到余韵回落
这次更新,我给项目加上了一个全新的能力——音乐旅程编排(Music Journey):
它不只是推荐几首歌,而是按照故事 / 情绪曲线自动分段,为每一段生成一小段「配乐章节」。
下面基于这次重构后的项目,整理一篇完整介绍,也顺便推荐一下 GitHub 仓库。
一、项目简介:音乐推荐 Agent
这个项目的定位是一个开源的 「音乐推荐 Agent」:
用一句自然语言,串起心情、场景与故事的整条音乐旅程。
你可以像和朋友聊天一样对它说:
- 「给我一份适合深夜加班写代码的歌单」
- 「我想在雨天窗边听些治愈的独立民谣」
- 「根据周杰伦,帮我找一些同样浪漫的中文 R&B」
- 「帮我为一个展览设计 60 分钟的音乐旅程,从好奇到平静,再到感动」
系统会通过 LLM + LangGraph 工作流理解你的意图,再联动 Spotify、网络搜索和本地数据,给出带解释的推荐结果。
二、核心功能一览
当前版本已经支持以下几个核心能力:
-
自然语言驱动的音乐推荐:
心情 / 场景 / 歌手 / 流派,一句话描述需求即可。
-
可解释推荐:
不只是「给你一堆歌」,还会用一小段自然语言解释:
为什么是这些风格、为什么是这个艺术家、为什么放在这个位置。 -
歌曲网络推荐 / 搜索:
- 优先通过 Spotify MCP + 在线乐库 搜索歌曲
- 失败时回退到 Tavily 网络搜索 提取歌曲信息
- 还可以退回到本地示例库做模糊匹配
这一层已经从简单「本地搜索」升级成真正意义上的 网络级音乐检索 +推荐。
-
音乐旅程编排(Music Journey)(本次重点):
- 输入一个故事或情绪时间线(mood timeline)
- 自动划分为多个阶段(Segments)
- 每个阶段给出情绪标签、文字描述与对应推荐歌曲
- 前端通过 SSE 流式展示整个旅程的结构和配乐

-
SSE 流式体验:
- 推荐说明逐词输出,像「打字机」一样
- 歌曲逐首添加到列表里
- 状态(思考中 / 获取推荐中 / 完成)实时刷新
-
RESTful API + 前后端分离:
- 后端:FastAPI + LangGraph
- 前端:Next.js 14 + TypeScript
- 提供
/api/recommendations、/api/search、/api/journey等接口,方便二次集成。
三、重点展开:音乐旅程编排(Music Journey)
1. 使用场景
这个功能特别适合这些场景:
-
播客 / 视频创作者:
想要一条「叙事感」很强的配乐线,跟着故事起伏走。 -
展览 / 装置艺术 / 线下空间:
希望在一定时间内,音乐跟着观众情绪变化而变化:
从好奇 → 沉浸 → 共鸣 → 平静。 -
长时间专注 / 学习 / 写作:
不想只是重复一首 BGM,而是情绪有规划地缓慢演进。
2. 你需要提供什么?
你可以给系统两种输入方式(任选其一):
-
故事文本(
story):
比如「我想为一整天的工作设计音乐,从清晨通勤开始,到夜晚回家整理心情。」 -
情绪时间点序列(
mood_transitions):
例如:[ { "time": 0.0, "mood": "好奇", "intensity": 0.4 }, { "time": 0.3, "mood": "专注", "intensity": 0.7 }, { "time": 0.7, "mood": "激动", "intensity": 0.8 }, { "time": 1.0, "mood": "平静", "intensity": 0.5 } ]
另外可以指定一个总时长(比如 60 分钟),系统会据此进行分段。
3. 系统会做什么?
在后端,MusicJourneyService 会做这几件事:
-
情绪/故事分析
- 如果传入
story,先用 LLM 根据文本抽取几个关键阶段和情绪基调。 - 如果传入
mood_transitions,则直接使用你给的情绪时间线。
- 如果传入
-
阶段划分(Segments)
- 把总时长切分为若干阶段(一般 3–6 段),每一段有:
mood:这一段的主要情绪(如:放松、专注、激昂、平静)description:简短的文字描述duration:预计时长intensity:情绪强度(0–1)
- 把总时长切分为若干阶段(一般 3–6 段),每一段有:
-
为每一段选歌
- 基于这一段的情绪、描述及用户偏好,调用推荐工具为该段挑选合适的歌曲列表。
- 保证同一段内部风格相对统一,而不同段之间有合理过渡。
-
流式输出(SSE)
/api/journey/stream会以 SSE 形式,依次推送:- 整体旅程信息(总段数、总时长、总歌曲数)
- 每一段的
segment_start、segment_complete - 每段中的歌曲
song事件
- 前端可以边接收边渲染,实时看到「旅程的结构」被构建出来。
4. 前端体验
在前端,项目提供了一个「音乐旅程」页面(对应 README 里的截图):
- 顶部是你输入故事/情绪的区域;
- 中间是阶段卡片(每段一个 card,展示 mood / 描述 / 预计时长);
- 底部是每个阶段下的歌曲列表。
配合 SSE,整个过程很像实时“排片+配乐”的导演台:
你能看到系统如何把一段模糊的体验,拆分成一条有结构的音乐时间线。
四、架构与技术栈(简述)
后端:
- FastAPI:提供 REST & SSE 接口
- LangGraph:负责任务编排(意图识别、搜索、推荐、解释)
- MCP 工具层:对接 Spotify、SiliconFlow、Tavily 搜索等
- Pydantic / asyncio:数据建模与异步执行
前端:
- Next.js 14(App Router)+ TypeScript
- React Hooks + 自定义组件(推荐页、搜索页、旅程页等)
- 自己实现的 SSE 客户端(
fetch + ReadableStream),兼容 POST 请求
数据与配置:
- 本地示例数据:
data/music_database.json - 外部配置:
setting.json或环境变量 - 详细的数据流与节点说明在仓库的
SSE_DATAFLOW.md中也有完整文档。
五、如何本地快速体验?
后端 & 前端分别启动:
# 后端
python run_api_server.py # 默认 http://localhost:8501
# 前端
cd web
npm install
npm run dev # 默认 http://localhost:3000
打开浏览器访问:
http://localhost:3000/recommendations—— 体验流式音乐推荐http://localhost:3000/search—— 体验歌曲网络搜索 / 推荐- 音乐旅程页面(如果你已经打开 README 截图中对应路由)—— 体验故事驱动的音乐旅程编排
六、GitHub 仓库地址
仓库已经开源,代码和文档都在这里:
- GitHub:https://github.com/imagist13/Muisc-Research
仓库里已经包含:
- 完整的 README(本篇文章内容的代码版)
- API 说明、SSE 数据流设计文档
- MCP 工具与测试脚本(例如
test_music_mcp.py)
如果你:
- 正在做音乐相关产品、播客/视频配乐工具;
- 想学习「LLM + LangGraph + MCP + SSE」这一整套落地链路;
- 或者只是想有一个好玩的「情绪驱动音乐旅程」小玩具,
欢迎直接 clone 下来玩一玩,也非常欢迎在 GitHub 提 issue / PR 一起完善。
更多推荐



所有评论(0)