Qt桌面工具集成语音识别:百度语音识别API REST接口调用实战
给桌面工具加语音输入功能时我第一反应不是去编译官方SDK而是直接用百度语音识别API的REST接口配合QT 5.14.1做图形界面。整个过程不依赖复杂环境一个QNetworkAccessManager就能完成音频上传和结果解析通信很快最核心的代码也不过两三百行。今天把这套实现完整拆开讲一遍包含可以直接参考的源码片段也会把我实测过程中遇到的几个坑标注出来。如果你正打算给某个QT程序加上“说话转文字”能力或者只是想验证一下云端语音识别在自己项目里的可行性这篇内容可以直接照着做。动手之前先明确这套方案的定位它适合对识别时效性要求不苛刻、允许网络依赖、数据不是在绝对隔离环境中使用的桌面工具。1. 为什么我建议走REST接口而不是SDK1.1 先对比几种语音识别的接入方式接入语音识别粗分有三条路官方C SDK、REST接口、离线模型。很多人一上来就找SDK但“简单实现”四个字恰恰决定了REST是最合适的切入点。接入方式依赖复杂度部署体积识别效果适用场景官方C SDK需要编译、链接官方库较大与云端一致长期正式项目、模块化强REST接口只依赖网络和JSON无额外体积与云端一致快速原型、轻量工具、简单Demo离线模型离线库集成很大看模型和设备无网络、隐私强约束场景我在某个内部工具里只需要把一段短语音转成文字不涉及流式识别也不需要离线能力选REST最直接。SDK的优势是封装了重试、长连接、流式逻辑但代价是编译环境容易和Qt版本冲突而REST接口只发HTTP请求QNetworkAccessManager是Qt自带能力返回值是JSON用QJsonDocument解析就行没有任何额外依赖。对“简单实现”来说这是最稳的路。1.2 版本选择为什么固定在QT 5.14.1Qt版本选5.14.1首先是因为它稳定。Qt 6出来以后API有调整很多老的教程和第三方示例还是Qt5风格照着改会踩到编译错误5.14.1属于5.x里比较成熟的版本QNetworkAccessManager、QJsonDocument这些模块的行为都和后续版本基本一致用起来熟练度最高。其次5.14.1自带的MinGW 7.3.0组合在Windows上很干净不需要额外装庞大的VS工具链安装包选好组件就能直接跑。如果你的环境不是5.14.1也不用担心只要是Qt5这套代码基本不需要改。我特意固定版本是为了让复现结果更一致避免“我编译过了你怎么报错”这类问题。Linux上直接用系统的Qt5包管理器安装qtbase5-dev同样能编译跨平台表现也很稳定。2. 百度语音识别API的工作原理先取token再传音频2.1 access_token的获取与有效期百度语音识别API的调用逻辑可以概括成两句话先用API Key和Secret Key换一个临时令牌access_token再带着令牌上传音频。第一步是标准OAuth 2.0的client_credentials模式请求地址是https://aip.baidubce.com/oauth/2.0/token?grant_typeclient_credentialsclient_id你的APIKeyclient_secret你的SecretKey返回的JSON里有一个access_token字段还有expires_in字段。expires_in是有效期按秒计算一般是一个月左右。很多新手会把API Key和Secret Key直接放进识别请求里这是不行的识别接口只认access_token。token这东西不是一次性的有效期内可以反复使用所以比较合理的做法是缓存到本地过期后再重新获取。后面我会在踩坑部分细说这个点。2.2 音频参数为什么必须精确匹配识别引擎对音频格式的要求非常严格可以用一个类比来记它就像一家只接受固定规格订单的餐厅你递过去的材料少一样或者规格不对后厨直接拒绝开工。官方要求最常见的组合是PCM格式、16000Hz采样率、16bit位深、单声道。这是短语音识别的黄金标准。为什么不是越高越好16000Hz采样率对语音识别已经足够覆盖人声的频带范围你取44100Hz的立体声文件传上去数据量翻了几倍识别率并不会显著提升反而可能因为格式不匹配直接报错。我在测试中发现很多人拿麦克风录出来的wav默认是44100Hz、16bit、双声道这样的文件不经过转换直接传上去大概率会收到音频格式错误的返回码。另外要注意短语音接口对音频时长也有约束一般建议控制在60秒以内。超过这个范围要么自己切分成多段要么换成长语音接口。文件大小也有上限具体数值以当前官方文档为准所以我一般在上传前会做一次本地校验宁可提前拦截也别等服务端拒绝。2.3 一次完整的识别请求长什么样识别接口的地址是https://vop.baidu.com/server_api请求方式是POSTContent-Type设置为application/json请求体是一个JSON对象。核心字段如下{ format: pcm, rate: 16000, channel: 1, cuid: qt-demo-001, token: 上一节拿到的access_token, speech: 音频原始数据的Base64编码, len: 12345, dev_pid: 1537 }字段逐个说format是音频格式pcm/wav/amr/m4a里选rate是采样率16000就是16kHzchannel是声道数1是单声道cuid是用户唯一标识任意字符串即可但建议每次请求保持一致token就是上一步换来的令牌speech是音频数据做Base64编码后的字符串len是原始音频数据的字节长度不是Base64编码后的长度这个最容易搞混dev_pid是识别模型1537代表普通话。返回的也是一个JSON正常情况长这样{ err_no: 0, err_msg: success, result: [识别出的文字] }注意result是一个数组里面可能有多条候选识别结果通常取第一条就是最可能的文本。如果err_no不是0err_msg会给出具体失败原因排查时候先看这两个字段。3. 环境准备与项目骨架3.1 Qt 5.14.1安装与编译器选择Windows下安装Qt 5.14.1下载对应的在线安装版组件选择时建议勾选“Qt 5.14.1”下的MinGW 7.3.0 32-bit。同时确保“Tools”分类里也有MinGW 7.3.0否则编译器缺失会导致项目无法构建。如果手头已经有MSVC环境也可以选MSVC2017 64-bit但那样还需要额外安装配套的VS构建工具对纯语音识别项目来说有点重。Linux环境简单很多用系统包管理器安装qtbase5-dev就能获得Qt 5 Widgets和Network模块qmake版本只要是5.x即可。选择MinGW还是MSVC对网络代码没有影响QNetworkAccessManager在两者下面行为一致区别只在于调试器工具链不同。我的经验是只是为了跑通这个DemoMinGW最省心。3.2 新建项目和pro文件配置打开Qt Creator新建“Qt Widgets Application”生成的主窗口类保持不变。关键是打开.pro文件确认包含了core、gui、widgets然后手动加上network模块。修改后的pro文件核心部分QT core gui widgets network CONFIG c11 SOURCES \ main.cpp \ mainwindow.cpp HEADERS \ mainwindow.hnetwork模块提供QNetworkAccessManager、QNetworkRequest、QNetworkReply三个核心类没有这一行代码里一引入网络相关头文件就会编译失败。CONFIG洗c11是为了让lambda表达式和某些Qt5特性正常工作实际上Qt 5.14.1默认也支持写明确一点更保险。3.3 界面最小设计UI不需要花哨只需要一个按钮、一个文本区和一个状态栏。按钮用来选择WAV文件并触发识别文本区用来显示识别结果状态栏显示当前状态。m_btn new QPushButton(选择WAV并识别, this); m_btn-setGeometry(10, 10, 160, 32); m_textEdit new QTextEdit(this); m_textEdit-setGeometry(10, 50, 460, 260); statusBar()-showMessage(就绪); connect(m_btn, QPushButton::clicked, this, MainWindow::onSelectAndRecognize);为什么不用Designer拖拽因为界面太简单了直接代码创建的代码量比维护.ui文件还少而且分享源码时别人拷贝下来就能看懂。等以后功能复杂了再把布局换成Relative或Grid布局即可。4. 核心代码逐段拆解4.1 获取access_token的网络类我在MainWindow里直接管理网络请求没有额外封装类核心成员变量如下QNetworkAccessManager *m_nam; QString m_apiKey; QString m_secretKey; QString m_token; QByteArray m_pcmData;m_nam是全局网络管理对象整个程序复用一个实例m_apiKey和m_secretKey是你在控制台申请到的密钥m_token是运行时缓存的访问令牌m_pcmData是读取出来待识别的音频数据。获取token的代码本质就是一次带查询参数的GET请求重点在把参数放进QUrlQuery而不是手拼字符串void MainWindow::getToken() { QUrl url(https://aip.baidubce.com/oauth/2.0/token); QUrlQuery query; query.addQueryItem(grant_type, client_credentials); query.addQueryItem(client_id, m_apiKey); query.addQueryItem(client_secret, m_secretKey); url.setQuery(query); QNetworkRequest request(url); QNetworkReply *reply m_nam-get(request); connect(reply, QNetworkReply::finished, this, [this, reply] { reply-deleteLater(); if (reply-error() ! QNetworkReply::NoError) { statusBar()-showMessage(QString(获取token失败: %1).arg(reply-errorString())); return; } QJsonDocument doc QJsonDocument::fromJson(reply-readAll()); m_token doc.object().value(access_token).toString(); statusBar()-showMessage(token获取成功); // 拿到token后继续走识别流程 sendRecognize(); }); }这里要重点说明一个设计原则网络请求必须走异步信号槽绝不能用waitForFinished()阻塞等待。Qt的事件循环天然适合这种写法后面踩坑部分我会讲为什么。4.2 从WAV文件读出PCM数据WAV文件由RIFF头、fmt块和data块组成数据块之前的标准头通常是44字节但有些工具产出的wav会在fmt和data之间插入额外信息直接跳过固定44字节会读到错误位置。所以我在代码里做了data块搜索而不是盲目偏移。quint32 littleEndianInt(const QByteArray bytes, int pos) { return (quint32)(unsigned char)bytes[pos] | ((quint32)(unsigned char)bytes[pos 1] 8) | ((quint32)(unsigned char)bytes[pos 2] 16) | ((quint32)(unsigned char)bytes[pos 3] 24); } qint64 findDataOffset(const QByteArray wavData) { if (wavData.size() 36) return -1; int pos 12; while (pos 8 wavData.size()) { QByteArray chunkId wavData.mid(pos, 4); quint32 chunkSize littleEndianInt(wavData, pos 4); if (chunkId data) return pos 8; pos 8 chunkSize (chunkSize % 2); } return -1; }选择文件后读取数据的逻辑很简单void MainWindow::onSelectAndRecognize() { QString filePath QFileDialog::getOpenFileName(this, 选择WAV文件, , 音频文件 (*.wav)); if (filePath.isEmpty()) return; QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { statusBar()-showMessage(文件打开失败); return; } QByteArray allData file.readAll(); file.close(); qint64 dataOffset findDataOffset(allData); if (dataOffset 0) { statusBar()-showMessage(没有找到data块); return; } m_pcmData allData.mid(dataOffset); statusBar()-showMessage(音频数据已读取, QString::number(m_pcmData.size()) 字节); getToken(); }注意把data块之后的裸PCM字节存进m_pcmData识别请求里的speech字段就用这份数据做Base64。如果你手里的文件本来就是16kHz/16bit/单声道的PCM裸流没有wav头那可以直接跳过整个解析过程m_pcmData 文件内容即可。4.3 请求体构造与POST发送识别请求是标准的JSON POST注意Content-Type必须是application/jsonvoid MainWindow::sendRecognize() { QJsonObject obj; obj[format] pcm; obj[rate] 16000; obj[channel] 1; obj[cuid] qt-demo-001; obj[token] m_token; obj[speech] QString::fromLatin1(m_pcmData.toBase64()); obj[len] m_pcmData.size(); obj[dev_pid] 1537; QJsonDocument doc(obj); QByteArray body doc.toJson(QJsonDocument::Compact); QNetworkRequest request(QUrl(https://vop.baidu.com/server_api)); request.setHeader(QNetworkRequest::ContentTypeHeader, application/json); QNetworkReply *reply m_nam-post(request, body); connect(reply, QNetworkReply::finished, this, [this, reply] { reply-deleteLater(); handleRecognizeReply(reply); }); }两个容易出错的点speech字段必须是Base64字符串如果音源本身是中文文件名或者音频内容里含非法字符直接用QString::fromLatin1转Base64结果是安全的len字段必须是你原始音频的字节数也就是m_pcmData.size()不是Base64之后字符串的长度。我见过有人把speech的base64字符串长度填进len服务端直接报参数错误。4.4 结果解析与错误处理识别返回的内容先按JSON解析然后取result数组的第一项void MainWindow::handleRecognizeReply(QNetworkReply *reply) { if (reply-error() ! QNetworkReply::NoError) { statusBar()-showMessage(网络请求失败: reply-errorString()); return; } QByteArray data reply-readAll(); QJsonParseError parseError; QJsonDocument resp QJsonDocument::fromJson(data, parseError); if (parseError.error ! QJsonParseError::NoError) { statusBar()-showMessage(JSON解析失败); return; } QJsonObject root resp.object(); int errNo root.value(err_no).toInt(); if (errNo 0) { QJsonArray result root.value(result).toArray(); if (!result.isEmpty()) { QString text result.at(0).toString(); m_textEdit-append(text); statusBar()-showMessage(识别成功); } } else { statusBar()-showMessage( QString(识别失败: err_no%1, err_msg%2) .arg(errNo) .arg(root.value(err_msg).toString())); } }这里有个处理技巧不管成功还是失败先把返回的原始JSON完整打印到控制台或者调试端方便排查。网上很多示例代码只处理成功分支一旦失败就抓瞎。我习惯在parseError分支里顺便输出data内容如果JSON解析失败多半是服务端返回了HTML错误页而不是JSON这时候先查网络代理或接口地址。4.5 串起来的完整调用链整套流程跑起来是点击按钮选择文件 → 读取PCM → 检查token是否有效 → 没有则先获取token → 获取成功后发送识别请求 → 解析结果并显示。这里面最关键的是时序控制我用两种方式保证如果m_token为空就getToken在getToken的finished里调用sendRecognize如果m_token非空直接sendRecognize。实际操作中我通常会在程序启动时就异步获取一次token这样用户第一次点按钮时token已经准备好了。一个可运行的MainWindow构造函数初始化流程大概是MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { m_nam new QNetworkAccessManager(this); m_apiKey 你的API Key; m_secretKey 你的Secret Key; // 创建按钮、文本区、状态栏 // connect按钮点击 if (m_token.isEmpty()) getToken(); }密钥写死在源码里只适合Demo正式项目建议放到配置文件或者通过qmake宏注入到编译变量里避免源码泄露后密钥也跟着泄露。5. 实测中的三个坑格式、卡顿、token过期5.1 坑一3301音频格式错误第一次跑通时我用自己电脑录音软件导出的wav文件测试点击识别返回的err_no是3301。看err_msg才知道是音频格式问题。当时文件是44100Hz、16bit、双声道而接口要求16000Hz、16bit、单声道。这个坑几乎是所有新手都会踩的因为wav文件本身能正常播放你很难想到服务端会拒绝。解决办法是先转换格式。可以用音频处理工具把采样率降为16000声道合并为单声道位深保持16bit再导出成PCM或WAV。我更推荐的做法是录制时就强制使用16kHz/16bit/单声道省去后期转换。如果用的是音频库采集可以直接设置音频设备参数避免录完再转。还有一个小细节录音文件如果本身是amr或m4aformat字段要写对应的格式名不能照抄pcm。我建议统一转成16kHz、16bit、单声道的pcm因为这是所有模型里兼容性最好的一种。5.2 坑二waitForFinished把界面卡死了识别一个几秒钟的音频网络请求加上服务端处理总耗时可能在一两秒左右。有同学为了方便在按钮点击的槽函数里直接调用reply-waitForFinished()想同步拿到结果。结果就是整个界面在请求返回前完全无响应窗口拖不动按钮点了没反应体验非常糟糕。根本原因是Qt的图形界面必须运行在事件循环里waitForFinished会阻塞当前线程的事件处理。解决办法是用异步信号槽也就是我在4.1和4.3里写的connect方式。Qt里的网络请求本身就是异步设计不要在槽函数里做任何阻塞操作所有后续逻辑都放到finished信号对应的lambda或槽函数里执行。实测下来的体感是异步流程虽然代码看起来多了几个回调但程序不卡状态栏还能实时显示“正在识别”之类的信息这种体验是同步方案给不了的。5.3 坑三token过期后返回错误码第一次实现token缓存时我把access_token写进了本地配置文件想着省去每次请求都重新获取的麻烦。结果第二天打开程序识别失败返回的错误码指向认证问题。原因很简单token有效期不是永久我当天没看expires_in字段缓存了一个即将过期的token。后来我的处理逻辑是获取token时把expires_in读出来减去一个安全缓冲时间比如提前10分钟过期存成到期时间戳。每次识别前如果发现当前时间接近或超过到期时间就重新获取token。这样既保留了缓存带来的速度优势又避免了过期问题。还有一点token的获取接口本身也要做返回值校验有时候网络抖动可能导致拿到的access_token为空不检查就直接发识别请求的话报错信息不够直观排查起来很累。5.4 排查链路从状态码到日志定位如果你也碰到识别失败我建议按这条链路排查基本能定位90%的问题先看HTTP状态码。如果网络层就挂了检查代理、DNS、接口地址是否写错。再看服务端返回原文。用输出函数把reply-readAll()的原始内容打出来看看是不是合法JSON。对照err_no和err_msg列表定位错误大类。如果是音频错误回到本地检查采样率、位深、声道数和format字段是否匹配。最后核对参数有没有笔误尤其是len是不是原始字节长度cuid是不是带了空格。这套顺序的出发点是“从外往里查”先用网络层信息排除环境问题再用JSON字段缩小范围最后才看音频本身。很多人在第一步就卡住完全是因为只盯着代码看没有先看服务端真正说了什么。6. 从Demo到可用后面还能怎么扩展6.1 用QAudioInput做实时录音文件选择式的识别适合验证流程真正好用还得是点击按钮直接录音松手结束然后自动识别。Qt里可以用QAudioInput配合QAudioProbe采集音频数据也可以直接用QMediaRecorder录成一个wav文件再走现有流程。我推荐先用后者因为录音文件的格式问题可以在录制阶段解决比处理实时音频缓冲简单得多。核心是把音频编码器设置为pcm采样率16000声道1这样录出来文件直接就是可识别的格式。6.2 语种参数与长音频处理dev_pid字段控制识别语种普通话是1537英语是1737需要支持其他语种时查官方参数表即可。如果你要识别的是超过60秒的音频短语音接口就撑不住了要么在本地做切片分段发送要么换长语音接口。长语音接口的请求方式和短语音类似但返回结果可能不是一次性JSON需要处理异步回调或轮询逻辑复杂度会上去一截。6.3 我自己沉淀下来的接入习惯做完这个Demo之后我形成了一个固定的习惯凡是涉及云端API的Qt程序密钥一律不写死源码token一律缓存并检查过期时间音频上传前一律在本地打印一份原始参数摘要。这三个习惯帮我避开了大部分“昨天还能用今天突然不行”的灵异问题。单独提醒一个细节如果你给多个平台交叉编译注意对音频数据的字节序处理little-endian和big-endian在跨平台时可能导致识别结果完全乱码。我遇到过一次在某个嵌入式环境上采集的数据没做字节序转换结果服务端返回成功但识别文字全是乱码。排查到最后才发现是音频字节序问题。这类问题比报错更隐蔽拿到识别成功后也别急着高兴先确认文本是真的符合预期。

相关新闻

FFT里常被误读的“基”:基2 DIT算法原理与蝶形运算全解析

FFT里常被误读的“基”:基2 DIT算法原理与蝶形运算全解析

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

2026/10/17 1:29:23 阅读更多 →
TVS二极管导通建立时间精准测量方法

TVS二极管导通建立时间精准测量方法

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

2026/10/17 1:29:23 阅读更多 →
MLLM Agent 多模态理解研究进展:从感知到决策的链路拆解与 TaoToken 统一调用实践

MLLM Agent 多模态理解研究进展:从感知到决策的链路拆解与 TaoToken 统一调用实践

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

2026/10/17 1:29:23 阅读更多 →

最新新闻

SpringBoot3断代升级实战:从零搭建到部署的完整指南

SpringBoot3断代升级实战:从零搭建到部署的完整指南

前两周帮某电商团队做技术迁移评审,对方项目经理一上来就问:能不能在 SpringBoot2.7 基础上直接改版本号升到 3?我当时就告诉他:这可不是改一行版本号的事。编译直接红一片,javax消失,Tomcat行为变了&#…

2026/10/18 3:54:22 阅读更多 →
Widget是配置不是UI:Flutter三棵树与状态管理核心解析

Widget是配置不是UI:Flutter三棵树与状态管理核心解析

