From b345d64337eabb0296c65d78a4c9a065e5499d18 Mon Sep 17 00:00:00 2001
From: hzl <1803573449@qq.com>
Date: Wed, 12 Aug 2026 22:33:30 +0800
Subject: [PATCH 1/2] docs: clarify project purpose and usage boundaries
---
README.md | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 2230ed9..a990334 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,17 @@
-# 抖音广告跳过(Douyin Ad Skipper)
+# 抖音网页版社区片段助手(Douyin Ad Skipper)
-一个非官方、社区驱动的 Chrome 扩展,用于跳过抖音网页版中带有明确广告标识的视频,以及用户手动标记的视频内部广告片段。
+一个非官方、开源、社区驱动的浏览器扩展,用于在抖音网页版中标记视频内部的赞助、自我推广、互动提醒等可选片段,并按照用户选择显示或跳过这些片段。
+
+这个项目源于个人浏览需求,主要通过 AI 辅助完成设计、开发、测试与文档整理。它仍处于持续完善阶段,不代表成熟的商业产品;欢迎用户在 GitHub 上提出问题、分享使用体验并共同讨论改进方案。
> [!IMPORTANT]
> 本项目与抖音、字节跳动、SponsorBlock 或 BilibiliSponsorBlock 没有隶属、授权或背书关系。“抖音”仅用于说明兼容的网站。
+>
+> 本项目不是平台广告拦截器:不拦截抖音的广告请求,不隐藏或破解平台官方广告,不伪造播放、点击或曝光数据,也不绕过付费内容。它只处理用户正在观看的普通作品时间轴中的社区标记片段,所有跳过行为均可由用户关闭或撤销。
## 当前能力
-- 识别“广告 / 商业推广 / 广告推广 / 推广”等明确页面标识并切换到下一条。
-- 在抖音播放器控制栏内创建广告片段起止时间。
+- 在抖音播放器控制栏内创建视频片段的起止时间。
- 在播放器进度条中显示已标记片段:待提交为深绿色,已提交/可信片段为亮绿色。
- 再次播放同一作品时自动跳过本地草稿或社区片段。
- 可从播放器内的提交菜单把待提交片段发送到自建社区服务。
@@ -31,7 +34,7 @@
播放器底部清晰度按钮左侧会显示片段标记图标:
-1. 广告开始时点击“片段从当前开始”。
+1. 可选片段开始时点击“片段从当前开始”。
2. 图标切换为红色取消按钮和青色结束按钮。
3. 广告结束时点击“片段现在结束”,片段先作为本地草稿保存,并以深绿色显示在进度条上。
4. 此时控制栏会出现“提交”和“删除最后一个未提交片段”按钮;点击提交会打开播放器内菜单。
@@ -40,7 +43,7 @@
自动跳过时间片段后,提示条会短暂提供“撤销”按钮;社区片段还可直接赞成、反对或举报。
-片段管理页可以修改本地草稿的开始和结束时间。修改会清除预览状态,必须返回对应视频重新预览;社区片段跳过后可赞成、反对或按“时间错误、不是广告、视频不符、滥用”举报。
+片段管理页可以修改本地草稿的开始和结束时间。修改会清除预览状态,必须返回对应视频重新预览;社区片段跳过后可赞成、反对或按“时间错误、分类错误、视频不符、滥用”举报。
社区片段支持“自动跳过、显示提示手动跳过、不处理”三种模式。播放器快捷键默认为:`Alt+Z` 开始/结束片段、`Alt+X` 取消创建、`Alt+Enter` 打开提交菜单;可在选项页的“快捷键”中重新录制,在输入框中不会触发。
@@ -81,9 +84,19 @@
社区查询默认启用并连接项目公共 API,也可随时关闭或改用自建服务。扩展只查询当前作品 ID,并且仅在你主动点击提交时上传片段起止时间。完整说明见 [PRIVACY.md](PRIVACY.md)。
+## 使用边界
+
+- 只标记普通作品内部具有明确起止时间的可选片段,不处理平台插入的信息流广告或其他官方广告位。
+- 不得因为不喜欢某位创作者而标记正常内容,也不得把整部作品恶意标记为可跳过片段。
+- 不得使用本项目骚扰创作者、操纵播放数据、绕过付费服务或干扰平台正常运行。
+- 社区数据可能存在错误;用户可以关闭自动跳过、立即撤销跳过,并通过投票或举报参与纠错。
+- 网页结构和平台规则可能随时变化,请在遵守所在地法律、平台规则和创作者权益的前提下使用。
+
## 参与贡献
-欢迎提交问题、页面适配、交互改进和共享服务设计。开始前请阅读 [CONTRIBUTING.md](CONTRIBUTING.md) 和 [SECURITY.md](SECURITY.md)。
+欢迎提交问题、页面适配、交互改进和共享服务设计。无论是否会编程,都可以通过 [GitHub Issues](https://github.com/bbnotcode/douyin-ad-skipper/issues) 描述遇到的问题、讨论产品边界或提出建议;代码改动也欢迎通过 Pull Request 共同完善。
+
+本项目的大部分代码与文档由维护者在 AI 辅助下完成,并经过人工确认与测试。AI 生成内容仍可能存在疏漏,因此问题报告、代码审查和真实使用反馈尤其重要。提交代码前请阅读 [CONTRIBUTING.md](CONTRIBUTING.md),安全或隐私问题请按照 [SECURITY.md](SECURITY.md) 私下反馈,不要公开披露敏感细节。
每次推送和 Pull Request 都会运行扩展语法、清单约束、Worker 测试和 TypeScript 检查;推送 `v版本号` 标签后会自动生成不含服务器配置的 Chrome ZIP,并发布到 GitHub Releases。
From a188b965947131f587f5fb0a967a9dac6ae31549 Mon Sep 17 00:00:00 2001
From: hzl <1803573449@qq.com>
Date: Wed, 12 Aug 2026 23:28:31 +0800
Subject: [PATCH 2/2] feat: improve segment editor and refresh consistency
---
CHANGELOG.md | 9 +++
PRIVACY.md | 2 +-
README.md | 6 +-
content.css | 75 ++++++++++++++++++------
content.js | 136 ++++++++++++++++++++++++++++++++++++++++++--
manifest.json | 2 +-
server/src/index.ts | 4 +-
7 files changed, 206 insertions(+), 28 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d72801e..c8e8a34 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# 更新日志
+## 0.6.4 - 2026-08-12
+
+- 重构播放器提交窗口,按片段信息、分类、主要定位、精确编辑和提交操作分层布局,改善窄播放器中的拥挤和遮挡。
+- 每个待提交片段新增“删除此片段”“预览片段”“片段开头”“片段结尾”和“精确编辑”操作。
+- 精确编辑支持起点、终点 ±0.1 秒调整,以及可点击的“上一帧 / 下一帧”按钮和 `,` / `.` 快捷键。
+- 微调时间时改为原地更新弹窗,保持编辑区域展开,不再返回收起页面;修改后自动要求重新预览。
+- “片段开头”进入临时校准播放模式,从起点正常播放而不触发当前片段自动跳过;“片段结尾”暂停并定位到终点。
+- 社区片段查询改为强制获取最新结果,服务端禁止缓存片段查询响应,修复提交后刷新页面可能暂时无法跳过的问题。
+
## 0.6.2 - 2026-08-12
- 新增 GitHub Actions 持续集成,自动检查扩展脚本、清单、Worker 测试与类型。
diff --git a/PRIVACY.md b/PRIVACY.md
index 71a06a9..3478585 100644
--- a/PRIVACY.md
+++ b/PRIVACY.md
@@ -2,7 +2,7 @@
最后更新:2026-08-12
-## 当前版本(v0.6.2)
+## 当前版本(v0.6.4)
扩展只在 `https://www.douyin.com/*` 页面运行,并使用 Chrome `storage` 权限保存:
diff --git a/README.md b/README.md
index a990334..f73e755 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@
5. 选择本仓库根目录。
6. 打开或刷新 `https://www.douyin.com/`。
-也可以从 GitHub Releases 下载自动生成的 Chrome ZIP,解压后按上述方式加载。Release 标签必须与 `manifest.json` 版本一致,例如版本 `0.6.2` 使用标签 `v0.6.2`。
+也可以从 GitHub Releases 下载自动生成的 Chrome ZIP,解压后按上述方式加载。Release 标签必须与 `manifest.json` 版本一致,例如版本 `0.6.4` 使用标签 `v0.6.4`。
## 创建片段
@@ -38,7 +38,7 @@
2. 图标切换为红色取消按钮和青色结束按钮。
3. 广告结束时点击“片段现在结束”,片段先作为本地草稿保存,并以深绿色显示在进度条上。
4. 此时控制栏会出现“提交”和“删除最后一个未提交片段”按钮;点击提交会打开播放器内菜单。
-5. 在提交菜单逐段点击“预览”;播放器实际越过片段末尾后才允许提交。
+5. 在提交菜单使用“片段开头”“片段结尾”和“精确编辑”校准边界,再逐段点击“预览”;播放器实际越过片段末尾后才允许提交。
6. 提交成功后本地草稿会删除,亮绿色片段和管理列表从社区服务读取。
自动跳过时间片段后,提示条会短暂提供“撤销”按钮;社区片段还可直接赞成、反对或举报。
@@ -47,7 +47,7 @@
社区片段支持“自动跳过、显示提示手动跳过、不处理”三种模式。播放器快捷键默认为:`Alt+Z` 开始/结束片段、`Alt+X` 取消创建、`Alt+Enter` 打开提交菜单;可在选项页的“快捷键”中重新录制,在输入框中不会触发。
-片段可标记为“赞助/广告”“自我推广”或“互动提醒”,进度条会使用不同颜色。片段管理页支持对起点和终点进行 ±0.1 秒微调;时间变化后需要重新预览才能上传。
+片段可标记为“赞助/广告”“自我推广”或“互动提醒”,进度条会使用不同颜色。播放器提交菜单和片段管理页均支持对起点和终点进行 ±0.1 秒微调;提交菜单还可逐帧前进或后退。时间变化后需要重新预览才能上传。
和 BilibiliSponsorBlock 的默认行为一致:赞助/广告自动跳过,自我推广与互动提醒先显示提示,也可以在“社区共享”页分别改成自动跳过或不处理。
diff --git a/content.css b/content.css
index e9d4e21..f0410a2 100644
--- a/content.css
+++ b/content.css
@@ -109,34 +109,75 @@
.das-submission-menu {
position: absolute;
- right: 86px;
- bottom: 64px;
+ right: clamp(16px, 5vw, 86px);
+ bottom: 68px;
z-index: 10020;
- width: min(360px, calc(100% - 32px));
- padding: 16px;
+ width: min(440px, calc(100% - 32px));
+ max-height: min(560px, calc(100% - 92px));
+ padding: 0;
+ overflow: hidden;
border: 1px solid rgba(255,255,255,.14);
- border-radius: 12px;
+ border-radius: 16px;
color: #fff;
- background: rgba(22,24,29,.96);
+ background: rgba(18,20,25,.97);
+ backdrop-filter: blur(18px);
box-shadow: 0 16px 50px rgba(0,0,0,.45);
font: 14px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
-.das-submission-menu header { display: flex; align-items: center; justify-content: space-between; font-size: 17px; }
-.das-submission-menu header button { border: 0; color: #aaa; background: transparent; font-size: 24px; cursor: pointer; }
-.das-submission-menu p { margin: 10px 0; color: #b8bac1; }
-.das-submission-menu ol { max-height: 180px; margin: 0; padding: 0; overflow: auto; list-style: none; }
-.das-submission-menu li { display: flex; align-items:center; justify-content: space-between; gap:12px; padding: 8px 0; border-top: 1px solid rgba(255,255,255,.08); }
-.das-submission-menu li span { display:flex; flex-direction:column; }
-.das-submission-menu li small { margin-top:2px; color:#8f939d; }
-.das-submission-menu li button { padding:5px 10px; border:1px solid rgba(37,244,238,.3); border-radius:6px; color:#25f4ee; background:rgba(37,244,238,.08); cursor:pointer; }
-.das-submission-menu li select { max-width:105px; padding:5px 6px; border:1px solid rgba(255,255,255,.18); border-radius:6px; color:#fff; background:#292c33; }
+.das-submission-menu header { display:flex; align-items:center; justify-content:space-between; padding:16px 18px 11px; }
+.das-submission-menu header div { display:flex; min-width:0; flex-direction:column; }
+.das-submission-menu header strong { font-size:18px; }
+.das-submission-menu header small { margin-top:2px; color:#858a95; font-size:11px; font-weight:500; }
+.das-submission-menu header button { display:grid; flex:none; place-items:center; width:32px; height:32px; padding:0; border:0; border-radius:8px; color:#aaa; background:transparent; font-size:25px; cursor:pointer; }
+.das-submission-menu header button:hover { color:#fff; background:rgba(255,255,255,.08); }
+.das-submission-menu > p { margin:0; padding:0 18px 13px; color:#aeb2bc; font-size:12px; }
+.das-submission-menu ol { max-height:min(380px, calc(100vh - 286px)); margin:0; padding:0 10px; overflow:auto; list-style:none; scrollbar-width:thin; }
+.das-submission-menu li { display:grid; grid-template-columns:minmax(112px,auto) minmax(0,1fr); gap:12px 14px; padding:15px 8px; border-top:1px solid rgba(255,255,255,.09); }
+.das-segment-summary { display:flex; align-self:start; flex-direction:column; padding-top:2px; font-variant-numeric:tabular-nums; white-space:nowrap; }
+.das-segment-category { min-width:0; }
+.das-submission-menu li small { margin-top:3px; color:#8f939d; font-size:11px; }
+.das-submission-menu li button { min-height:32px; padding:5px 10px; border:1px solid rgba(37,244,238,.3); border-radius:7px; color:#25f4ee; background:rgba(37,244,238,.08); cursor:pointer; white-space:nowrap; }
+.das-submission-menu li button:hover { background:rgba(37,244,238,.15); }
+.das-submission-menu li button.das-active { color:#161823; background:#25f4ee; }
+.das-submission-menu li select { min-width:0; width:100%; padding:6px 8px; border:1px solid rgba(255,255,255,.18); border-radius:7px; color:#fff; background:#292c33; }
.das-submission-menu li em { color: #9da0a9; font-style: normal; }
-.das-submission-actions { display: flex; gap: 8px; margin-top: 14px; }
-.das-submission-actions button { flex: 1; padding: 9px 10px; border: 0; border-radius: 7px; color: #fff; background: #34363d; cursor: pointer; }
+.das-segment-primary-actions { grid-column:1 / -1; display:grid; grid-template-columns:1.2fr 1fr 1fr; gap:7px; }
+.das-segment-primary-actions button { display:flex; min-width:0; height:48px; align-items:center; justify-content:center; gap:7px; padding:6px 8px !important; color:#e7e9ee !important; border-color:rgba(255,255,255,.13) !important; background:rgba(255,255,255,.045) !important; }
+.das-segment-primary-actions button:first-child { color:#25f4ee !important; border-color:rgba(37,244,238,.28) !important; background:rgba(37,244,238,.09) !important; }
+.das-segment-primary-actions button:hover { border-color:rgba(37,244,238,.42) !important; background:rgba(37,244,238,.13) !important; }
+.das-segment-primary-actions button b { flex:none; font-size:15px; font-weight:500; }
+.das-segment-primary-actions button span { overflow:hidden; text-overflow:ellipsis; }
+.das-segment-secondary-actions { grid-column:1 / -1; display:flex; align-items:center; justify-content:space-between; gap:12px; }
+.das-segment-secondary-actions button { min-height:30px !important; padding:4px 2px !important; border:0 !important; color:#aeb2bc !important; background:transparent !important; }
+.das-segment-secondary-actions button:hover { color:#25f4ee !important; background:transparent !important; }
+.das-segment-secondary-actions button[data-menu-action="toggle-editor"] { display:flex; align-items:center; gap:7px; }
+.das-segment-secondary-actions button[data-menu-action="toggle-editor"] b { transition:transform .16s ease; }
+.das-segment-secondary-actions button[data-menu-action="toggle-editor"].das-active b { transform:rotate(180deg); }
+.das-segment-secondary-actions button[data-menu-action="delete-segment"] { color:#ff718d !important; }
+.das-segment-editor { grid-column:1 / -1; display:grid; grid-template-columns:36px 32px minmax(84px,1fr) 32px; gap:5px; align-items:center; }
+.das-segment-editor[hidden] { display:none; }
+.das-segment-editor > span { color:#8f939d; font-size:11px; }
+.das-segment-editor button[data-menu-action="seek-boundary"] { color:#fff; border-color:rgba(255,255,255,.14); background:#292c33; font-variant-numeric:tabular-nums; }
+.das-segment-editor button[data-menu-action="adjust"] { padding:0; font-size:17px; }
+.das-frame-controls { grid-column:1 / -1; display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:7px; padding-top:11px; border-top:1px solid rgba(255,255,255,.08); }
+.das-frame-controls button { display:flex; height:42px; align-items:center; justify-content:center; gap:8px; color:#dfe2e8 !important; border-color:rgba(255,255,255,.14) !important; background:rgba(255,255,255,.045) !important; }
+.das-frame-controls button:hover { color:#25f4ee !important; border-color:rgba(37,244,238,.4) !important; background:rgba(37,244,238,.1) !important; }
+.das-frame-controls button b { color:#25f4ee; font-size:22px; font-weight:400; line-height:1; }
+.das-frame-controls kbd { min-width:24px; padding:2px 6px; border:1px solid #4a4f5b; border-bottom-width:2px; border-radius:5px; color:#b9bdc6; background:#292c33; font:11px/1.4 inherit; text-align:center; }
+.das-submission-actions { display:grid; grid-template-columns:1.15fr .85fr; gap:10px; padding:0 18px 18px; }
+.das-submission-actions button { flex:1; min-width:0; padding:10px; border:0; border-radius:8px; overflow:hidden; color:#fff; background:#34363d; cursor:pointer; text-overflow:ellipsis; white-space:nowrap; }
.das-submission-actions button:first-child { color: #161823; background: #25f4ee; font-weight: 700; }
.das-submission-actions button:disabled { opacity: .55; cursor: wait; }
+@media (max-width: 520px) {
+ .das-submission-menu { right:8px; bottom:56px; width:calc(100% - 16px); max-height:calc(100% - 68px); }
+ .das-submission-menu li { grid-template-columns:1fr; }
+ .das-segment-primary-actions { grid-template-columns:1fr 1fr; }
+ .das-segment-primary-actions button:first-child { grid-column:1 / -1; }
+ .das-submission-actions { grid-template-columns:1fr; }
+}
+
.das-toast-actions { display:flex; gap:6px; margin-left:12px; pointer-events:auto; }
.das-toast-actions button { padding:4px 8px; border:1px solid rgba(255,255,255,.24); border-radius:6px; color:#fff; background:rgba(255,255,255,.1); cursor:pointer; }
.das-toast-actions button:hover { border-color:#25f4ee; color:#25f4ee; }
diff --git a/content.js b/content.js
index 303c59a..4305986 100644
--- a/content.js
+++ b/content.js
@@ -187,6 +187,7 @@
const videoHash = await sha256Hex(videoId);
const response = await fetch(`${apiBase}/v1/videos/by-hash/${videoHash}/segments`, {
headers: { Accept: 'application/json' },
+ cache: 'no-store',
signal: controller.signal,
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
@@ -449,7 +450,7 @@
document.querySelectorAll('.das-submission-menu').forEach((menu) => menu.remove());
}
- function openSubmissionMenu(video, videoId) {
+ function openSubmissionMenu(video, videoId, expandedSegmentId = null) {
const player = getVideoPlayer(video);
if (!player) return;
const existing = player.querySelector('.das-submission-menu');
@@ -463,9 +464,26 @@
const menu = document.createElement('section');
menu.className = 'das-submission-menu';
const allPreviewed = pending.every((item) => item.previewed === true);
- menu.innerHTML = `
提交前请逐段预览,确认开始和结束时间准确。
-先微调时间并完整预览,确认片段边界准确后再提交。
+