这条在讲 Sohee Lee 给首尔明洞做的语音导览,整个明洞街区是她在 Three.js 里从 OSM footprint 一套搭出来的。出处是她的 dev.to 文章,投的 DEV 周末挑战赛。
我对 weekend challenge 的预期一向不高,默认是调一两个 API 包层皮、演示完就扔。这篇是读到作者原话「城市是我自己搭的,因为首尔没有公开的写实 3D 数据,Google 的 3D tiles 又不覆盖韩国」那一段,才确认值得写。没现成数据,这理由太硬了。
导览角色叫 Tobaggi(토박이),韩语里指那种生在一个街区、一辈子没搬走过的人。这个设定一下就立住了——游客从明洞站 6 号口出发,戴着耳机,跟着一个本地人的声音穿过真实街道。它讲的是你排队那家煎饺店从 1966 年就在蒸饺子,讲那栋哥特式天主堂当年庇护过抗议者。不是景点列表腔。
往根上说,这是态度。明洞在大多数人眼里只剩一家 TikTok 带火的餐厅加两片面膜,历史全没了,作者烦的就是这个。然后她没写文章抱怨,去把整座城搭出来。
技术上我摘几个觉得值钱的地方说。
3D 环境不是拿现成模型堆的。3535 个建筑 footprint 从 OpenStreetMap 来,在 Three.js 里按真实高度拉伸出体块,再用程序化窗格网格和彩色店面贴皮,尺度是真实米。清溪川从地图北边穿过去,给了一条会动的水流。这个“动”我挺在意——它不是静态盒子城。
路线也没糊弄。算法是 Dijkstra,在 OSM 的街道图上跑,所以 avatar 和真人在 GPS 模式下走的都是真实连通的路,从明洞站 6 号口开始,不会穿楼。
读的时候最抓我的是另一个细节:城市镜像首尔实时太阳位置,天黑之后窗户会亮灯,明洞下雨,app 里也下雨。URL 参数还能强制——?time=night 和 ?wx=rain。
我顺手跑了一下。
打开 demo 地址 myeongdong-3d.netlify.app,加 ?time=night,确实变成夜景,窗户亮得不算均匀,像真的。?wx=rain 也生效,雨点落下来,地面反光处理得不精致,但有那么一回事。GPS 模式我在屋里没法验证,只能说:路线计算的芯片是 Dijkstra 没错,作者代码写的也是这个,没跑现场,漂移情况不确定。
AI 在这项目里的角色很诚实,没硬蹭。
Gemini 3.5 Flash 写文案,负责 116 个景点餐厅加 66 家化妆品店的脚本,素材来自韩国旅游局介绍。ElevenLabs 出声音,用的 voice 叫 Amelia,原作者说这是平台上被用得最多的声音,一个英国口音的讲故事腔。
最妙的地方不是“AI 生成了语音导览”,而是 Amelia 要干五种不同的活:博物馆式景点街景、两个景点之间的地方史、离路警告、重播上一句、相册旁白。这说明作者没把 voice 当一个开关,拆成了不同叙事层。“你走偏了”和“这里的历史是这样的”不该是一个腔调。
照片功能也提一嘴。拍完照会盖上地点、时间、首尔真实天气。然后“Make my album”把照片发给 Gemini,注意,作者特意写了模型检查的是像素本身,不是位置标签,然后写第一人称配音。也就是说,它看画面里
