目录

任务一完成,它就蹦出来喊「妈」——给 DeepSeek Harness 养一头牛来

一个纯客户端插件的诞生:抠图修蹄子、喊声基频鉴假、嘴型时间线、WAAPI 动画三连坑,外加三只手绘小动物

DeepSeek Harness

一、先上成品

agent 干完活的那一刻,屏幕角落的小牛会蹦起来,字正腔圆地喊一嗓子「妈」——尾音拖足,嘴型跟上,中气十足:

PC 端:菜单、换皮肤、唠叨气泡、连喊三声的残影。手机端一样欢实——深色那条录到了蓝鲸喷水飞圈,浅色那条录到了奶牛和熊猫开嗓,两条的结尾都是「发消息 → agent 回完 → 蹦出来喊妈」的完整闭环:

不装 dsh 也能玩到它:这插件是纯客户端的,同一套代码原样跑在裸页面上就是个小游戏——戳下面的试玩窗(或打开全屏版),戳牛、跑个模拟任务,等它喊妈(公众号读者点「阅读原文」直达):

不认识这头牛的同学补一下背景:《牛来》是最近的一个现象级奇观——一部画风粗糙的 3D 动画片,上映前十天全国票房不到一万块,被短视频带火后一周直冲千万。全网看完都在骂,骂完接着看,号称"看了后悔 86 分钟,不看后悔一辈子",李永乐老师还专门讲过它爆火背后的禁果效应。主角那头丑得很有特色的黄牛,喊"妈"是名场面,二创鬼畜剪辑满天飞。我把它养进了 DeepSeek Harness(dsh)的 web 界面里——就是我最近连着折腾了好几篇的那个 agent 工作台。

二、为什么不是通知,是桌宠

dsh 跑任务时我经常切到别的桌面干活,完成通知这事我做过两轮:cenacle 通知中心、飞书卡片推送。都好使,但都太……正经了。

桌宠才是 AI 工作台缺的最后一块。它不提供信息,它提供情绪价值:平时在角落呼吸、眨眼、踱步、趴下打盹,偶尔冒个气泡吐槽一句「我在吃草,你在吃苦」;你跑 AI 久了它会报时「AI 已经跑了 2分13秒…」;任务完成的那一刻,它用最炸裂的方式替你庆祝。

选牛来当主角不需要理由,看到这头牛的人自然会懂。

三、它现在长什么样

/posts/2026/08/19/dsh-niulai-pet/family.png
五皮肤全家福:牛来、小黄、奶牛、熊猫、蓝鲸

  • 五个皮肤:牛来、小黄(幼年版,无角更黄亮)、奶牛、熊猫、蓝鲸——后三只没有现成素材,是我用 SVG 一只一只手绘的,蓝鲸特意调了 DeepSeek 蓝、加了虎鲸的白眼斑。
  • 签名动作:牛来连跳、小黄和熊猫翻滚、奶牛摇摆、蓝鲸弧线跃出水面(到弧顶还会喷水)。动作可以绑到事件上,也能设成随机。
  • 叫声:牛来和小黄用原声(精修降噪过),奶牛/熊猫/蓝鲸的叫声是 WebAudio 现场合成的——哞、吱、鲸鸣,零素材零依赖。
  • 唠叨气泡:AI 在跑就报耗时,闲下来就随机吐槽,嫌烦可以在菜单里关掉。
  • 右键菜单:声音/完成时喊/气泡唠叨三个开关、连喊几声、动作绑定、换皮肤,还有个「关于」页,里面写着我的一句心里话:「我尽力了,只能做成这样了😂」。

四、纯客户端插件:dsh 插件的第三种形态

技术选型上一句话就够:这个插件只有客户端dsh.client),没有任何 host 侧代码。

放到系列前两篇的坐标系里看,dsh 插件的三种形态就算凑齐了:

插件 形态 干什么
dsh-browser-fs 双面(host + client) 注册模型工具,读写浏览器端文件
dsh-cenacle-bridge 纯 bundle(host) 订阅会话事件,上报通知中心
dsh-niulai-pet 纯 client 界面层行为,订阅只读服务

桌宠唯一需要的外部信号是"哪个会话在跑/跑完了",dsh client runtime 本来就向插件发布 sessions.list 快照——订阅它即可,一行 host 代码都不用写。纯客户端的好处极其实在:改完代码 npm run build 完刷新页面就生效,永远不用重启宿主

另一个红利开头已经看到了:把 sessions 订阅换成一个模拟任务驱动,pet.ts 一行没改就跑在裸页面上——本文的在线试玩页就是这么来的,不是什么另写的复刻版。

任务完成的判定就两条:running 从 true 翻成 false(当前会话跑完),或 completed 新置位(后台会话完成,即侧边栏绿点的同一信号)。宿主太旧没有 sessions 服务时降级成纯手动戳。

五、制作过程:每一环都在打仗

形象:抠图只是开始,修图才是战役

  • 犄角没了:牛角是深炭色,颜色阈值抠图直接把它当背景丢了——一只全没,一只只剩半截。放宽暗色区间重抠才找回来。
  • 蹄子被草吃了:原帧里牛蹄埋在草里,抠出来就是两条断腿。抠图解决不了,只能造:按腿的宽度重建小腿、补上深色蹄冠。第一版是两块矩形,丑得像贴的砖;返工版改成了微梯形 + 正中分趾缝(偶蹄目的灵魂)+ 纵向渐变 + 微外八站姿。

/posts/2026/08/19/dsh-niulai-pet/feet_zoom.png
修好的蹄子:分趾缝是牛蹄的身份证

喊声:选段、鉴假、降噪

