如果你也在做前端对接豆包api的联动,最可能的场景之一就是直播间互动。我之前写过一个系列,第一篇搭好了服务端和整体方案,这篇是第二篇,重点落在浏览器侧的两块硬骨头:插件开发和网页捕捉。
在做这个项目之前,我以为最难的会是模型接口或者prompt设计,真正上手之后才发现,豆包api的对接反而只花了一个晚上,剩下三天全部消耗在“怎么稳定地知道直播间里发生了什么”“怎么把捕捉到的内容安全地送进大模型”这两件事上。这篇就把我踩过的坑、最终采用的方案、以及那些在文档里不太会写清楚的细节一次性说透。
开始之前把边界说清楚:我做的这个插件,定位是主播/运营的辅助工具。它读取的是用户打开抖音直播间页面后、浏览器里已经渲染出来的公屏内容(也就是任何打开直播间的用户都能看到的那部分),不碰直播间的私有接口,不做批量采集,更不做绕过平台规则的自动化操作。所有“互动”,我都会设计成AI生成候选话术、再由人工确认后发出的形式。这样既解决了真实需求,也把合规风险摁在了最低。
1. 为什么第2篇要拆成“插件开发”和“网页捕捉”两件事
1.1 整个系列在做什么
先花半分钟对齐一下全景。整个项目做的是:在抖音直播间场景里,让豆包大模型根据直播间正在发生的互动内容,辅助主播或运营快速生成回应话术。
整体链路是这样的:
浏览器插件负责两件事。第一,捕捉直播间页面中实时滚动的公开互动内容;第二,把捕捉到的内容整理后发给豆包api,拿到生成结果再展示回去。中间可以通过一个自己的轻量服务来保管密钥、做限流和审计。
我第一篇文章里已经把这个中转服务搭好了,所以第2篇从一开始就默认“插件侧拿到的key是一个有时效的临时凭证”,而不是直接在浏览器里硬编码主密钥。
1.2 为什么“网页捕捉”必须放在前端
有人可能问:既然抖音有那么多直播数据,为什么不直接在Node服务端去捞?我的回答是:个人开发者做辅助工具,最忌讳的就是去逆向对方的内部接口。你一旦去解析那些私有协议,一方面账号风险极大,字节的防护团队不是吃素的;另一方面你的代码会随对方接口变更频繁失效,维护成本高到离谱。
反过来,网页捕捉走的是另一条路:抖音直播间的网页版本身是一个运行在浏览器里的应用,公屏上的互动内容最终都会渲染成DOM节点。浏览器插件天生就有权限去读取“当前页面渲染后的状态”。这是每一个普通用户都能看到的内容,也是各家浏览器扩展最常见的运行方式。
这条路的最大优势是稳定。只要页面渲染逻辑不改成canvas绘制,基于DOM读取的实现就能兼容很久。如果哪天它真的改成canvas绘制了,那也不是普通辅助工具该去解的方向,你可以直接放弃“自动捕捉”改成“半自动复制粘贴”。
1.3 技术选型:Chrome扩展、油猴脚本还是独立网页
我当时在三种方案之间犹豫了很久,列个对比供参考:
| 方案 | 优点 | 缺点 | 结论 |
|---|---|---|---|
| Chrome扩展(MV3) | 权限清晰、生命周期可控、适合处理跨域请求 | 开发调试比普通网页麻烦 | 首选 |
| 油猴脚本 | 开发最快,几行代码就能注入 | 跨域请求受限多、权限边界模糊、用户安装门槛高 | 原型验证可以,正式不合适 |
| 独立后台服务定时扫页面 | 不需要浏览器插件 | 你拿不到直播间页面DOM,除非用无头浏览器,太重且容易被识别 | 不推荐 |
Chrome扩展里还有一个细分选择:用纯原生JS还是用前端工程化框架。我的建议是,不要因为自己是前端开发就条件反射上React。这个插件的核心逻辑在content script和background,UI只有一个悬浮面板,用原生JS加少量CSS完全够用。构建工具会引入很多content script场景下的兼容性问题(后面踩坑章节会讲),能不上就不上。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 豆包api的前端调用姿势:鉴权、SSE解析、上下文裁剪
2.1 鉴权信息不要直接塞进插件
很多人做第一个版本会把API Key直接写死在插件代码里,本地自用没问题,但只要你想发给别人用,或者代码开源,这就是事故。
我在第一篇文章里做的方案是:插件向自己的服务端要一个短时凭证,服务端拿这个凭证去调用豆包api。这里涉及两个层级。
如果只是自己一个人用,并且你的插件只在本机跑,那么用豆包官方的API Key直连其实也能接受。但有两个前提:第一,这个Key只放在background脚本里,绝不放进content script或者页面注入的脚本里;第二,你的Chrome浏览器本身要有基本的系统安全保护,别把导出的Key发到任何聊天工具里。
如果是要做成一个小工具分发给同团队的朋友,就必须走中转。原因很简单:Key在任何一个同事的浏览器里都等于裸奔,随时可能被翻出来滥用。中转服务可以做到按人签发令牌、按天限流、记录调用日志,出问题了能追溯。
2.2 一段可以直接跑的fetch请求
豆包api的服务地址是火山方舟的OpenAI兼容接口,这意味着凡是习惯用OpenAI SDK的人,切换到豆包只需要改base_url和model名。在纯前端环境里,我们不需要SDK,直接fetch就行。
一段最精简的请求大概是这个样子:
javascript复制const response = await fetch('https://ark.cn-beijing.volces.com/api/v3/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + accessToken
},
body: JSON.stringify({
model: 'doubao-seed-1-6-250615',
messages: [
{
role: 'system',
content: '你是一个直播间互动助手,你会根据弹幕内容生成简洁、自然、有网感的口播回应。'
},
{
role: 'user',
content: '以下是最新的弹幕内容,请基于这些内容给出一句适合口头回应的话。\n' + bulletText
}
],
stream: true,
temperature: 0.8
})
});
需要注意三点:
第一,model字段的值不是固定的,豆包模型版本更新很频繁,一定要以方舟控制台页面里显示的模型ID为准,不要抄我这里的示例。我见过太多人拿别人博客里的模型名去调,返回404然后怀疑人生。
第二,如果你是自己用API Key直连,Host可以写死;如果你走了中转,这里的URL就换成你自己的服务地址,
