uniCloud Serverless 实战:英语学习小程序全链路开发

简介:这是一套面向英语学习者与小程序开发者的完整项目源码,基于uniapp与uniCloud Serverless架构构建,可直接在微信环境中运行。项目集生词本记录、拍照识别单词、内置词典查询、AI语音翻译、跟读打分评测于一体,并针对考研人群补充了专项学习资源,适合想练手全栈小程序开发或自建英语学习工具的读者参考。压缩包共288个文件,约15.13MB,以js逻辑、json配置、vue页面组件为主,辅以scss样式、png与jpg图片素材、md说明文档及字体文件,结构清晰,便于按模块阅读与二次开发。资源内附使用说明与开发文档,可帮助理解各功能实现细节与后端扩展方式。目前已有52人学习,适合具备一定前端基础、希望深入uniCloud实践的学习者。

1. 橙事英语小程序:Serverless 架构下的英语学习工具到底怎么落地

去年帮一个做考研英语培训的朋友看需求,他张口就要「拍照识词 + 跟读打分 + 生词本 + AI 翻译」四件套,预算却只够一个前端。这种场景下,传统「买服务器 + 配 Nginx + 写后端接口」的路子基本走不通——光运维和备案就够喝一壶。橙事英语这类基于 uniapp + uniCloud Serverless 架构的英语学习微信小程序,解决的正是这个矛盾:前端一套代码跑微信小程序,后端逻辑全部托管在 uniCloud 的云函数和云数据库里,没有独立服务器,没有运维,按调用量付费。

它适合谁?一是想快速验证英语学习类产品形态的独立开发者,二是手里有内容资源但缺后端人力的教培团队,三是想拿一个完整 Serverless 小程序案例练手的学生。核心功能链路其实就四条:拍照识别单词走 OCR 云函数,词典查询走第三方 API 聚合,跟读打分走语音评测接口,生词本走云数据库增删改查。把这四条链路跑通,整个项目骨架就立住了。下面按「架构选型 → 拍照识词 → 词典与生词本 → 语音跟读 → 避坑 → 进阶」的顺序拆开讲。

2. uniapp + uniCloud 的架构选型:为什么不用传统后端

2.1 Serverless 在这个项目里省掉了什么

传统小程序后端至少要一台云服务器跑 Node 或 Java,还要配数据库、对象存储、HTTPS 证书、域名备案。一个考研英语工具类小程序,日活可能就几百到几千,服务器常年闲置却要按月付费。uniCloud 把这层全托管了:云函数按调用次数计费,云数据库按读写次数计费,云存储按容量和流量计费。项目冷启动阶段,费用几乎可以忽略。

更关键的是开发效率。uniapp 的uniCloud.callFunction直接在前端调用云函数,不需要自己封装 HTTP 请求、处理跨域、管理 token 刷新。云函数里uniCloud.database()直接操作数据库,权限规则在schema里声明,前端拿到的就是过滤后的数据。这套东西对单人开发者极其友好。

但 Serverless 不是银弹。云函数有冷启动延迟,首次调用可能 1 到 3 秒;单次执行有超时限制,默认 5 秒,复杂 OCR 或语音评测要留意;云数据库查询有单次返回条数上限。这些边界决定了架构怎么切分。

2.2 目录结构与云函数划分

一个能跑起来的 uniCloud 项目,目录大致长这样:

project/ ├── pages/ │ ├── index/ # 首页 │ ├── camera/ # 拍照识词 │ ├── dict/ # 词典查询 │ ├── wordbook/ # 生词本 │ └── read/ # 跟读打分 ├── uniCloud-aliyun/ │ ├── cloudfunctions/ │ │ ├── ocr-word/ # 拍照识别 │ │ ├── dict-query/ # 词典查询 │ │ ├── wordbook-crud/ # 生词本增删改查 │ │ └── speech-score/ # 跟读打分 │ └── database/ │ └── wordbook.schema.json ├── static/ ├── App.vue ├── main.js ├── manifest.json └── pages.json