喊声备了四段候选,其中两段怎么听都不像牛来的声音——不是耳朵好,是我跑了自相关基频分析:正常奶声基频 800-889Hz,那两段只有 516-552Hz。它们是被加速过的变调段,音调跟着速度一起飞了,低近一半的基频就是铁证。

留下来的两段背景音又大(BGM 焊死在音轨里),上 ffmpeg 降噪:highpass 专治轰隆隆的低频(人声基频 800Hz,高通切到 280Hz 都伤不到它)、afftdn FFT 降噪压 BGM。我做了七档对比反复听,选定中强档——再狠人声就出"水下音"了。

嘴型:尾音要一直张着嘴

第一版的嘴是在喊声全程不停开闭的,看着像打机关枪。不对——「妈-妈~~」是两个音节,尾音是开口音:正确的时间线是张嘴 240ms → 闭 120ms(两个音节的分合)→ 重新张开,一直保持到尾音结束才闭上。

时长也不能写死:插件在挂载时预读 mp3 的 metadata 拿真实时长,嘴型、气泡都跟着音频长度走,连喊几声时是串行接龙,每声之间自然闭一下。

动画:单图变形 + 少量换帧,还有三个坑

桌宠没有序列帧素材,90% 的动作是单张 PNG 的 WAAPI 变换:呼吸是 scaleY 正弦,蹦跳带 squash&stretch,飞行是根元素走抛物线 + 机身沿切线俯仰。只有嘴型、眨眼、飞行姿态、鲸鱼喷水这几处用双帧切换。

踩了三个值得写下来的坑:

  1. pause 的动画不是透明的。呼吸动画 pause 后仍压在 img 的 transform 上(WAAPI 在级联里压内联样式),飞行时机身旋转死活不生效——改 cancel() 才行。
  2. 镜像父级里的 rotate 不能乘方向。朝向翻转用根节点 scaleX(-1),镜像会把精灵图和旋转一起翻,两个方向自洽;我多乘了一个方向系数,牛直接底朝天飞。
  3. 协程收尾别抢状态。踱步协程结束时无条件 mood = 'idle',把刚起飞的飞行状态绞杀在半空——所有收尾都加了身份检查。

叫声:零素材方案

三只手绘动物没有真声可截,干脆全部 WebAudio 合成:哞 = 锯齿波下滑 + 低频震颤 + 低通;鲸鸣 = 正弦长音先扬后抑 + 慢颤音;吱声 = 两声三角波短促上挑。总共不到 60 行代码,一个音频文件都不用下载。

手绘三小只

/posts/2026/08/19/dsh-niulai-pet/whale-compare.png
鲸鱼返工:从修长到胖圆 + 虎鲸眼斑

奶牛、熊猫、鲸鱼都是手写 SVG 渲染成 PNG,迭代了好几轮:鲸鱼的尾鳍一度像兔子耳朵,熊猫的竹子一度像拿着话筒。家族一致性靠三件套:同款描边色、大眼双高光、粉腮红。

录视频:手机录屏它不出声

开头三条视频的录制本身也是一场仗。PC 版一次成型(宿主机录屏能带上系统声音),但两条手机版遇到了新问题:手机录屏录不到系统内放——屏幕录像走的是麦克风,桌宠喊得再字正腔圆,录出来也只剩 -46dB 的环境底噪。

解法是时间戳配音法的升级版:先按 0.25 秒一帧抽接触表,把每个气泡(「妈」「哞——!」「嗯嗯!」「噗——!」)出现的精确时刻抠出来;声源不走录音——「妈」直接用仓库里的无损 mp3,奶牛/熊猫/蓝鲸的叫声则把插件里的 WebAudio 合成代码原样搬进 OfflineAudioContext 离线渲染成 WAV(和运行时发出的声音逐字节一致、零底噪);最后按时间戳 adelay 混回去,顺手把 HEVC 转成全浏览器通吃的 h264。音画对齐误差百毫秒级,音质比现场采的干净一个数量级。

六、一些小但重要的设计

  • 「喊一声」只喊不跳,「戳一下」又喊又跳——一个是嘴上功夫,一个是全身反应。
  • 静音是真静音:没有声音也没有「妈」气泡,庆祝退化成纯动作。
  • 完成时喊妈可以关,连喊几声可以设(1-3 声),动作可以绑成固定或随机。
  • 位置、皮肤、所有开关都记忆在 localStorage。

七、安装与素材

一行装上:

1
dsh plugin --profile web add github:whitefirer/dsh-niulai-pet

构建产物已入库,安装零脚本;首次安装重启一次 dsh web,之后升级刷新页面即生效。奶牛/熊猫/蓝鲸三只手绘的 SVG 源文件在仓库 tools/drawn/ 里,随便拿去用。

八、收尾

/posts/2026/08/19/dsh-niulai-pet/pet_demo.gif

至此我的 dsh 插件小系列凑齐了三种定位:通用能力、开发能力、娱乐休闲。说实话,最后一个是我打开 dsh 时嘴角上扬幅度最大的一个。

下一步:自定义皮肤(导入自己的图和声音)、按住它说话的语音控制(识别完直接发给当前会话,STT 选型调研已经躺在仓库 docs/roadmap.md 里)、插件市场收录(awesome 门槛是仓库满一天 + 提交数 ≥10,CI 自动校验,PR 已在路上)。仓库在 github.com/whitefirer/dsh-niulai-pet,素材全入库,装上即玩。

本文是「DeepSeek Harness」系列第 5 篇,共 5 篇。上一篇:把 DeepSeek Harness 开放到局域网:手机访问的几个坑与解法清单