
1. 为什么我把第一个眼镜应用选在吃上先交代一下背景。我拿到 Rokid Glasses 的开发者预览机之后翻了半天文档脑子里蹦出来的第一个练手项目不是那种看起来很有科技感的复杂玩意儿而是一个极其朴素的需求戴眼镜的时候让眼镜告诉我今天吃什么。很多人一开始做眼镜应用容易犯一个毛病——想得太宏大。什么空间导航、多屏协同、AI 助理全家桶恨不得第一天就把所有能力全塞进去。我自己的经验是智能眼镜这个形态跟手机完全不同它是一个轻交互、强场景、短时间的设备用户戴上去之后注意力是跟着眼前的物理世界走的不是盯着屏幕的。所以第一个项目越具体、越能解决一个即刻需求越好。今天吃什么恰好是那种几乎人人都会遇到、又非常适合语音驱动的场景——不需要打字、不需要翻手机、几秒钟就要答案。这篇文章就把我从 0 到 1 开发这个今天吃什么AIUI 应用的完整过程拆开讲一遍包括环境准备、工程结构、语音交互的接入方式、推荐逻辑的落地点、以及我在真机上实测时踩过的一堆坑。适合刚接触 Rokid Glasses 开发、手头有设备或模拟器、想快速跑通一个完整应用的人参考。在开始写代码之前你得先理解一个关键问题Rokid Glasses 上跑的所谓AIUI 应用到底是一个什么东西1.1 它其实是一个跑在眼镜上的 YIUI 应用Rokid Glasses 的应用开发使用的是名为 YIUI 的界面框架底层逻辑和 Web 前端很像——你写 JS、写渲染描述、写样式最后通过设备上的运行时渲染到眼镜的显示模组上。但和手机 WebView 方案不同的是YIUI 是一套专门为 AR/眼镜形态优化的轻量渲染引擎它不需要完整浏览器那样的重资源占用而是通过一套声明式的 UI 描述语法来构建页面。我最初以为要写 Android 原生代码结果看完文档发现走的是 JS 这条路对前端背景的开发者来说非常友好。你不需要关心 OpenGL 渲染、不需要关心双目显示合成只需要关心页面长什么样和数据怎么来。AIUI 在这里扮演的角色则是整个应用的大脑输入通道。它负责把你的语音指令转换成结构化意图再把这个意图交给你的应用逻辑去处理。简单说你负责写听到指令之后干什么AIUI 负责让你听见指令。1.2 为什么今天吃什么是最佳新手项目选这个项目有几个很实际的原因。第一它天然是语音驱动的。你不会想在一副眼镜上打字搜索菜谱语音是唯一舒适的自然输入方式。这强迫你从一开始就习惯 AIUI 的思路设定唤醒词、定义意图、解析槽位、组织应答。第二它的 UI 极简。整个页面其实就是一个推荐结果 一个换一个按钮不需要复杂的列表、地图、滚动交互你可以在最短时间内跑通完整链路建立成就感。第三它的内容生成完全不依赖后台服务。用前端数组硬编码一个推荐池就能完成核心需求如果需要进阶再引入位置、天气、大模型都是后话。把一个逻辑链路走通比堆功能更能帮你理解平台的运行机制。2. 动手前的三件套硬件准备、开发账号、环境安装这个部分我不想一笔带过因为新手最容易在准备阶段被文档劝退。Rokid 的文档站其实写得还算清楚但信息分散在不同页面你需要自己拼出完整的安装路径。2.1 你需要准备什么项目说明Rokid Glasses 真机非必须但强烈建议很多传感器和语音能力在模拟器上表现打折USB Type-C 数据线用于连接眼镜和电脑部分版本需要专用连接线开发者账号在开放平台注册获取 AppKey 和 AppSecretYIUI CLI 工具用于创建工程、编译、打包、推送模拟器VS Code 或其他编辑器写 JS 代码用我用的 VS Code配合官方插件可以高亮 YIUI 语法真机和模拟器两个环境我后面会专门对比。这里先说你没有真机也能完成第一步——模拟器上可以跑 UI 页面和部分交互只是语音的模拟体验会比较奇怪。2.2 环境安装与账号激活先安装 Node.js LTS 版本然后全局安装 YIUI CLI。装完之后用开发者账号登录这个登录动作会在本地生成一个凭证之后所有的 build、push 操作都会用到。我在这一步卡过一次原因是公司网络代理导致 CLI 云端服务连接超时换成个人热点就正常了如果你也遇到莫名其妙的超时先查网络。需要说明的是账号激活和 App 创建都在网页端完成。创建一个新应用之后你会拿到一对 AppKey 和 AppSecret这个一定要保存好后面配置 AIUI 能力的时候要用。创建应用时选择类型为眼镜应用平台会自动帮你把 YIUI 工程模板相关的能力配好。2.3 工程模板与第一个运行CLI 安装完成后执行初始化命令按提示选择带 AIUI 能力的模板这样生成的工程里已经预置了语音相关的依赖和配置文件。# 创建工程名字自己起 yiui create what-to-eat # 进入工程目录 cd what-to-eat # 安装依赖 npm install # 启动本地开发服务会热更新代码到已连接的设备/模拟器 yiui dev第一次跑起来的时候不要急着写业务逻辑先在模拟器上确认页面能渲染、代码改动能热更。我当时是先改了主页的文字内容然后在模拟器上看到Hello YIUI变化成自己的内容才放心往后走。这一步看起来无关紧要但它是整个开发链路通畅的基准线。3. 从 0 到 1 的完整实现拆成三个可验证的阶段下面进入核心部分。为了保证每个阶段都能独立验证我把整个今天吃什么应用拆成了三个步骤每个步骤结束你都能看到明确成果。一次做一大坨在眼镜开发里特别难受因为真机调试成本高于手机一次改动太多很难定位问题。3.1 第一阶段搭出今天吃什么的页面骨架先不接语音做一个静态页面确认 UI 渲染链路没问题。在 YIUI 工程里页面的根文件通常是一个app.js或者页面入口 JS 文件在里面定义一个页面描述对象。YIUI 的页面描述风格比较接近 React Native 的样式对象但写法有自己的定义。你可以把它理解成用 JS 对象来描述你想要的界面。我先定义一个推荐结果的数据结构再写一个最简单的页面中间一个大号菜品名称下方一个按钮用来换一个。// app.js const DISHES [ { name: 宫保鸡丁, category: 川菜 }, { name: 番茄牛腩, category: 炖菜 }, { name: 扬州炒饭, category: 主食 }, { name: 清蒸鲈鱼, category: 粤菜 }, ]; Page({ data: { currentDish: DISHES[0], }, onReady() { this.$setData({ currentDish: DISHES[0] }); }, onNext() { const nextIndex Math.floor(Math.random() * DISHES.length); this.$setData({ currentDish: DISHES[nextIndex] }); }, });配套的渲染描述文件负责决定文本放在哪、按钮什么颜色、点击之后触发哪个回掉。YIUI 支持文本、图片、按钮、容器等基础组件写法类似小程序按键通过bindtap绑定事件。跑起来之后屏幕上应该显示宫保鸡丁四个大字点一下按钮就换成另一个。这一步验证的核心是工程链路通、页面渲染通、交互事件通。这时候还不涉及任何 AI 能力但你已经在这个眼镜上有了一个能用的应用。3.2 第二阶段接通 AIUI听懂今天吃什么页面骨架没有问题之后开始接入语音能力。Rokid Glasses 上的 AIUI 接入方式和手机端 SDK 有些区别。这里应用本身不直接与语音云端通信而是通过眼镜系统的 AIUI 服务来感知语音意图。在工程配置文件里你需要在入口文件头部声明依赖 AIUI 能力和对应的行为配置。这段配置的本质是告诉系统我的应用想监听哪些语音指令以及指令到达之后调用哪个动作。// 在入口文件顶部声明使用的 AIUI 能力 App({ globalData: { aiui: { enable: true, domain: what_to_eat, commands: [ { name: RECOMMEND_FOOD, phrases: [ 今天吃什么, 推荐一道菜, 给我安排一下今天吃什么, ], }, { name: CHANGE_DISH, phrases: [ 换一个, 换一道菜, 不想吃这个, ], }, ], }, }, });这段配置表达的是当系统识别到用户说出类似今天吃什么的话时向应用派发一个名为RECOMMEND_FOOD的语音意图。应用侧只需要监听这个意图名字然后执行自己的逻辑即可。页面里新增语音意图的监听代码Page({ // ... 上一阶段的逻辑 onAICommand(payload) { const { command } payload; if (command RECOMMEND_FOOD) { this.showRecommend(); } else if (command CHANGE_DISH) { this.onNext(); } }, });在真实设备上用户先唤醒设备比如说出你好眼镜或者按下侧边键唤醒然后说今天吃什么系统就会把这句话送入本地的语义理解匹配到RECOMMEND_FOOD指令后派发给应用。应用收到之后调用showRecommend()渲染推荐结果。这一步注意一个细节phrases里的示例句子不是硬匹配而是语义匹配。我一开始以为写死今天吃什么四个字才算触发后来发现我口头说中午不知道吃什么好了也应该被触发。实际效果是语义近似度匹配模板句给得越丰富识别准确率越高。建议覆盖早中晚、请求推荐、换一换等变化形式。3.3 第三阶段把推荐做出来再让眼镜开口说话前面的页面已经能通过按钮换一个了现在要把语音指令和推荐逻辑合起来并且让结果不只是看得到还要听得到。这一步就是 AIUI 相对普通 UI 应用最有意思的部分——语音播报反馈。眼镜的场景里用户很多时候不能低头看屏幕所以播报不是辅助功能而是主交互通道。在我的实现里showRecommend的逻辑是showRecommend() { let suggestion ; const hour new Date().getHours(); if (hour 6 hour 10) { suggestion 早餐来点清淡的推荐虾仁粥配小笼包; } else if (hour 10 hour 14) { suggestion 午餐要吃好推荐麻婆豆腐加米饭再来一份青菜; } else if (hour 14 hour 17) { suggestion 下午容易饿来一份点心吧蛋挞配美式咖啡; } else { suggestion 晚餐别吃太饱推荐清蒸鱼加凉拌黄瓜; } this.$setData({ currentDish: suggestion }); // 通过系统的语音合成接口播报结果 this.speak(suggestion); }, speak(text) { const SpeechRenderer require(system.speech); SpeechRenderer.speak({ text, onStart() {}, onComplete() {}, onError(err) { console.error(播报失败, err); }, }); },这里我用了简单的时间段逻辑来充当推荐策略还没上大模型和真实餐厅数据。但整个体验闭环已经通了用户用语音发出需求应用理解意图应用推荐结果眼镜把结果显示出来并且开口告诉你。这里有一个非常重要的经验播报文本要设计得短。眼镜的语音播报不同于手机喇叭用户戴在耳朵边一段话超过 10 秒会变得很煎熬。我在测试时写了一句长文案报菜名报到第二句我都想打断它了。后来我把所有反馈都压到两句话以内一句讲推荐一句讲理由。这也是做眼镜应用的通用原则输出内容必须比手机端更克制。4. 那些文档没写清楚的配置细节与平台边界这个坑位我单独列出来讲是因为我在这里浪费了很多时间。官方文档给了你主流程但有一些配置细节需要你自己摸索。4.1 应用密钥与 AIUI 能力的授权关系很多人以为 AppKey 和 AppSecret 只是在创建应用时用一次。实际上YIUI 工程打包成能在眼镜上运行的应用时必须把 AppKey 配置到工程里否则 AIUI 能力会静默失效——页面能正常渲染但语音指令怎么发都不来。这个配置入口一般不在主app.js里而是在工程的project.config.json或者类似的平台配置文件中。{ appKey: 你的_app_key, appSecret: 你的_app_secret, deviceConfig: { aiui: true, speech: true } }我在第一次接入时漏掉了speech配置导致语音合成接口调用后没有任何声响。查了半天发现不是代码问题而是设备侧压根没拿到语音能力授权。在确认代码逻辑无误之前先把这些开关都过一遍能省很多时间。4.2 闪屏与图标启动体验的真实感受眼镜应用的冷启动和手机很不一样。用户唤醒眼镜后再唤起应用等待的时间阈值比手机低得多。我最初没改应用闪屏用的是默认图标和默认启动页真机上唤醒应用时那种上个时代的界面突然出现的割裂感非常强。后来我花了一个小时做了两件事第一在配置里把应用显示名改成今天吃什么而不是默认工程名第二做了一个简单的启动图标使用纯色背景加一个餐盘剪影适配眼镜的圆形显示区域。这个投入很小但对体验的感知提升非常大。在眼镜这种穿戴设备上应用的第一印象往往比功能细节还重要因为用户的观看时间很短界面必须一眼就觉得这是专门为眼镜设计的。4.3 模拟器与真机的能力差异我在开发阶段大量使用模拟器但有几件事情模拟器是做不了或者不准的唤醒词检测模拟器没有麦克风阵列语音输入是模拟的无法真实体验唤醒延迟和误唤醒。光线/交互方式真机上的侧边按键和触摸板交互在模拟器里只能通过鼠标模拟。环境光下的显示效果模拟器上的对比度和真机差异很大特别是户外场景真机上偏暗的文字在模拟器上看起来完全正常。续航和发热这个只能在真机判断。我的今天吃什么在模拟器上跑得好好的真机上却发现高频调用语音播报会让镜腿温度上升后来我加了一个简单策略如果用户连续 3 次换一个播报频率自动降低为每两次播报一次屏幕显示保持更新。建议的开发节奏是日常逻辑用模拟器每完成一个完整闭环、要测试语音相关功能时一定要上真机。不要让模拟器上的看起来成功欺骗了你眼镜的真实体验只有戴在头上才知道。5. 我实测中踩过的坑从点击没反应到播报卡壳这部分是很多人最想看的。我按时间顺序记录几个印象深刻的坑以及对应的排查过程你会发现大部分问题都不是代码不会写而是代码逻辑与设备行为没对齐。5.1 坑一模拟器上 AIUI 指令一直收不到这是我的第一个大坑。按照模板做完之后页面正常显示但无论我怎么模拟输入今天吃什么这个指令都到不了onAICommand回调。排查过程先怀疑配置没生效把project.config.json里的aiui开关反复检查重写了两遍还是不行。然后去翻日志发现工程里没有任何关于意图识别的记录说明指令压根没到应用层。最后回到文档里细看发现模拟器默认没有开启语音语义识别的云端通道。你需要先在模拟器的系统设置里调用一次语音助手功能把它激活然后模拟器的 AIUI 链路才会真的接管模拟输入。解决方式在模拟器上点开系统自带的语音助手应用随便输入一句话看到模拟语音助手有回话之后再回到自己的应用里测试指令就好了。这是模拟器的一个软激活机制不亲自踩一遍真的很难想到。5.2 坑二真机上页面频繁白屏把同个包推到真机之后出现了另一个诡异问题页面偶尔会白屏特别是语音播报正在进行的时候操作界面白屏概率特别高。拆解下来问题出在我处理用户语音播报还没结束就又来了新指令的情况。YIUI 的页面渲染和语音播报在低功耗设备上是共享系统资源的播报中的音频处理会占用一部分 CPU如果此时我同时执行$setData更新大段文案渲染线程就可能被挤掉队表现为白屏一帧。修复方式有两个在播报期间锁住页面交互播报结束前不处理新的换菜请求。把播报文本的更新和页面文案的更新解耦页面先显示新菜品播报独立进行两条链路互不等待。我采用了第二种方案因为用户体验更自然——你说话换一个屏幕上应该立刻有反应而不是等 5 秒播报完再变。5.3 坑三意图触发串台还有一个在真机上非常有意思的问题。我测试时说今天吃什么结果系统的日程助手也弹出来了。排查后发现是唤醒后我的指令语句里带了今天两个字被系统的另一个全局意图模板也给匹配上了。这个问题本质上是平台级意图和应用级意图的竞争。解决方式是尽量避免指令模板和系统内置意图强相关把语义表达聚焦到推荐食物、换菜这两个更垂直的意图上并且在设备端把今天吃什么这类高频句子的优先级调高——在 AIUI 里配置意图的优先级数值数值越高这个应用越优先响应。这里也提醒你定义语音指令模板时尽量接近自然口语中的惯用短句不要加太多修饰词。像我之前写请帮我推荐一道菜五个字反而比推荐一道菜更容易被误识别成其他的意图。6. 做完今天吃什么下一步怎么进阶走到这一步你已经拥有一个完整的、能听会说能看的 Rokid Glasses AIUI 应用了。但这只是通过最小闭环认识平台。在我的经验里从跑通到好用之间还有几个值得投入的方向。6.1 加入用户偏好和位置感知现在的版本随机推荐用户不满意只能换一个。进阶版本可以记录用户的口味偏好通过语音直接设置我不吃辣 - 记录一条偏好数据。推荐个清淡的 - 结合记录过滤推荐池。更进一步眼镜有定位能力可以通过地理围栏感知用户是在家里、公司附近还是商圈然后调整推荐策略。比如在公司附近时推荐周边步行可达的简餐在家时就推荐适合外送的菜式。这些能力不一定全在应用侧实现有很多可以通过云端接口下发但用户的语音输入和最终的播报输出都发生在眼镜上。6.2 让推荐更有灵魂接入大模型能力静态推荐池最大的问题是没有灵魂——三次推荐之后用户就会发现规律应用变得无趣。我在第二版里接入了一个大模型接口每次用户说今天吃什么应用向云端发送一条携带上下文当前时间、用户偏好、最近几次的推荐记录的请求大模型返回一条个性化的推荐理由。实话说体验和静态推荐完全是两个层次——大模型推荐的今天天凉炖一锅番茄牛腩暖胃又省事这种话听起来就像真有人给你建议而不是一个随机数组在取模。做这一步注意一点给大模型的 Prompt 要限定输出长度。我一开始没做限制模型经常输出一大段餐厅点评级别的文本播报起来又臭又长。后来我在 Prompt 里明确要求推荐一种菜说明理由不超过两句话输出质量立刻可控了。6.3 多模态方向与后续扩展眼镜终究不只是语音设备。触摸板、头动交互、环境感知都能叠加到今天吃什么这个场景上结合摄像头识别菜品吃饭前对餐桌拍一下自动识别今天吃的什么生成饮食日记。结合健康监测数据如果当天运动量低推荐食谱时自动降低热量标签。结合多轮对话用户问这个菜怎么做眼镜直接给出步骤并逐步播报。这些方向背后是各自独立的开发主题但共同点是它们都建立在 AIUI 的意图理解、YIUI 的界面渲染、以及系统能力的组合之上。你把今天吃什么整个链路跑通之后再往任何一个方向走都会比别人从零开始顺得多。根据我的实际经验眼镜应用的迭代节奏比手机快了太多——用户戴着它的时候是真的在过生活而不是坐在桌前专心用 App。所以做这个平台上的应用最重要的不是堆功能而是让每个交互都刚好出现在它该出现的时刻然后见好就收。