
1. 从“想做个生日惊喜”到“手势点蜡烛”这件事先说清楚这篇要交付什么一个能在浏览器里跑起来的手势识别点蜡烛页面。打开摄像头握拳点燃蜡烛张开手掌吹灭吹灭后自动播放生日快乐歌并撒彩带。适合谁完全没写过前端、但想快速做出一个能当场演示的 AI 交互页面的朋友。核心检索词就三个Trae、SOLO 模式、HTML 手势识别。我自己的起点特别朴素——朋友下周生日想搞个不一样的互动页面翻了一圈现成的不是收费就是丑干脆自己做。问题是我不太会写 HTML标签都背不全。后来发现 Trae 的 SOLO 模式可以全程用大白话描述需求AI 自动生成整个项目文件我只需要在浏览器里点开验证效果。整个过程里我一行代码没手写但最后拿到的是一个真实可运行的页面。不过这里有个容易被忽略的环节AI 生成代码、调试报错、反复改需求这些动作背后都要调用大模型。如果你同时用好几个 AI 工具每个都要单独配 Key、单独管额度很快就会乱。我的做法是用 TaoToken 做统一的 Key 和 API 通道一个 Key 走通所有接入省掉到处找配置的麻烦。下面我会把 Trae SOLO 生成页面的完整过程、可复制的 HTML 骨架、手势识别配置片段、浏览器验证动作以及中间踩过的坑全部拆开讲一遍。2. 前置准备TaoToken 统一 Key 与 Trae SOLO 模式2.1 为什么先讲 TaoTokenTrae 的 SOLO 模式本质是让 AI 读你的自然语言需求然后生成、修改、调试代码。这个链路里模型调用是核心。如果你只用一个工具可能感觉不到问题但当你既要生成代码、又要排查报错、还想换个模型对比效果时每个平台单独申请 Key、单独记额度管理成本会迅速上升。TaoToken 在这里的角色是统一入口一个 Key 覆盖多种模型调用API 地址统一接入文档清晰。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 。你不需要把它想复杂就当成一个“Key 管理中心 调用通道”即可。具体操作上先去控制台创建 API Key然后在你使用的 AI 工具里把 API 地址和 Key 填进去。如果你用的是 Claude Code 这类编码工具接入文档里有对应的配置说明。这一步做完后面 Trae 生成代码、调试报错时模型调用就走同一条通道不用来回切换。2.2 Trae 的两种模式怎么选Trae 有 IDE 模式和 SOLO 模式。IDE 模式适合有基础的人自己改代码SOLO 模式是 AI 全自动开发。零基础直接选 SOLO别犹豫。新建项目时选 SOLO然后在对话框里用大白话描述你要什么。我当时的原话是这样的做一个网页版互动生日蛋糕打开摄像头用手握拳点燃蜡烛张开手掌把它吹灭吹灭后自动播放生日快乐并撒彩带、放礼炮庆祝可重新许愿。你看完全是说人话。AI 等了十几秒直接生成了一个完整的 HTML 文件还自动打开了预览窗口。火焰在跳摄像头也启动了。2.3 需要准备的环境一台有摄像头的电脑或手机建议用 Chrome 浏览器打开。不需要装任何 APP不需要额外依赖。摄像头权限在浏览器里授权即可。如果你在本地打开 HTML 文件时摄像头不工作大概率是浏览器安全策略问题后面排障章节会讲。3. 可复制配置HTML 骨架与手势识别片段3.1 页面整体结构Trae 生成的 HTML 文件结构其实不复杂核心就三块视频采集区、蜡烛与火焰渲染区、手势识别逻辑区。下面是我整理后的可复制骨架你可以直接存成 index.html。!DOCTYPE html html langzh-CN head meta charsetUTF-8 / meta nameviewport contentwidthdevice-width, initial-scale1.0 / title手势点蜡烛/title style body { margin: 0; background: #0b0b1a; display: flex; flex-direction: column; align-items: center; } #video { width: 320px; height: 240px; border-radius: 12px; transform: scaleX(-1); } #stage { position: relative; width: 320px; height: 360px; } #candle { position: absolute; bottom: 40px; left: 50%; transform: translateX(-50%); width: 40px; height: 160px; background: linear-gradient(#ffe9a8, #f5c542); border-radius: 8px; } #flame { position: absolute; bottom: 200px; left: 50%; transform: translateX(-50%); width: 26px; height: 46px; background: radial-gradient(circle at 50% 70%, #fff6b0, #ff9d00 60%, transparent 70%); border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%; animation: flicker 0.18s infinite alternate; } keyframes flicker { from { transform: translateX(-50%) scale(1); opacity: 0.9; } to { transform: translateX(-50%) scale(1.12); opacity: 1; } } .off #flame { display: none; } /style /head body video idvideo autoplay playsinline/video div idstage div idcandle/div div idflame/div /div audio idbirthday srcbirthday.mp3/audio script srchttps://cdn.jsdelivr.net/npm/mediapipe/hands/hands.js/script script srchttps://cdn.jsdelivr.net/npm/mediapipe/camera_utils/camera_utils.js/script script // 手势识别逻辑见下一节 /script /body /html这段骨架里火焰用 CSS 动画做跳动感蜡烛用渐变模拟蜡身视频区做了镜像翻转这样你抬手时画面方向才符合直觉。3.2 手势识别配置片段手势识别用的是 MediaPipe Hands它能输出 21 个手部关键点。判断握拳还是张开核心看手指尖和指根的距离关系。下面这段是 Trae 生成后我整理过的逻辑const video document.getElementById(video); const stage document.getElementById(stage); const birthday document.getElementById(birthday); let candleOn true; function isFist(landmarks) { // 指尖索引8 12 16 20指根索引5 9 13 17 const tips [8, 12, 16, 20]; const bases [5, 9, 13, 17]; let folded 0; for (let i 0; i tips.length; i) { const tip landmarks[tips[i]]; const base landmarks[bases[i]]; if (tip.y base.y) folded; // y 越大越靠下说明手指卷曲 } return folded 3; } function isOpenPalm(landmarks) { const tips [8, 12, 16, 20]; const bases [5, 9, 13, 17]; let extended 0; for (let i 0; i tips.length; i) { const tip landmarks[tips[i]]; const base landmarks[bases[i]]; if (tip.y base.y) extended; } return extended 4; } const hands new Hands({ locateFile: (f) https://cdn.jsdelivr.net/npm/mediapipe/hands/${f} }); hands.setOptions({ maxNumHands: 1, modelComplexity: 0.7, minDetectionConfidence: 0.6, minTrackingConfidence: 0.6 }); hands.onResults((results) { if (!results.multiHandLandmarks || results.multiHandLandmarks.length 0) return; const lm results.multiHandLandmarks[0]; if (isFist(lm) !candleOn) { candleOn true; stage.classList.remove(off); } if (isOpenPalm(lm) candleOn) { candleOn false; stage.classList.add(off); birthday.currentTime 0; birthday.play(); } }); const camera new Camera(video, { onFrame: async () { await hands.send({ image: video }); }, width: 320, height: 240 }); camera.start();这里有两个关键参数minDetectionConfidence和minTrackingConfidence默认 0.5 容易误判我调到 0.6 之后稳定很多。modelComplexity设 0.7 是精度和性能的折中手机上也跑得动。3.3 音频与彩带生日快乐歌用一个 audio 标签加载本地 mp3吹灭时触发播放。彩带效果可以用简单的 canvas 粒子或者直接引入轻量库。Trae 当时生成的是 canvas 粒子版本逻辑不复杂核心是吹灭时启动粒子动画循环。如果你不想写粒子用 CSS 动画做几个飘落的小方块也能凑合演示够用。4. 验证请求浏览器里跑一遍看结果4.1 本地打开与摄像头授权把 index.html、birthday.mp3 放在同一个文件夹双击 index.html 用 Chrome 打开。浏览器会弹出摄像头授权点允许。如果视频区是黑的先检查是不是被其他程序占用了摄像头或者地址栏左侧的摄像头图标是不是被禁用了。4.2 验证动作清单打开页面后按这个顺序验证第一看火焰是否在跳动。如果火焰静止说明 CSS 动画没生效检查keyframes flicker有没有被覆盖。第二把手放到摄像头前握拳。观察火焰是否出现如果之前是熄灭状态。这里注意握拳判断的是四指卷曲不是拇指。第三张开手掌五指伸直。火焰应该消失同时生日快乐歌开始播放。第四再次握拳火焰重新出现音乐停止。第五换一只手、换不同距离再试看识别是否稳定。4.3 成功结果长什么样成功时你会看到视频区实时显示手部画面蜡烛和火焰叠加在下方握拳和张开切换时火焰有明确的出现和消失音乐在吹灭瞬间响起。整个页面不需要刷新手势切换是实时的。如果这些都对上了说明链路通了。5. 本篇常见错排查5.1 摄像头打不开或黑屏最常见的原因是浏览器安全策略。本地双击打开 HTML 时部分浏览器会限制摄像头访问。解决办法有两个一是用 Chrome 并确保地址栏左侧摄像头权限是允许二是起一个本地静态服务比如在文件夹里执行python -m http.server 8000然后访问http://localhost:8000。localhost 被视为安全上下文摄像头权限更稳。5.2 手势识别不准或误判如果握拳被识别成张开或者反过来先调minDetectionConfidence和minTrackingConfidence从 0.5 提到 0.6 甚至 0.65。其次检查光照背光或太暗都会影响关键点检测。再就是手离摄像头太远21 个关键点会飘建议手部占据画面三分之一以上。我试过在对话框里直接跟 Trae 说“只有握拳才算点燃只有手掌张开才算熄灭其他手势忽略”它会把判断逻辑改得更严格误判明显减少。5.3 音乐不播放Chrome 有自动播放策略音频必须由用户交互触发。如果你的页面在没有任何点击的情况下直接调play()可能被拦截。解决办法是加一个“开始”按钮用户点一下之后再启动摄像头和音频上下文。或者确保birthday.play()是在手势识别回调里触发的这算用户交互的一种通常能放行。5.4 MediaPipe 加载失败如果控制台报 Hands 未定义检查 CDN 地址是否可访问。国内网络环境下jsdelivr 有时不稳定。可以换成本地引入把 hands.js 和 camera_utils.js 下载到本地改 script 的 src 路径。这一步用 Trae 也能直接说“把 MediaPipe 改成从本地加载”它会帮你改好引用。5.5 火焰位置偏移火焰和蜡烛的位置靠 CSS 的 absolute 定位。如果你改了视频区尺寸火焰可能对不上蜡烛。检查#flame的bottom值和#candle的高度是否匹配。简单办法是给 stage 一个固定宽高内部元素按比例定位。6. 接入与排障用 TaoToken 统一通道收尾整个流程跑下来你会发现真正花时间的不是写代码而是调试和反复改需求。Trae SOLO 模式负责生成和修改但模型调用这条链路如果每个工具单独配很容易乱。我的做法是统一走 TaoToken在控制台创建 API Key把 API 地址填成 https://taotoken.net/api 然后在接入文档里找到对应工具的配置方式。这样不管是生成代码、排查报错还是换模型对比效果都走同一个 Key不用来回切换。如果你在排障阶段遇到模型调用报错优先检查 Key 是否有效、额度是否充足、API 地址是否填对。接入文档里有常见错误码的说明对着查很快。验证模型是否正常响应可以用模型对话入口发一条测试消息确认通道通了再回到 Trae 里继续调试。长期做编码和 Agent 类任务的话Coding Plan 更适合持续调用不用每次单独配。回到这个手势点蜡烛页面本身它最大的价值不是技术多复杂而是证明了一件事零基础的人也能用自然语言做出可演示的 AI 交互页面。你不需要先学三个月 HTML只需要把需求说清楚剩下的交给工具。摄像头、手势识别、音频播放、动画效果这些在以前要查很多文档的东西现在描述清楚就能生成。做完之后把文件夹打包发给朋友打开就能玩。