[{"data":1,"prerenderedAt":139},["ShallowReactive",2],{"article-search-sections":3},[4,11,16,21,26,29,32,35,38,41,44,47,50,56,62,68,74,80,86,91,97,102,107,112,117,122,127,130,133,136],{"date":5,"id":6,"title":7,"titles":8,"content":9,"level":10},"2025-11-15","\u002Farticle\u002Fessay\u002F2025-11-15-test4","测试4",[],"测试测试测试 测试测试测试测试测试测试 测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试 哈基米哈基米哈基米哈基米哈基米 哈基米哈基米哈基米哈基米 哈基米哈基米哈基米哈基米",1,{"date":12,"id":13,"title":14,"titles":15,"content":9,"level":10},"2025-11-16","\u002Farticle\u002Fessay\u002F2025-11-16-test3","测试3",[],{"date":17,"id":18,"title":19,"titles":20,"content":9,"level":10},"2025-11-17","\u002Farticle\u002Fessay\u002F2025-11-17-test2","测试2",[],{"date":22,"id":23,"title":24,"titles":25,"content":9,"level":10},"2025-11-18","\u002Farticle\u002Fessay\u002F2025-11-18-test","TEST",[],{"date":5,"id":27,"title":7,"titles":28,"content":9,"level":10},"\u002Farticle\u002Fother\u002F2025-11-15-test4",[],{"date":12,"id":30,"title":14,"titles":31,"content":9,"level":10},"\u002Farticle\u002Fother\u002F2025-11-16-test3",[],{"date":17,"id":33,"title":19,"titles":34,"content":9,"level":10},"\u002Farticle\u002Fother\u002F2025-11-17-test2",[],{"date":22,"id":36,"title":24,"titles":37,"content":9,"level":10},"\u002Farticle\u002Fother\u002F2025-11-18-test",[],{"date":5,"id":39,"title":7,"titles":40,"content":9,"level":10},"\u002Farticle\u002Ftech\u002F2025-11-15-test4",[],{"date":12,"id":42,"title":14,"titles":43,"content":9,"level":10},"\u002Farticle\u002Ftech\u002F2025-11-16-test3",[],{"date":17,"id":45,"title":19,"titles":46,"content":9,"level":10},"\u002Farticle\u002Ftech\u002F2025-11-17-test2",[],{"date":22,"id":48,"title":24,"titles":49,"content":9,"level":10},"\u002Farticle\u002Ftech\u002F2025-11-18-test",[],{"date":51,"id":52,"title":53,"titles":54,"content":55,"level":10},"2025-11-19","\u002Farticle\u002Ftech\u002F2025-11-19-heading-style-test","标题样式测试",[],"这是一篇用于测试文章目录和各级标题样式的技术博文。",{"date":51,"id":57,"title":58,"titles":59,"content":60,"level":61},"\u002Farticle\u002Ftech\u002F2025-11-19-heading-style-test#二级标题","二级标题",[53],"二级标题通常用于划分文章的主要章节。",2,{"date":51,"id":63,"title":64,"titles":65,"content":66,"level":67},"\u002Farticle\u002Ftech\u002F2025-11-19-heading-style-test#三级标题","三级标题",[53,58],"三级标题用于组织章节中的具体主题。",3,{"date":51,"id":69,"title":70,"titles":71,"content":72,"level":73},"\u002Farticle\u002Ftech\u002F2025-11-19-heading-style-test#四级标题","四级标题",[53,58,64],"四级标题适合描述更细的实现步骤或概念。",4,{"date":51,"id":75,"title":76,"titles":77,"content":78,"level":79},"\u002Farticle\u002Ftech\u002F2025-11-19-heading-style-test#五级标题","五级标题",[53,58,64,70],"五级标题用于验证目录缩进和正文间距。",5,{"date":51,"id":81,"title":82,"titles":83,"content":84,"level":85},"\u002Farticle\u002Ftech\u002F2025-11-19-heading-style-test#六级标题","六级标题",[53,58,64,70,76],"六级标题是 Markdown 支持的最深层级，通常用于补充说明。",6,{"date":51,"id":87,"title":88,"titles":89,"content":90,"level":61},"\u002Farticle\u002Ftech\u002F2025-11-19-heading-style-test#其它内容","其它内容",[53],"目录行会根据标题深度逐级缩进，并使用交替背景色，方便在较长文章中快速定位。 这是一段引用，用于确认标题前后的正文排版不会互相影响。 const headingLevels = [1, 2, 3, 4, 5, 6];\nconsole.log(headingLevels); html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"date":92,"id":93,"title":94,"titles":95,"content":96,"level":10},"2026-09-21","\u002Farticle\u002Ftech\u002F2026-09-21-tamaasr","让Linux也用上语音输入",[],"在Linux下，我们也能愉快地畅骂AI了......",{"date":92,"id":98,"title":99,"titles":100,"content":101,"level":61},"\u002Farticle\u002Ftech\u002F2026-09-21-tamaasr#语音输入法真香","语音输入法，真香",[94],"原本我对语音输入的态度一直都是拒绝的，即便手机上的讯飞在我小学时就已经支持了这个功能，\n我也从来没用过。 但是，自从用上了vibe coding以后，我发现，面对时不时整出逆天操作的ai时，还是用语音输入畅快地骂出来比较有利于身心健康。 但众所周知呢，我又是一名常年的桌面Linux用户，至少一半的开发工作都是在Linux下进行的。在Windows下语音输入法确实很多也很完善，像用得最多的微信输入法，还有一些新兴的千问输入法等。但在Linux下，几乎就是一片空白了。 Linux下目前的方案主要聚焦于本地模型或云端api调用。 本地模型派的代表是VoCoType-linux，它使用优化后的FunASR，可以在CPU上离线运行，但本地模型的最大问题就是：缺乏商业级输入法的实时AI润色能力。 还有一些对接云端ASR api的方案，比如LexiSharp。这些实现的最大问题是：调用api要钱。我本来用AI都花钱了，骂AI再花钱那不是成冤大头了。 以及部分商业输入法在UOS\u002FKylin下提供语音输入，但显然，打死我都不会用那些信创发行版的。 那还有什么解决方案呢？",{"date":92,"id":103,"title":104,"titles":105,"content":106,"level":61},"\u002Farticle\u002Ftech\u002F2026-09-21-tamaasr#喜报您的输入法为您引入了一个新的chromium浏览器","喜报：您的输入法为您引入了一个新的chromium浏览器！",[94],"打开各种AI网页对话助手，比如豆包，我们可以惊喜地看到，在输入框的右侧，有一个语音识别的按钮。而且这种语音识别能力是跨平台的，即便在Linux下也能使用。 诶，那为什么不能靠这个功能来做个语音输入法呢？实现方案也很明晰，要么逆向对应的网页的语音识别接口链路，要么直接内置一个浏览器去从前端控制转发。 你现在看到的这个项目，TamaASR，便是第二种方案下的产物。 选二不选一的主要原因一是逆向的接口不稳定，时不时得重新适配，而前端元素改动的可能性却是非常低。而我是一个懒人，没多少精力去维护这么个业余项目。二是现在的大模型网安道德水平都高得要死，逆向请求这类操作轻易不会让你做的，想做还得搞破甲或者手搓。三是现在的设备带个electron应用基本上问题都不大，我个人是没什么electron洁癖的，多装个chromium就多装个。 至于为什么不用Tauri，我在项目仓库里也写明了，其实主要就是我的一台主力设备不兼容，使用webkit2gtk打开这些AI助手的网页是根本没法进行语音输入的。 事实上，后来我发现已经有了类似思路但是走逆向请求的项目，如Doubao Murmur，如果不喜欢内嵌一个chromium并且常驻500-700mb的内存的话，也可以看看这个项目哦。",{"date":92,"id":108,"title":109,"titles":110,"content":111,"level":61},"\u002Farticle\u002Ftech\u002F2026-09-21-tamaasr#x11-wayland-没事我们有fcitx5","X11? Wayland? 没事，我们有fcitx5",[94],"我和AI讨论这个方案时，AI就提醒我，需要注意X11和Wayland的兼容性问题。 尤其是Wayland，不得不说，可是让人又恨又爱啊。它是比X11现代化了，But at what cost？为了避免堆成屎山，Wayland选择尽可能少的协议约束，但是做桌面又不能没有那些功能，于是各家桌面环境就推出了各种碎片化的第三方协议，对于输入法这样的涉及原生事件的软件来说简直是一场灾难。 但是！输入法毕竟是桌面使用的刚需，总得有人去做的，于是我们就等来了一位“白马王子”，CJK输入法使用最广泛的框架，fcitx5。诶，那我们直接去适配fcitx5，不就能解决Wayland下的兼容问题了吗？ 于是，最难啃的部分也解决了，现在，让我们为Linux桌面带来接近微信输入法体验的高精度语音输入法吧！",{"date":92,"id":113,"title":114,"titles":115,"content":116,"level":61},"\u002Farticle\u002Ftech\u002F2026-09-21-tamaasr#选择什么后端豆包元宝千问chatgpt","选择什么后端？豆包？元宝？千问？ChatGPT？",[94],"嗯，遇到这个问题，大部分人应该还是首选豆包吧，毕竟是国内大模型多模态做的最好的。 但是！豆包的网页版存在一个严重问题：它是直接识别完后把识别内容作为对话请求发出去，这就意味着，单靠纯前端控制元素很难达成目标了，因为前端不会显示输入的中间态，在发送请求前也不会存在可抓取的前端DOM。如果坚持使用豆包就会导致实现很不优雅，首先得拦截最终的发送请求（你也不想让对话记录里一堆乱七八糟的识别内容被发给豆包吧？），其次中间态也得想办法拦截，不然最后只是整段地呈现的话，说的话一多就很难受。 于是只好转向国内的其它几家啦。国内的AI助手网页端总共也就那么几家，智谱和deepseek是没有网页端语音识别的，最后敲定使用千问和元宝。千问是最先适配的，但实测元宝会更好用点，元宝会有一个最终的AI精修的动作，而千问基本上是边说边修，结束输入就不再改动了。 至于ChatGPT，openai的whisper在业内一直都很出名，但我毕竟要做的是一个日用而且中文友好的，一个需要时刻使用魔法，中文识别也谈不上顶尖的选择就暂时不考虑了。 后来发现讯飞星火和百度文心也有符合要求的网页版语音识别，但因为元宝和千问够用了，所以一直没适配，前面说了，我懒。",{"date":92,"id":118,"title":119,"titles":120,"content":121,"level":61},"\u002Farticle\u002Ftech\u002F2026-09-21-tamaasr#适配时遇到的一些问题","适配时遇到的一些问题",[94],"Wayland: 没错，还是万恶的Wayland。因为我们需要用悬浮球显示输入状态，而在Wayland下，悬浮球一出现就会打断输入焦点，导致输入被中断。最后强制指定了x11，在Wayland下靠XWayland运行。状态不统一: 因为是靠的前端DOM进行判断和操作，所以总会因为各种莫名其妙的边界条件导致状态不统一，比如取消并再次输入太快了就会导致多次点击网页后端的输入按钮，造成网页后端维持在输入态而前台已经退出输入。electron43的托盘图标: 很难想象这么大个项目还能整出这种篓子，electron43早期的一些版本（但已经是正式版而非测试版了）的托盘图标会不显示，而我们很依赖托盘图标进入后台，最后全部指定为42。对Tauri的迷信: 毫无疑问，这种要常驻后台的Web应用，人们的第一反应肯定是Tauri。我其实也尝试过至少两版Tauri移植。但实际上，对于这个应用的很多DOM操作，Tauri其实是并没有提供对应的api的，如果想移植到Tauri，必须还得自行实现一套DOM操作和DOM状态判断的API，甚至于和移植到QtWebEngine都无异了。继续移植下去肯定也能做，但我之前也说了，我有台设备根本用不了Tauri版，而也能使用Tauri的其它设备性能要强得多，后台多挂个electron应用根本没啥影响，对我而言开发Tauri版的收益就很低了，也许以后学习Rust时会再次尝试吧。所以说，选择Tauri还是Electron，有时也不能光看刻板印象。",{"date":92,"id":123,"title":124,"titles":125,"content":126,"level":61},"\u002Farticle\u002Ftech\u002F2026-09-21-tamaasr#解放双手以后","解放双手以后",[94],"历经波折明明是烧了很多token吧，也是在Linux下用上语音输入了。不得不说还是语音输入开骂舒服啊。 项目也已经以MPL2许可证开源，欢迎各位来提出宝贵的建议，或者开发更好的方案，比如使用逆向请求或者移植到Tauri。",{"date":5,"id":128,"title":7,"titles":129,"content":9,"level":10},"\u002Farticle\u002Fworks\u002F2025-11-15-test4",[],{"date":12,"id":131,"title":14,"titles":132,"content":9,"level":10},"\u002Farticle\u002Fworks\u002F2025-11-16-test3",[],{"date":17,"id":134,"title":19,"titles":135,"content":9,"level":10},"\u002Farticle\u002Fworks\u002F2025-11-17-test2",[],{"date":22,"id":137,"title":24,"titles":138,"content":9,"level":10},"\u002Farticle\u002Fworks\u002F2025-11-18-test",[],1790509162561]