云函数按业务域拆分,不要把所有逻辑塞进一个函数。原因有三:一是单个函数代码体积小,冷启动快;二是权限和配额可以分开控制;三是出问题好定位。ocr-word只负责收图片、调 OCR、返回单词候选;dict-query只负责查词义;wordbook-crud只碰数据库;speech-score只处理音频。

2.3 云数据库 schema 与权限配置

生词本的数据结构是整个项目的地基,设计不好后面全是坑。wordbook.schema.json常见写法:

{ "bsonType": "object", "required": ["user_id", "word"], "permission": { "read": "doc.user_id == auth.uid", "create": "auth.uid != null", "update": "doc.user_id == auth.uid", "delete": "doc.user_id == auth.uid" }, "properties": { "_id": { "description": "系统自动生成" }, "user_id": { "bsonType": "string", "description": "用户唯一标识" }, "word": { "bsonType": "string", "description": "单词原形" }, "trans": { "bsonType": "string", "description": "释义快照" }, "source": { "bsonType": "string", "description": "来源:camera/dict/read" }, "create_date": { "bsonType": "timestamp", "defaultValue": { "$env": "now" } } } }

权限规则里auth.uid是 uniCloud 内置的当前用户 ID,配合uni-id使用。read和update都限定doc.user_id == auth.uid,意味着用户只能读写自己的生词。这一步如果偷懒写成true,上线后就是数据裸奔,血泪经验。

注意:schema 里的权限是数据库层面的最后一道防线,前端传参校验不能替代它。两者都要做。

3. 拍照识别单词:从图片到单词候选的完整链路

3.1 前端选图与压缩

拍照识词的第一步不是调 OCR,是把图片压到合理体积。微信小程序对上传图片有大小限制,原图动辄几 MB,直接传既慢又费流量。常见做法是用uni.chooseImage拿到临时路径后,用uni.compressImage压缩。

// pages/camera/camera.vue async function pickAndCompress() { const res = await uni.chooseImage({ count: 1, sizeType: ['compressed'], // 先用系统压缩 sourceType: ['camera', 'album'] }); const tempPath = res.tempFilePaths[0]; // 二次压缩,控制长边不超过 1280 const compressed = await uni.compressImage({ src: tempPath, quality: 80, compressedWidth: 1280 }); return compressed.tempFilePath; }

sizeType: ['compressed']让微信先做一轮压缩,compressImage再做一轮,quality: 80是画质和体积的平衡点。compressedWidth: 1280是因为主流 OCR 接口对长边 1280 到 1600 的图片识别率已经够用,再大只是浪费带宽。压完通常能到 200KB 以内。

3.2 云函数调用 OCR 与结果清洗

图片上传到云存储后,把 fileID 传给ocr-word云函数。云函数里下载图片、调 OCR、清洗结果:

// uniCloud-aliyun/cloudfunctions/ocr-word/index.js const cloud = require('wx-server-sdk'); // 以微信侧 OCR 为例 cloud.init(); exports.main = async (event) => { const { fileID } = event; const { fileContent } = await cloud.downloadFile({ fileID }); // 调用 OCR,generalBasic 适合通用印刷体 const ocrRes = await cloud.openapi.ocr.printedText({ type: 'photo', img: fileContent }); // 清洗:按行拆分,过滤非英文,去重 const lines = ocrRes.itemList.map(i => i.text); const words = new Set(); lines.forEach(line => { const matched = line.match(/[a-zA-Z][a-zA-Z-]{1,24}/g) || []; matched.forEach(w => { const lower = w.toLowerCase(); if (lower.length >= 2) words.add(lower); }); }); return { code: 0, words: Array.from(words).slice(0, 50) }; };

逻辑说明:downloadFile把云存储图片拉成 Buffer;printedText是通用印刷体识别,适合课本、试卷、屏幕截图。清洗阶段用正则[a-zA-Z][a-zA-Z-]{1,24}提取英文单词,过滤掉长度小于 2 的碎片,用Set去重,最后截断到 50 个候选——一次拍照识别出几百个词没有意义,用户也选不过来。

参数说明:type: 'photo'针对拍照场景优化,如果是截图可以换'scanned'。slice(0, 50)的上限可以根据 UI 调整,但建议不超过 100,否则前端渲染列表会卡。