前两周帮同事排查一个非常诡异的问题:商品列表滚动到某个位置后界面卡成PPT,CPU直接飙满。代码翻了三轮,最终定位到的根因,居然不在列表渲染逻辑,而在于有人把一个封装的 Widget 实例存在字段里,每次 build…

2026/10/18 3:54:22 阅读更多 →
OpenHarmony上Flutter三方库适配实战:以carousel_slider为例

OpenHarmony上Flutter三方库适配实战:以carousel_slider为例

刚开始做 OpenHarmony 上的 Flutter 适配时,不少人一脸懵——明明 Flutter 在三方库生态上已经非常成熟,随便pub add一个库就能跑,怎么一到 OpenHarmony 上就不是这么回事了?实际上,OpenHarmony 的 Flutter 引擎适配层…

2026/10/18 3:54:22 阅读更多 →
用户登录案例与随机验证码结合:从表单校验到会话管理

用户登录案例与随机验证码结合:从表单校验到会话管理

不少刚学完 Web 基础的朋友,都会拿“用户登录”当第一个综合项目来做。但很多人做到最后发现,自己写的登录功能除了能查一下数据库、比对一下密码,根本谈不上“系统”。原因很简单:真实场景里的登录,永远不会只靠“用户…

2026/10/18 3:54:22 阅读更多 →
PHP+MySQL+百度地图全链路打点方案:从数据库到前端渲染

PHP+MySQL+百度地图全链路打点方案:从数据库到前端渲染

简介:这是一份面向Web开发初学者与地理信息系统(GIS)入门者的PHPMySQLHTML百度地图打点实战示例,解决动态数据驱动地图标记的核心问题,适用于LBS位置服务、门店展示、轨迹可视化等常见业务场景。资源共4个精简文件&…

2026/10/18 3:54:22 阅读更多 →
Delphi 11下EhLib 10.0.031安装与DBGridEh实战指南

Delphi 11下EhLib 10.0.031安装与DBGridEh实战指南

简介:EhLib 10.0.031是一套面向Delphi 11开发者的功能型组件库,核心覆盖图形图像处理、多类数据库连接、报表设计、图表分析与界面增强等常见开发场景。该版本已通过Delphi 11.1.5环境安装测试,适合中高级Delphi工程师和需要构建数据密集型桌…

2026/10/18 3:53:22 阅读更多 →

日新闻

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

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

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

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

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

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

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

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

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

2026/10/18 0:00:55 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 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/18 0:55:02 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →