基于大语言模型的视频广告智能检测插件开发实战
1. 项目概述当大模型遇上视频广告检测作为一个在内容平台冲浪多年的老用户我对于视频里那些猝不及防的“硬广”和“软植入”可以说是又爱又恨。爱的是创作者需要恰饭恨的是它总在我看得最投入的时候打断节奏。手动拖动进度条太麻烦而且你永远不知道广告到底有多长。直到我遇到了VideoAdGuard一个用大语言模型LLM来“听懂”视频内容、自动识别并跳过植入广告的浏览器插件我才发现原来对抗“恰饭”可以这么优雅和智能。简单来说VideoAdGuard 是一个运行在你浏览器里的智能助手。当你打开一个B站视频时它会悄无声息地工作抓取视频的字幕或者通过语音识别获取文本然后将这些文本信息连同视频标题、置顶评论等上下文一股脑儿“喂”给一个你配置好的大语言模型比如智谱的GLM、OpenAI的GPT或者本地的Ollama。模型的任务不是和你聊天而是像一个经验丰富的审核员分析这些文本中是否存在商业推广、产品介绍等广告内容并精准地告诉你广告从第几分钟开始到第几分钟结束。插件拿到这个时间区间后就会在播放器上生成一个醒目的“跳过广告”按钮一键清净。这背后的核心逻辑是将一个复杂的、依赖人类主观判断的“广告识别”问题转化成了一个LLM擅长的“文本理解与分类”问题。它解决的痛点非常明确为用户节省时间提升观看体验的连贯性。无论你是追番剧、看科技评测还是学习知识都不再需要和突如其来的广告“斗智斗勇”。这个项目适合所有B站的深度用户尤其是那些对观看体验有要求又不想错过优质内容的人。当然如果你是一名开发者对AI应用落地、浏览器插件开发或者LLM的提示工程Prompt Engineering感兴趣这个项目的架构和实现思路也极具参考价值。2. 核心原理与方案选型为什么是“大模型插件”在深入代码之前我们得先想明白市面上已经有各种广告拦截插件了为什么还要专门做一个基于大模型的、针对B站视频内植入广告的检测工具传统的广告拦截如AdBlock主要针对的是网页上的横幅广告、弹窗广告以及视频前的贴片广告它们的工作原理是基于预定义的规则列表如EasyList去屏蔽对特定域名或HTML元素的加载。然而B站UP主口播或场景内植入的广告其内容本身就是视频流的一部分与正常内容水乳交融传统的规则拦截对此完全无能为力。2.1 技术路径的抉择面对这个难题技术上有几条路可以走基于关键词的规则匹配维护一个庞大的广告关键词库如品牌名、“购买链接”、“优惠券”等在字幕中进行匹配。这种方法简单粗暴但误杀率和漏杀率会非常高。UP主可能只是客观评价某个产品或者品牌名本身就是视频主题如数码评测这都会被错误识别。传统的机器学习分类模型训练一个二分类模型广告/非广告。这需要大量已标注的视频片段广告标签数据标注成本极高且模型的泛化能力有限。UP主们创意无限广告形式千变万化一个固定模型很难跟上节奏。基于大语言模型LLM的理解与推理这正是VideoAdGuard选择的道路。LLM特别是经过海量文本训练的大模型具备强大的上下文理解、语义分析和逻辑推理能力。它不需要预先知道“瑞幸咖啡”或“某手机品牌”是广告它可以通过分析整段文本的语义、语气和商业意图来判断。例如模型能理解“本期视频由XXX赞助播出”和“我个人很喜欢喝XXX的咖啡”之间的本质区别。为什么这个选择是合理的零样本或少样本学习LLM无需针对“B站广告”进行专门训练凭借其已有的通用知识就能完成判断极大降低了开发门槛。强大的上下文理解模型可以综合视频标题可能包含“测评”、“开箱”、置顶评论可能有“老板大气”、以及字幕全文来做综合判断准确度远高于孤立的关键词匹配。灵活可迭代广告识别的逻辑完全封装在给模型的“提示词”Prompt中。如果发现某种新的广告话术模型识别不了我们不需要重新训练模型只需要优化Prompt即可迭代成本极低。2.2 架构设计插件作为最佳载体确定了用LLM作为大脑下一个问题就是载体。为什么是浏览器插件而不是一个独立的桌面应用或手机App无缝集成浏览器插件可以深度嵌入B站网页直接操作DOM获取视频播放器实例、字幕元素并能在页面上任意位置添加UI组件如“跳过广告”按钮。这种集成度是其他形式难以比拟的。跨平台与便捷性Chrome、Edge、Firefox等主流浏览器都支持相同的插件标准Manifest V3一次开发多平台使用。用户只需在商店点击安装无需下载安装包或配置复杂环境。性能与隐私平衡核心的文本分析和广告判断发生在云端你配置的LLM API插件只负责数据采集、结果展示和用户交互。这既利用了云端模型的强大能力又避免了在用户本地进行繁重的AI推理可能带来的性能问题。同时视频流、字幕等原始数据仅在插件与API之间传输符合最小化原则。油猴脚本的局限性项目早期也提供了油猴脚本版本但油猴脚本在权限、API调用稳定性、以及本地存储管理上限制较多难以实现复杂的功能和良好的用户体验。因此插件版成为了主力开发和维护的方向。注意选择LLM方案也意味着项目强依赖于外部API服务的可用性、成本和响应速度。这是架构上的一个关键权衡用一定的外部依赖换来了开发效率和识别效果的巨大提升。3. 插件深度配置与模型接入实战安装插件只是第一步让它真正“聪明”起来的关键在于配置一个合适的大语言模型API。VideoAdGuard设计了一个非常灵活的配置界面支持几乎市面上所有主流的LLM服务提供商。下面我将带你一步步完成配置并解释每个选项背后的考量。3.1 配置界面详解安装插件后点击浏览器工具栏上的VideoAdGuard图标会弹出配置面板。核心设置区域如下启用插件总开关。关闭后插件将完全停止工作。大语言模型LLM设置这是核心中的核心。SDK类型下拉菜单选择你使用的API服务商兼容的协议。这是最关键的一步选错了会导致后续所有配置都无法连通。API地址API服务的端点URL。API密钥你的身份凭证务必妥善保管。模型名称指定要使用的具体模型如glm-4-flash、gpt-3.5-turbo等。音频识别API可选用于处理没有字幕的视频。目前主要支持Groq的Whisper服务。高级功能自动跳过开启后检测到广告时将自动快进跳过无需手动点击按钮。UP主白名单你可以添加你信任的、认为其内容不含广告或你不想跳过其广告的UP主ID。插件会忽略这些UP主的视频。限制模式开启后插件仅在视频信息中包含商品链接如“视频简介里有链接”时才启动检测可以节省API调用次数。3.2 主流模型接入实战指南这里我以三个最典型的场景为例给出详细的配置步骤和避坑指南。场景一使用国内便捷服务——智谱AIGLM智谱AI的GLM系列模型在国内访问速度快价格相对实惠是很多开发者的首选。获取API Key前往 智谱AI开放平台 注册并登录在“API密钥”页面创建新的密钥。插件配置SDK类型选择“OpenAI 兼容”。因为智谱的API接口设计与OpenAI高度兼容。API地址填写https://open.bigmodel.cn/api/paas/v4/。这是智谱V4 API的通用地址。API密钥填入你在第一步获取的Key。模型名称根据你的需求选择例如追求速度选glm-4-flash追求效果选glm-4-plus。具体可用模型请查阅平台文档。实操心得智谱的glm-4-flash模型在广告识别这个任务上性价比极高响应速度快识别准确度完全够用。首次配置后建议找一个你知道有广告的视频进行测试观察控制台F12的输出确认API调用成功且返回了正确的时间区间。场景二使用国际主流服务——OpenAIGPT如果你有稳定的国际网络环境OpenAI的GPT系列模型是可靠的选择。获取API Key访问 OpenAI平台 创建新的密钥。插件配置SDK类型选择“OpenAI 兼容”。API地址默认即为https://api.openai.com/v1/无需修改。API密钥填入你的OpenAI Key。模型名称推荐使用gpt-3.5-turbo或gpt-4o-mini。gpt-4-turbo效果更好但成本也更高。对于广告识别gpt-3.5-turbo通常已绰绰有余。注意事项使用OpenAI API需要特别注意费用。广告识别每次调用消耗的token数取决于字幕长度虽然单次费用极低但长时间高频使用也会积累。务必在OpenAI后台设置用量限制。场景三追求隐私与可控——本地Ollama模型如果你希望所有数据不出本地或者想用最新的开源模型Ollama是完美的解决方案。安装并运行Ollama前往 Ollama官网 下载对应操作系统的安装包安装后通过命令行拉取一个模型例如ollama pull llama3.2:3b这是一个较小的模型适合测试。运行ollama serve启动服务。插件配置SDK类型选择“自定义 Fetch”。这个选项允许你直接向任意HTTP端点发送请求。API地址填写你的Ollama服务地址通常是http://localhost:11434/v1。/v1是Ollama提供的OpenAI兼容端点。API密钥本地服务通常不需要密钥此栏可以留空或随意填写。模型名称填写你在Ollama中拉取的模型名称如llama3.2:3b。关键避坑点浏览器插件出于安全限制默认不允许向localhost或非HTTPS地址发起请求这会导致跨域CORS错误。解决方法是启动Ollama时设置允许所有来源在终端中执行OLLAMA_ORIGINS* ollama serveLinux/macOS或在环境变量中添加OLLAMA_ORIGINS为*Windows。这是本地部署中最容易踩的坑。服务类型优势劣势适用场景智谱AI等国内云服务访问速度快文档中文支持好价格适中可能受国内监管政策影响国内用户首选追求稳定和便捷OpenAI等国际云服务模型能力强生态成熟更新快需要网络环境有使用成本响应可能稍慢有国际网络对模型效果有更高要求本地Ollama模型数据完全隐私零网络延迟零API费用需要本地算力模型效果可能弱于顶级云服务配置稍复杂对隐私极度敏感有本地GPU资源喜欢折腾的开发者3.3 音频识别功能的配置对于没有字幕的视频比如一些生活Vlog、街头采访插件会自动切换到音频识别模式。这个功能依赖Groq提供的免费Whisper语音转文字服务。获取Groq API Key访问 Groq控制台 注册并获取API密钥。插件配置在配置面板的“音频识别API”部分填入Groq的API密钥即可。API地址通常是预置好的。重要提醒Groq服务在国内网络环境下可能无法直接访问。这是使用该功能的前提条件。音频识别会先下载一小段音频数据非完整视频发送给Groq进行识别会产生少量的网络流量。4. 核心工作流程与代码级解析理解了配置我们深入到插件内部看看从你打开一个B站视频到屏幕上出现“跳过广告”按钮这中间究竟发生了什么。这个过程完美体现了现代AI应用前后端协作的典型模式。4.1 字幕检测模式全流程拆解这是插件最主要的工作路径逻辑清晰分为以下几步第一步内容抓取与上下文构建当插件检测到页面URL匹配B站视频模式如www.bilibili.com/video/BV...且视频开始加载时它便开始工作。获取字幕插件通过监听视频播放器事件和扫描页面DOM获取B站播放器生成的.bpx-player-ctrl-subtitle或.bilibili-player-video-subtitle等元素内的文本。这些字幕可能是CC字幕创作者上传或AI生成字幕。插件会以一定频率如每秒采样收集当前时间点及前后一段时间窗口内的字幕文本合并成一段连贯的上下文。获取视频元信息同时插件会抓取视频的标题h1标签、UP主信息以及视频简介区的置顶评论。这些信息为LLM判断提供了宝贵的背景。例如标题是“【实测】XXX手机一周使用报告”那么视频中出现该手机品牌详细介绍的概率就很高。构建Prompt插件将以上信息组装成一个精心设计的提示词Prompt发送给LLM。这个Prompt是识别准确度的灵魂它大致是这样的你是一个视频内容分析助手。请分析以下视频片段内容判断其中是否包含商业推广、产品植入或广告内容。 视频标题[这里是视频标题] 视频片段字幕[这里是合并后的字幕文本] 附加信息[这里是置顶评论等内容] 请严格按照以下JSON格式输出且只输出JSON { has_ad: true/false, ad_segments: [{start: 开始时间(秒), end: 结束时间(秒)}], reason: 你的判断理由 } 如果has_ad为false则ad_segments为空数组。 开始和结束时间请基于提供的字幕上下文进行估算。提示这个Prompt的设计非常关键。它明确了角色、任务、输入和严格的输出格式。强制JSON输出便于插件解析而要求提供“reason”则有助于后期调试和优化Prompt。第二步大模型推理与结果解析API调用插件使用配置的SDKAxios或Fetch将构建好的Prompt发送到你配置的LLM API端点。结果处理收到LLM返回的JSON后插件首先验证格式是否正确。然后它会提取ad_segments数组。这里有一个细节LLM返回的时间可能是基于文本叙述估算的如“视频中段”插件会结合当前视频播放器的总时长和字幕出现的时间点将这些相对时间或描述性时间转换为精确的秒数。第三步UI交互与缓存渲染跳过按钮一旦解析出有效的广告时间段插件会在B站播放器的右下角或其他不遮挡内容的位置动态插入一个“跳过广告”按钮。这个按钮绑定了一个点击事件点击后会将视频的当前播放时间currentTime设置为广告片段的结束时间。智能缓存每次成功的检测结果以视频的BV号或AV号为键都会被缓存到浏览器的本地存储如localStorage或chrome.storage.local中并设置一个24小时的过期时间。当你再次观看同一个视频时插件会先检查缓存。如果存在未过期的缓存则直接使用缓存的结果瞬间显示跳过按钮无需再次调用昂贵的LLM API。这极大地提升了重复观看的体验并节省了API费用。4.2 音频识别模式的降级策略当插件发现当前视频没有任何字幕时就会自动触发音频识别流程作为降级方案。音频流提取插件通过B站播放器的API或分析网络请求获取视频的音频流URL。它不会下载整个视频而是通常只下载前几分钟或根据策略采样部分音频以平衡识别效果和网络开销。语音转文本将下载的音频数据发送到Groq的Whisper API进行语音识别得到文本字幕。后续流程接下来的步骤就与字幕检测模式完全一样了构建Prompt - 调用LLM - 解析结果 - 显示按钮。注意音频识别模式受限于语音识别的准确度尤其是背景嘈杂或口音较重时且需要额外的网络请求因此其准确性和速度通常不如直接使用原生字幕。它被设计为一种保底方案。4.3 关键代码片段与实现要点让我们看看项目中一些核心的实现片段这能帮助我们更好地理解其工作原理。1. 监听视频状态与获取字幕插件需要知道视频何时加载、播放、暂停以及如何获取字幕。这通常通过监听播放器事件和MutationObserver监听DOM变化来实现。// 伪代码示意核心逻辑 class VideoMonitor { constructor() { this.videoElement document.querySelector(video); this.subtitleContainer null; this.init(); } init() { // 监听视频加载元数据 this.videoElement.addEventListener(loadedmetadata, this.onVideoReady.bind(this)); // 使用MutationObserver监听字幕区域的变化 this.setupSubtitleObserver(); } onVideoReady() { // 视频就绪开始检测流程 this.detectAd(); } getCurrentSubtitles() { // 从字幕容器中提取当前显示的文本 if (!this.subtitleContainer) return ; return this.subtitleContainer.innerText.trim(); } // 检测广告的主函数 async detectAd() { const bvid this.getBVIDFromURL(); // 从URL提取BV号 // 1. 检查缓存 const cachedResult await cacheManager.get(bvid); if (cachedResult !cacheManager.isExpired(cachedResult)) { this.renderSkipButton(cachedResult.ad_segments); return; } // 2. 无缓存收集数据 const subtitles await this.collectSubtitlesOverTime(30); // 收集30秒字幕 const videoInfo await this.fetchVideoInfo(bvid); // 获取标题、评论等 // 3. 调用LLM const llmResult await llmService.analyze({ title: videoInfo.title, subtitles: subtitles, topComment: videoInfo.topComment }); // 4. 缓存并渲染 await cacheManager.set(bvid, llmResult); this.renderSkipButton(llmResult.ad_segments); } }2. 与LLM API通信项目抽象了一个LLM服务层根据配置的SDK类型来调用不同的后端。// 简化版的LLM服务接口 interface LLMService { analyze(context: VideoContext): PromiseAdDetectionResult; } class OpenAIService implements LLMService { async analyze(context: VideoContext): PromiseAdDetectionResult { const prompt this.buildPrompt(context); // 构建上文提到的Prompt const response await fetch(this.config.apiEndpoint, { method: POST, headers: { Authorization: Bearer ${this.config.apiKey}, Content-Type: application/json, }, body: JSON.stringify({ model: this.config.model, messages: [{ role: user, content: prompt }], response_format: { type: json_object }, // 强制JSON输出 temperature: 0.1, // 低温度使输出更确定 }), }); const data await response.json(); return this.parseResponse(data); // 解析返回的JSON } }3. 渲染跳过按钮按钮的渲染需要确保不与B站原有的UI冲突并且位置跟随播放器。function renderSkipButton(segments) { // 移除可能已存在的旧按钮 const oldButton document.getElementById(videoadguard-skip-btn); if (oldButton) oldButton.remove(); const currentTime videoElement.currentTime; const relevantSegment segments.find(s currentTime s.start currentTime s.end); if (relevantSegment) { const button document.createElement(button); button.id videoadguard-skip-btn; button.textContent 跳过广告 (${Math.ceil(relevantSegment.end - currentTime)}s); button.style.cssText position: absolute; bottom: 80px; right: 20px; z-index: 9999; padding: 8px 16px; ...; button.addEventListener(click, () { videoElement.currentTime relevantSegment.end; button.remove(); }); // 找到B站播放器的控制栏容器将按钮添加进去 const controlBar document.querySelector(.bpx-player-control-wrap); if (controlBar) { controlBar.appendChild(button); } } }5. 常见问题排查与实战优化技巧即使配置正确在实际使用中也可能遇到各种问题。下面是我在长期使用和测试中总结出的常见问题及其解决方法以及一些让插件更好用的进阶技巧。5.1 问题排查清单当你发现插件不工作没有出现跳过按钮时可以按照以下步骤进行排查问题现象可能原因排查步骤与解决方案插件图标灰色或不响应插件未启用或脚本未注入1. 点击插件图标检查弹出面板中“启用插件”开关是否打开。2. 刷新B站视频页面。3. 检查浏览器扩展管理页面确保VideoAdGuard已启用。控制台有错误日志API配置错误、网络问题或LLM返回异常1. 按F12打开开发者工具切换到“Console”标签页。2. 查看红色错误信息。常见错误-Network Error或CORS error: API地址错误或本地Ollama跨域问题。检查地址为Ollama设置OLLAMA_ORIGINS*。-401 Unauthorized: API密钥错误或过期。重新生成并填写密钥。-404 Not Found: 模型名称错误或API路径不对。核对模型名和文档。-Invalid JSON response: LLM没有返回标准JSON。可能是Prompt被拒或模型不稳定。尝试降低请求的temperature参数如果配置支持。只有部分视频有效视频无字幕且未配置/音频识别失败1. 确认当前视频是否有字幕CC或AI字幕。2. 若无字幕检查是否配置了Groq API密钥用于音频识别。3. 检查网络是否能访问Groq服务。跳过按钮出现但时间不准LLM判断偏差或时间转换误差1. 这是当前技术的局限性。LLM根据文本推断时间点本身就不精确。2. 可以尝试在插件设置中开启“调试模式”查看LLM返回的原始理由(reason)了解其判断依据。3. 对于固定UP主的固定广告模式可以考虑手动校准后提交反馈。消耗大量API额度观看视频过多或缓存未生效1. 确保缓存功能正常工作。可以打开浏览器开发者工具的“Application”标签查看Local Storage或IndexedDB中是否有插件的缓存数据。2. 考虑开启“限制模式”仅对可能有广告的视频进行检测。3. 使用更轻量的模型如glm-4-flash替代glm-4-plus。5.2 进阶使用与优化技巧平衡精度与成本模型选择策略日常使用glm-4-flash或gpt-3.5-turbo是绝佳选择响应快成本低对于大多数口播广告识别率已经很高。关键场景如果你在看非常重要的评测或学习视频对跳过精度要求极高可以临时在设置中切换到更强大的模型如glm-4-plus或gpt-4看完再切回来。隐私至上长期大量使用且拥有性能足够的电脑最好有GPU本地部署Qwen2.5:7b或Llama 3.2等模型是最安心、长期成本最低的方案。Prompt微调以提升准确率高级如果你发现插件对某类广告如“感谢观众老爷的充电”识别不准可以尝试理解其Prompt逻辑。虽然插件UI未提供直接修改Prompt的入口但作为开发者你可以通过修改源码中的Prompt模板来优化。核心思路是在提供给模型的系统指令或用户Prompt中更清晰地定义“广告”的边界增加或减少示例。例如可以强调“仅当内容明确包含产品推广、购买引导或赞助声明时才判定为广告主观体验分享不计入”。利用“UP主白名单”功能这个功能非常实用。如果你特别喜欢某个UP主并且不介意甚至喜欢看他的“恰饭”环节因为可能做得很有趣或者你信任某个知识区UP主不会插入硬广就可以将他的UID加入白名单。这样插件会完全跳过对他视频的检测过程既节省了API调用又保留了完整的观看体验。“限制模式”的妙用开启“限制模式”后插件会先扫描视频简介区、评论区顶部寻找是否有商品链接如京东、淘宝链接。只有检测到这类明确商业线索时才会启动LLM进行深度内容分析。这能有效过滤掉大量纯粹的知识分享、游戏实况等无广告视频将宝贵的API调用次数用在“刀刃”上对于使用付费API的用户来说这是控制成本的利器。手动校准与反馈插件在播放器右侧设置菜单中点击跳过按钮旁的齿轮图标通常提供“标记广告”或“反馈误判”的入口。当你发现广告时间段识别不准时可以手动调整开始和结束时间点并提交反馈。这些数据如果能汇聚到开发者那里将有助于整体模型的优化。这也是开源项目用户参与共建的一种方式。这个项目巧妙地利用了大语言模型的通用理解能力解决了一个非常具体的用户体验痛点。它不需要训练专门的模型而是通过Prompt Engineering将问题“翻译”成LLM能理解的任务。整个架构清晰、模块化前端插件负责采集与交互后端AI服务负责核心推理缓存机制保证了效率。在使用过程中合理配置API、理解其工作流程并善用高级功能就能让它成为你浏览B站时不可或缺的智能伴侣。