3.3 候选词回传与用户确认

OCR 结果不能直接写进生词本,必须让用户勾选。前端拿到words数组后渲染成可多选的标签列表,用户确认后再批量写入。这一步是产品逻辑,但技术上要注意:批量写入用云函数一次事务处理,不要在前端循环调 50 次add。

// 批量加入生词本 async function batchAdd(words) { const res = await uniCloud.callFunction({ name: 'wordbook-crud', data: { action: 'batchAdd', words, source: 'camera' } }); return res.result; }

wordbook-crud里用db.collection('wordbook').add()配合循环,或者用db.startTransaction()保证一致性。批量操作单次建议不超过 100 条,超过就分批。

4. 词典查询与生词本:数据怎么存、怎么查才不翻车

4.1 词典查询的三种数据源取舍

词典查询有几种常见做法:一是接第三方词典 API,优点是词库全、释义权威,缺点是有调用配额和费用;二是自建词库,把常用词导入云数据库,优点是快、免费,缺点是覆盖有限;三是混合,高频词走本地库,未命中再走 API。

对考研英语场景,我一般会建议混合方案。考研核心词汇大概 5500 个,全部导入云数据库也就几 MB,查询走db.collection('dict').where({ word }).get(),毫秒级返回。生僻词再走 API 兜底。

// uniCloud-aliyun/cloudfunctions/dict-query/index.js const db = uniCloud.database(); exports.main = async (event) => { const { word } = event; const lower = word.toLowerCase().trim(); // 先查本地词库 const local = await db.collection('dict').where({ word: lower }).limit(1).get(); if (local.data.length > 0) { return { code: 0, source: 'local', data: local.data[0] }; } // 本地未命中,走外部 API(此处以伪代码示意) const remote = await queryRemoteDict(lower); if (!remote) { return { code: 404, msg: '未找到该词' }; } // 异步回写本地库,下次就快了 db.collection('dict').add({ word: lower, ...remote }).catch(() => {}); return { code: 0, source: 'remote', data: remote }; };

逻辑说明:先本地后远程,远程结果异步回写。回写用.catch(() => {})吞掉错误,因为回写失败不影响本次查询,不能让它阻塞返回。limit(1)是因为单词唯一,查到一条就够。

参数说明:word要做toLowerCase().trim(),用户输入经常带空格或大小写混乱。本地词库的word字段建索引,否则数据量上来后查询会慢。

4.2 生词本的去重与同步策略

生词本最容易翻车的地方是重复添加。同一个词从拍照、查词、跟读三个入口进来,如果不做去重,用户会看到三条一样的记录。常见做法是在wordbook集合上建user_id + word的联合唯一索引,插入时用upsert语义。

// wordbook-crud 云函数片段 async function addWord(userId, word, trans, source) { const col = db.collection('wordbook'); const exist = await col.where({ user_id: userId, word }).limit(1).get(); if (exist.data.length > 0) { // 已存在,更新来源和释义,不新增 await col.doc(exist.data[0]._id).update({ trans, source, update_date: Date.now() }); return { code: 0, action: 'updated' }; } await col.add({ user_id: userId, word, trans, source, create_date: Date.now() }); return { code: 0, action: 'created' }; }

逻辑说明:先查后写,存在则更新,不存在则新增。这样无论从哪个入口进来,同一个词只有一条记录。update_date用于后续按最近添加排序。

参数说明:user_id从uni-id的 token 里取,不要信任前端传的 user_id,否则用户可以伪造别人的 ID 写数据。这是安全底线。

4.3 分页加载与本地缓存

生词本列表用db.collection('wordbook').where({ user_id }).orderBy('create_date', 'desc').skip(page * 20).limit(20).get()分页。skip在数据量大时性能会下降,更好的做法是用create_date游标:where({ user_id, create_date: dbCmd.lt(lastDate) })。

前端侧,已加载的生词本列表存到uni.setStorageSync,下次进入先渲染缓存再拉新数据,减少白屏。缓存要设过期时间,比如 5 分钟,避免用户在多端操作后看到旧数据。

5. 跟读打分与 AI 语音翻译:音频链路和评测参数

5.1 录音格式与采样率选择

跟读打分的第一步是录音。微信小程序用uni.getRecorderManager(),关键参数是format和sampleRate。主流语音评测接口对音频有明确要求,常见是 16kHz 采样、16bit 位深、单声道。

const recorder = uni.getRecorderManager(); recorder.start({ duration: 15000, // 最长 15 秒,够读一个句子 sampleRate: 16000, // 16kHz,评测接口标准 numberOfChannels: 1, // 单声道 encodeBitRate: 48000, format: 'mp3' // 部分接口要 pcm,按接口文档选 });

参数说明:duration: 15000是上限,超过自动停止,防止用户忘记停录。sampleRate: 16000是绝大多数评测接口的推荐值,用 44.1kHz 反而可能被拒。format要严格按接口要求,mp3 通用性好但部分评测要 pcm,选错直接返回格式错误。

5.2 云函数转发评测与结果解析

录音文件上传云存储后,speech-score云函数下载音频、调评测接口、解析分数:

// speech-score 云函数片段 exports.main = async (event) => { const { fileID, refText } = event; const { fileContent } = await cloud.downloadFile({ fileID }); // 调评测接口(伪代码,按实际接口替换) const scoreRes = await callSpeechEval({ audio: fileContent, text: refText, category: 'read_sentence' }); // 解析:总分、流利度、完整度、准确度 return { code: 0, total: scoreRes.total_score, fluency: scoreRes.fluency_score, integrity: scoreRes.integrity_score, accuracy: scoreRes.accuracy_score, detail: scoreRes.word_details || [] }; };

逻辑说明:refText是标准文本,评测接口拿它和用户录音比对,算出准确度和完整度。word_details是逐词评分,前端可以高亮读错的词,体验比只给一个总分好得多。

参数说明:category: 'read_sentence'是句子朗读模式,还有read_word、read_chapter等,按场景选。评测接口通常有并发限制,云函数里要加简单的限流或队列,避免高峰期被限。

5.3 AI 语音翻译的调用边界

AI 语音翻译本质是「语音识别 + 机器翻译」两步。先 ASR 把音频转文本,再 MT 把文本翻译成目标语言。这两步都可以在云函数里串起来,但要注意:ASR 和 MT 各自有延迟,串行调用总延迟可能到 3 到 5 秒,前端要有 loading 态。

另一个边界是成本。ASR 和 MT 都按调用量计费,如果用户频繁使用,费用会累积。常见做法是加一个每日免费额度,超出后提示或走更便宜的方案。额度控制放在云函数里,用user_id + date做计数,存云数据库。

6. 避坑与排查:这类 Serverless 小程序最容易翻车的 5 个点

6.1 云函数冷启动导致首次拍照识别超时

现象:用户第一次点拍照识别,转圈 3 秒以上,偶尔直接超时失败。 原因:云函数实例被回收后,下次调用要重新初始化,冷启动延迟叠加 OCR 接口延迟,超过前端等待阈值。 解决:给ocr-word配置定时触发器,每 5 分钟 ping 一次保持热实例;前端加超时重试,第一次失败后自动重试一次;把 OCR 调用和结果清洗拆成两个函数,减少单函数初始化负担。

6.2 云数据库权限写成 true 导致数据裸奔

现象:上线后发现 A 用户能看到 B 用户的生词本。 原因:schema 里read权限图省事写成true,或者忘了配user_id过滤。 解决:所有涉及用户数据的集合,read和write必须绑定auth.uid;上线前用两个测试账号交叉验证,确认互相看不到数据;定期审计 schema 文件。

6.3 录音格式不匹配导致评测接口返回格式错误

现象:跟读打分一直返回「音频格式不支持」。 原因:前端录音用了默认的aac或44.1kHz,评测接口只认16kHz pcm或mp3。 解决:录音参数严格按接口文档设,sampleRate: 16000、numberOfChannels: 1;上传前用uni.getFileInfo确认文件大小和格式;云函数里加格式校验,不合法直接返回明确错误码。

6.4 生词本重复添加导致列表出现多条相同记录

现象:同一个词从拍照和查词两个入口加,生词本里出现两条。 原因:没有做去重,或者去重查询和插入之间有并发窗口。 解决:建user_id + word联合唯一索引,数据库层面兜底;插入逻辑用「先查后写」,并发场景用upsert;前端加防抖,避免用户连点。

6.5 词典查询外部 API 超时拖垮整个云函数

现象:查生僻词时云函数执行超时,返回 500。 原因:外部词典 API 响应慢,云函数默认超时 5 秒被耗尽。 解决:给外部 API 调用设独立超时,比如 2 秒,超时就走降级返回「暂未收录」;把外部查询改成异步任务,先返回本地结果,远程结果通过订阅消息或轮询补上;云函数超时时间按需调大,但不要超过 10 秒。

7. 进阶:把生词本变成复习引擎的一个具体技巧

生词本如果只是「存起来」,用户加完就不会再看,留存极差。真正有价值的是把它变成复习引擎。这里讲一个我实际用过的技巧:基于遗忘曲线的复习队列,用云数据库的定时触发器每天生成待复习列表。

核心思路是给每个生词加三个字段:review_count(已复习次数)、next_review(下次复习时间戳)、ease(难度系数)。每次用户复习后,按 SM-2 算法的简化版更新这三个字段。

// 复习后更新调度参数 function scheduleNext(word, quality) { // quality: 0-5,用户自评掌握程度 let { review_count, ease } = word; ease = ease || 2.5; if (quality < 3) { // 没掌握,明天再来 review_count = 0; return { review_count, ease, next_review: Date.now() + 86400000 }; } review_count += 1; ease = Math.max(1.3, ease + (0.1 - (5 - quality) * 0.08)); const interval = Math.round(1 * Math.pow(ease, review_count - 1)); return { review_count, ease, next_review: Date.now() + interval * 86400000 }; }

逻辑说明:quality < 3视为没掌握,重置复习次数,明天再来。掌握的话,ease按质量调整,质量越高ease越大,间隔增长越快。interval用ease的幂次算,第一次 1 天,之后逐渐拉长到几天、几周。

参数说明:ease下限 1.3,防止间隔增长过慢;quality由用户自评或跟读打分映射,比如打分 80 以上映射为 5,60 到 80 映射为 3,60 以下映射为 1。

配合云数据库的定时触发器,每天凌晨跑一次,把next_review <= 今天的词查出来,生成当天的复习任务。前端首页展示「今日待复习 N 个」,点进去就是卡片式复习。这个改动不大,但能把生词本从「死数据」变成「活工具」,用户次日留存会有明显变化。

我自己踩过的坑是:一开始把next_review存成日期字符串,跨时区比较时各种错乱,后来统一改成时间戳才消停。还有ease初始值别设太高,2.5 是经过验证的起点,设 3.0 会导致间隔涨太快,用户很快就被大量复习任务压垮。这类调度逻辑,参数调优比算法本身更重要,建议先小范围跑一周看数据再放开。希望帮到你。

本文还有配套的精品资源,点击获取

相关新闻

WiFi指纹室内定位实战:从原理到Demo搭建

WiFi指纹室内定位实战:从原理到Demo搭建

1. 室内定位的现实困境与WiFi方案的破局点实话实说&#xff0c;第一次接手“基于WiFi的室内定位”这个方向时&#xff0c;我心里是打鼓的。日常大家用GPS导航已经习惯了&#xff0c;掏出手机就能知道自己在哪&#xff0c;但一旦走进大型商场、地下车库、机场航站楼&#xff0c;…

2026/10/20 17:33:06 阅读更多 →
大模型后端长对话记忆架构全解析:从无状态到有状态

大模型后端长对话记忆架构全解析:从无状态到有状态

做后端的人都有过这种体验&#xff1a;用户和AI助手聊了三十轮&#xff0c;前二十轮里明明已经把需求背景、偏好、禁忌都交代清楚了&#xff0c;结果聊到第三十一轮&#xff0c;AI突然反问一句“您刚刚提到的那个项目背景&#xff0c;方便再描述一下吗&#xff1f;”当场血压就…

2026/10/20 17:33:06 阅读更多 →
D435相机+OpenCV快速上手:彩色图与深度图实时显示全攻略

D435相机+OpenCV快速上手:彩色图与深度图实时显示全攻略

最近不少做视觉入门的朋友卡在第一关——把D435相机的画面真正“看”到屏幕上。很多人买了一台Intel D435深度相机&#xff0c;兴冲冲插上USB线&#xff0c;结果CPU占用飙高、程序报错、画面黑屏&#xff0c;折腾一晚上就劝退了。其实用D435搭配OpenCV显示彩色图和深度图&#…

2026/10/20 17:33:06 阅读更多 →

最新新闻

Appium移动端自动化测试环境搭建全攻略:Python+Android+Node.js实战

Appium移动端自动化测试环境搭建全攻略:Python+Android+Node.js实战

1. 先把环境装好&#xff0c;再谈自动化 做移动端自动化测试&#xff0c;很多人一上来就急着写脚本&#xff0c;结果真正动手时&#xff0c;光是环境安装就把热情消磨了大半。Appium Python Android Node.js这套组合&#xff0c;几乎每个部件都有自己的版本要求、环境变量和…

2026/10/20 18:10:34 阅读更多 →
QTTabBar、Office Tab与Quicker:告别Windows多窗口混乱,提升办公效率

QTTabBar、Office Tab与Quicker:告别Windows多窗口混乱,提升办公效率

1. 写在最前面&#xff1a;为什么你的Windows办公效率上不去先问一个问题&#xff1a;你每天要在这台电脑上打开多少个文件夹窗口&#xff1f;要在这几个窗口之间来回切换多少次AltTab&#xff1f;Word、Excel来回改的时候&#xff0c;任务栏上挤了多少个窗口&#xff1f;如果你…

2026/10/20 18:10:34 阅读更多 →
AI短剧创作教程源码包:从剧本到成片的自动化流水线

AI短剧创作教程源码包:从剧本到成片的自动化流水线

简介&#xff1a;AI短剧创作教程源码包&#xff0c;专为希望借助AI工具快速产出短剧的内容创作者与开发者设计。资源围绕AiPy工具&#xff0c;覆盖从故事主题设定、提示词生成剧本&#xff0c;到旁白与分镜头视频制作、人物一致性维护&#xff0c;直至音视频合成出片的完整流程…

2026/10/20 18:10:34 阅读更多 →
本体驱动开发:让AI应用先有一份清晰的领域宪法

本体驱动开发:让AI应用先有一份清晰的领域宪法

最近在整理ontology-driven-dev这个开源项目时&#xff0c;发现一个很有意思的现象&#xff1a;很多人第一眼看到"本体驱动"四个字&#xff0c;要么觉得是学术论文里才有的概念&#xff0c;要么直接把它和知识图谱划等号。但实际上&#xff0c;在做AI原生应用开发的过…

2026/10/20 18:10:34 阅读更多 →
C++利用链表模板类实现简易队列

C++利用链表模板类实现简易队列

前言 队列&#xff08;queue&#xff09;是先进先出&#xff08;first in, first out, FIFO&#xff09;的线性结构&#xff1a;只在尾部插入&#xff0c;只在头部删除。用链表实现队列的好处是插入和删除都是 O(1)&#xff0c;不需要像动态数组那样在头部删除时搬移元素&#…

2026/10/20 18:10:34 阅读更多 →
用Mock测试解决接口依赖问题:从工具选型到落地实践

用Mock测试解决接口依赖问题:从工具选型到落地实践

做接口联调这么多年&#xff0c;最烦的一件事就是“等”。前端等后端接口&#xff0c;后端等第三方服务&#xff0c;测试等环境稳定&#xff0c;最后所有人都在等别人。尤其是前后端并行开发那阵子&#xff0c;接口契约刚定完&#xff0c;前端已经把页面写了一半&#xff0c;后…

2026/10/20 18:09:32 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →