# dysync.net - 抖音同步工具(抖小云) `dysync.net` 是一款基于 **.NET Core ** 和 **Vue** 开发的工具,用于同步抖音收藏夹、「我喜欢」的视频及指定博主作品,支持多账号同步,内置视频信息刮削功能,同步后的视频可直接在 Emby 或 Jellyfin 中播放。 > 🔧 **问题反馈**:如使用中遇到任何问题,欢迎进Q群反馈:759876963,不一定及时回复,见谅。 --- ## 📺 Emby 效果预览  --- ## 📋 目录 - [dysync.net - 抖音同步工具(抖小云)](#dysyncnet---抖音同步工具抖小云) - [📺 Emby 播放效果预览](#-emby-播放效果预览) - [📋 目录](#-目录) - [1. 获取抖音关键信息(必做!同步核心凭证)](#1-获取抖音关键信息必做同步核心凭证) - [1.1 提取抖音 Cookie](#11-提取抖音-cookie) - [1.2 提取 `sec_user_id`(个人/指定博主)](#12-提取-sec_user_id个人指定博主) - [2. 路径映射规则(核心!错配会导致无法访问/数据丢失)](#2-路径映射规则核心错配会导致无法访问数据丢失) - [2.1 直接同步到 WebDAV(AList/OpenList)](#21-直接同步到-webdavalistopenlist) - [2.2 升级后将本地视频迁移到 WebDAV](#22-升级后将本地视频迁移到-webdav) - [2.3 WebDAV 自动化与真实服务测试](#23-webdav-自动化与真实服务测试) - [3. 默认账号密码(首次登录用)](#3-默认账号密码首次登录用) - [4. 运行方式(推荐 Docker Compose)](#4-运行方式推荐-docker-compose) - [镜像版本](#镜像版本) - [构建命令示例](#构建命令示例) - [方式一:Docker 命令行](#方式一docker-命令行) - [方式二:Docker Compose 运行(推荐)](#方式二docker-compose-运行推荐) - [🚀 5. 软件截图](#-5-软件截图) - [🚀 5. 已有功能与计划](#-5-已有功能与计划) --- ## 1. 获取抖音关键信息(必做!同步核心凭证) Cookie 及 `sec_user_id` 是同步功能的核心,需严格按步骤获取,避免遗漏或错误。 ### 1.1 提取`Cookie`以及 `sec_uer_id` 1. 打开 **抖音网页版** (https://www.douyin.com/) 并登录目标账号; 2. 进入个人主页,按下F12进入开发者模式、并切换到 `网络`(也可能叫`network`). 3. 在筛选框中输入`/follow`. 4. 点击自己头像边上的 `关注` 按钮、会弹出你的关注列表,然后在右侧网络请求里面会出现多个请求,随便选一个. 4. 在请求的标签里面切换到`负载`(也可能叫`payload`) 5. 找到sec_user_id,复制值即可 6. 在请求的标签里面切换到`标头`(也可能叫`Headers`) 7. 往下拉,直到出现`Cookie` ,复制完整的值,注意前后不要带换行符,很多人会多复制个换行符出来.     ### 1.2 提取 博主的`sec_user_id`以及博主的uid - **对于想下载博主视频,但是又不想关注博主,需要用到** - 1.进入博主主页,按`F12` 点击`Network` 或`网络` 筛选器里面填`/web/aweme/post` 然后切到`预览`或`preview` 展开 json数据结果 找到`aweme_list` 然后随便点开其中一个子项 即可找到`aweme_list[0].author.sec_uid` 这便是博主的uid 。后续在关注列表中,需要手动添加非关注博主同步视频时将会要用到。  --- ## 2. 路径映射规则(核心!错配会导致无法访问/数据丢失) 为实现视频在 Emby/Jellyfin 中正常播放及数据持久化,需正确配置本地路径与容器路径的映射: | 存储类型 | 容器内路径 | 本地路径配置要求 | 用途说明 | | ------------ | --------------- | --------------------------------------------------------------------- | -------------------------- | | 个人收藏视频 | `/app/collect` | 映射到本地目录(如 NAS:`/volume1/抖音/收藏`、电脑:`D:/抖音/收藏`) | 存储同步后的收藏视频 | | 个人喜欢视频 | `/app/favorite` | 映射到本地目录(建议与收藏视频路径区分,如 `/volume1/抖音/喜欢`) | 存储同步后的「我喜欢」视频 | | 图文视频 | `/app/images` | 映射到本地目录(建议与收藏视频路径区分,如 `/volume1/抖音/图文视频`) | 存储同步后的「图文视频」 | | 指定博主视频 | `/app/uper` | 映射到本地目录(如 `/volume1/抖音/博主作品`) | 存储同步后的博主视频 | | 指定博主视频 | `/app/mix` | 映射到本地目录(如 `/volume1/抖音/合集`) | 存储同步后的合集视频 | | 指定博主视频 | `/app/series` | 映射到本地目录(如 `/volume1/抖音/短剧`) | 存储同步后的短剧视频 | | 数据库文件 | `/app/db` | 映射到本地稳定目录(如 `/volume1/抖音/db`) | 持久化配置、同步记录 | | 数据库文件 | `/app/mp3` | 映射到本地稳定目录(如 `/volume1/抖音/mp3`) | 图文视频自定义音频(用于原视频音频带版权的情况) | > ✅ **关键注意**: > 1. 抖音授权时配置的路径为上面 表格里面 容器内路径 如 `/app/collect` 且注意 必须是`/`开头,路径可以自己随便命名,只要保证 授权里面配的路径有在docker-compose里面添加映射即可 > 2. 未配置路径映射时,文件仅存于容器内部,且容器删除后数据丢失。   --- ### 2.1 通过 OpenList 原生 API 同步到远端 `0.2.22` 不再使用 WebDAV 上传新内容。应用先把完整文件写入本地共享中转目录,再调用 OpenList `/api/fs/copy` 在服务端复制,并通过暂存目录、移动和长度校验原子提升到最终路径。OpenList 返回外部云盘签名地址时不会向该域名转发 OpenList Token,避免移动云 Range 校验返回 400,并防止登录凭据跨主机发送。 `0.2.23` 将“检测存储”固定显示在任务中心顶部;存储正常时可随时主动检测,熔断后会自动变为“重新检测存储”。移动端按钮独占一行,不再依赖警告框的操作区域。 `0.2.24` 修复 OpenList 新视频目录尚未创建时被误判为存储故障的问题。应用会继续保留已有目录的服务端真实大小写,并把缺失的尾部路径交给安全传输流程创建。抖音作品列表和媒体连接超时会进行两次带退避的有限重试;切换到 OpenList 后遗留的旧 WebDAV 同步任务会在启动恢复阶段安全终结并隐藏,不删除视频记录或媒体文件。普通同步成功切换存储但旧本地文件清理失败时,任务条目会显示“重试清理旧文件”,再次验证远端主媒体后才执行清理。 `0.2.25` 补齐 OpenList 对象检查的强制刷新分支:远端尚未创建的新视频目录会稳定返回“不存在”并进入下载,不再在 `ExistsAsync` 的第二次检查中误报 `object not found`。新建目录后会进行总计最多约 7.5 秒的有限刷新确认,以兼容远端云盘的可见性延迟;若服务端确实自动改名,仍会停止写入以避免生成重复目录。 当底层云盘目录大小写不敏感时,应用会根据 OpenList 目录列表解析真实名称。例如逻辑路径 `/collect/Kk` 会稳定复用现有 `/collect/KK`,不会再触发 `Kk_日期_时间` 自动改名。任务中心的“修复异常目录”会严格筛选时间后缀候选,逐个检查并等待人工确认;删除前还会复检,只删除空目录。 1. 在 fnOS 或宿主机创建应用可写的本地中转目录。 2. 在 OpenList 中添加一个本地存储驱动,让“源挂载目录”指向同一个物理目录。应用与 OpenList 看到的路径名称可以不同,但内容必须完全对应。 3. 进入“系统配置 → 媒体存储”,选择 **OpenList 原生 API**。地址填写站点根地址,例如 `http://192.168.1.2:5244`,不要填写 `/dav`。 4. 填写本地中转目录、OpenList 源挂载目录和目标基础目录,然后执行“测试完整复制链路”。测试会验证登录、本地文件可见、服务端复制、Range 读取和删除。 5. 测试通过后启用 OpenList,再进入“抖音授权”配置收藏、喜欢、关注、合集和短剧路径。这些字段都是目标基础目录之后的相对路径;留空保存时会按账号生成默认值。 注意事项: - OpenList 账号需要源挂载目录的读取权限,以及目标基础目录的读取、写入、移动、重命名和删除权限。 - 新写入不会调用 `/api/fs/put` 或 WebDAV。服务端复制完成并确认最终文件长度后,本地中转副本才会清理;失败任务会持久化并按退避规则恢复。 - 切换存储模式只影响之后的新同步内容,不会自动移动或删除历史文件。历史 WebDAV 驱动仅用于旧记录继续播放、删除和回滚。 - OpenList 密码使用 Data Protection 加密。密钥位于数据库目录的 `keys` 子目录,因此 Docker 部署必须持续映射并备份 `/app/db`。 - 图文和动态视频仍会先在本地完成 FFmpeg 合成,再进入同一 OpenList 中转与服务端复制流程。 ### 2.2 升级后将旧视频接管到 OpenList `0.2.25` 支持从官方 `0.2.x` 原地升级,保留数据库、Cookie、配置、Data Protection 密钥及历史媒体路径。系统配置会分别显示本地、历史 WebDAV、OpenList 和“不在当前存储”的记录数量;旧 WebDAV 迁移任务只保留审计信息,可直接归档隐藏。 > 升级 → 配置并测试 OpenList → 启用 OpenList → 迁移预检 → 手动创建任务 → 后台迁移 → 选择回滚或清理旧文件 1. 安装 `0.2.25 x86_64` FPK 覆盖升级。升级不会自动迁移视频,也不会覆盖 fnOS 数据共享目录;启动前会备份 SQLite、WAL/SHM 和 Data Protection 密钥,并只保留最近三份升级备份。 2. 按上一节配置共享中转目录和 OpenList,完成完整复制链路测试后再启用。此后新同步内容直接写入 OpenList,旧记录仍按原存储类型工作。 3. 打开“系统配置 → 存储迁移”执行预检。页面会统计本地记录、历史 WebDAV、可直接接管、需复制或回源、缺失文件、总字节数、无效 Cookie、未配置路径和目标冲突;存在冲突时不会创建任务。 4. 同一 OpenList 实例中可见且长度匹配的历史 WebDAV 文件会直接改标接管,不会重复复制。其余记录优先读取安全范围内的本地文件;本地主媒体缺失时才尝试记录 URL 和抖音全量列表回源。 5. 选择并发数 `1–3`(默认 `1`)并手动创建任务。升级、保存配置和启用 OpenList 都不会自动启动迁移。配置地址、源挂载、基础目录或账号变化时,任务会暂停并要求重新预检。 6. 任务支持暂停、恢复、取消和失败项重试;应用重启后会恢复中断项。单条记录只有在远端最终文件通过长度校验且数据库事务成功后才会改为 OpenList,失败项仍指向原存储。 7. 任务结束后可以整批回滚或清理成功项。清理前会再次检查数据库与远端文件;本地来源只删除不再被引用的旧文件,直接接管的 WebDAV 文件不会被误删。清理开始后不再允许回滚。 8. 已结束且无需继续清理或回滚的迁移历史可在系统配置或任务中心隐藏;归档只影响显示,不删除视频、文件或审计条目。 建议在抽样播放确认无误后再清理旧文件,并始终保留 `/app/db` 与原媒体目录的外部备份。 ### 2.3 媒体来源 403、429 与重新授权 任务中心会把抖音/CDN 来源错误与 OpenList 存储错误分开显示。任务条目只记录安全的来源域名、HTTP 状态和重试时间,不保存或输出带签名的完整媒体 URL、响应正文与 Cookie。 - 下载会优先尝试所选清晰度,再去重轮换其他清晰度地址;403、404 和 410 会立即切换候选地址。 - 同一抖音授权连续 3 个作品的全部候选地址均返回 403 时,只暂停该授权 15 分钟,其他授权继续同步。冷却结束后后台只用最早的等待条目探测一次。 - 探测成功会自动恢复该授权的其余等待条目;探测仍返回 403 或请求直接返回 401 时,任务中心和“抖音授权”页会提示重新授权。 - 保存新的 Cookie 会清除来源锁并安排一次探测。429 会遵循服务端 `Retry-After` 进入冷却,但不会直接判定 Cookie 失效。 - 404/410 只标记当前作品失败,通常表示作品下架、私密或签名地址已失效,不会暂停整个授权,也不会触发存储熔断。 如果任务中心显示“需要重新授权”,请进入“抖音授权”保留原入口并更新 Cookie;无需修改 OpenList 配置,也不要删除已有视频记录或文件。 ### 2.4 关注博主直播监测与邮箱通知 - 在“关注列表”中为每个博主独立开启“直播监测”。开启后会立即检查一次,之后后台每 5 分钟检查;单个博主也可手动刷新,30 秒内重复点击不会再次请求抖音。 - 页面每分钟读取一次本地状态,不会因此额外请求抖音。直播中可直接进入直播间;检查失败时保留上次成功状态并显示失败或过期提示。 - 同一授权账号下的博主串行检查并加入随机间隔;遇到 403、429 或验证响应时按账号进入 15–360 分钟递增冷却,避免持续请求扩大风控影响。 - 在“系统配置 → 邮箱通知”配置 SMTP 地址、端口、安全方式、账号、授权码、发件人和收件人。支持无加密、STARTTLS 和 SSL/TLS,建议优先使用邮箱服务商提供的授权码并先发送测试邮件。 - SMTP 密码使用 Data Protection 加密保存,不会通过读取配置接口返回。密码留空保存表示继续使用原密码;可填写多个收件人,使用逗号、分号或换行分隔。 - 全局邮箱启用并配置完整后,可在每个博主卡片上独立开启“开播邮件”。同一 `web_rid` 或直播房间只通知一次,邮件失败不会覆盖已获取的直播状态,15 分钟后才会重试;检测到下播后才会为下一场直播重新准备通知。 ### 2.5 OpenList 自动化与真实服务测试 本地自动化测试覆盖 OpenList Token 缓存与 401 刷新、Unicode 路径、服务端复制、Range 读取、重启恢复、数据库升级,以及历史 WebDAV 兼容行为: ```bash dotnet test tests/dy.net.Tests/dy.net.Tests.csproj ``` AList 和 OpenList 的历史 WebDAV 兼容实测默认跳过;需要验证旧记录读取与删除时,可分别设置以下环境变量: | AList | OpenList | 说明 | |---|---|---| | `DYSYNC_TEST_ALIST_ENDPOINT` | `DYSYNC_TEST_OPENLIST_ENDPOINT` | WebDAV 地址,例如 `https://host/dav` | | `DYSYNC_TEST_ALIST_BASE_PATH` | `DYSYNC_TEST_OPENLIST_BASE_PATH` | 专用测试目录,必须是包含 `dysync-test` 的非根路径 | | `DYSYNC_TEST_ALIST_USERNAME` | `DYSYNC_TEST_OPENLIST_USERNAME` | 测试账号用户名 | | `DYSYNC_TEST_ALIST_PASSWORD` | `DYSYNC_TEST_OPENLIST_PASSWORD` | 测试账号密码 | | `DYSYNC_TEST_ALIST_ALLOW_INVALID_CERTIFICATE` | `DYSYNC_TEST_OPENLIST_ALLOW_INVALID_CERTIFICATE` | 可选,仅可信内网自签证书设置为 `true` | 历史兼容测试只会在指定基础目录下创建随机子目录,验证完成后自动删除;不会读取网站中保存的生产配置,也不会输出密码。OpenList 原生写入还依赖应用与 OpenList 共享同一物理中转目录,因此请直接使用“系统配置 → 媒体存储 → 测试完整复制链路”完成部署环境实测。 --- ## 3. 默认账号密码(首次登录用) 首次访问后台管理页面时,使用以下默认账号密码: - **用户名**:`douyin` - **密码**:`douyin2026` > ⚠️ **安全建议**:登录后修改密码。 --- ## 4. 运行方式(推荐 Docker Compose) ### 镜像版本 | 镜像标签 | 架构 | | ----------------- | -------------- | | `beta_2.2.0` | x86_64 (amd64) | | `arm_2.2.0` | ARM64 | | `latest` | x86_64 (amd64) | ### 构建命令示例 将下方命令中的「本地路径」替换为你的实际路径,终端执行即可: ### 方式一:Docker Compose 运行(推荐) 创建 docker-compose.yml 文件,复制以下内容,替换「本地路径」后执行 docker-compose up -d: 需要注意:unraid玩家需要增加 user配置 --user 1000:100 ```yaml services: dysync: image: ccr.ccs.tencentyun.com/jianzhichu/dysync:beta_2.2.0 container_name: dysync2026 # 容器名称 restart: unless-stopped # 始终重启容器,除非容器被手动停止或Docker服务停止 ports: - "10101:10101" volumes: # 基础路径映射 - /vol2/1000/media/dysync/db:/app/db # 数据库目录(持久化配置和同步记录) # 默认音频目录(用于图文/动态视频合成,版权受限音频的替代) - /vol2/1000/media/dysync/mp3:/app/mp3 # 账号1 - 视频存储目录 - /vol2/1000/media/dysync/dy1/coll:/app/collect # 个人收藏视频 - /vol2/1000/media/dysync/dy1/fav:/app/favorite # 个人喜欢视频 - /vol2/1000/media/dysync/dy1/up:/app/uper # 指定博主视频 - /vol2/1000/media/dysync/dy1/mix:/app/mix # 合集(不需要可删除) - /vol2/1000/media/dysync/dy1/series:/app/series # 短剧(不需要可删除) # 账号2 - 多账号路径映射示例(可选:授权时可复用账号1路径) - /vol2/1000/media/dysync/dy2/collect:/app/collect2 - /vol2/1000/media/dysync/dy2/fav:/app/favorite2 - /vol2/1000/media/dysync/dy2/up:/app/uper2 network_mode: bridge dns: - 223.5.5.5 # 阿里云DNS(备用) - 114.114.114.114 # 国内114 DNS(提升国内访问稳定性) deploy: resources: limits: memory: 250m # 限制内存占用≤250MB(图文视频下载场景不建议设置) ``` 另一个版本去掉了所有视频存储路径设置项,docker只需要映射3个路径就可以,但是!!! 不兼容老的版本,如果觉得这种方式好一些可以重新部署。其他没什么变化。 所有路径都变成 根目录/cookie名字/视频类型/(如果是合集或者短剧这里还有一层)/合集或短剧/名称/视频文件 ``` services: dysync: image: ccr.ccs.tencentyun.com/jianzhichu/dysync:latest container_name: dysync_latest # 容器自定义名称 restart: unless-stopped # 容器非手动停止则自动重启 ports: - "10110:10101" # 端口映射 environment: # 限制GC堆最大内存为100MB(100*1024*1024=104857600,可根据需求调整) - COMPlus_GCHeapHardLimit=154857600 # 禁用服务器GC,改用工作站GC(轻量应用更友好) - COMPlus_GCServer=0 # 可选:强制GC回收后释放内存给操作系统(Linux专属) - COMPlus_GCConserveMemory=1 # 可选:显示GC日志(排查内存问题时用) # - COMPlus_GCLogFile=/app/gc.log volumes: # 基础路径映射 - 主账号(账号1) - /vol2/1000/media/dy001/db:/app/db # 数据库目录(持久化配置和同步记录) - /vol2/1000/media/dy001/mp3:/app/mp3 # 备用音频目录(版权音频无法下载时使用) - /vol2/1000/media/dy001/:/app/data # 视频存储目录 network_mode: bridge dns: - 223.5.5.5 # 阿里云DNS(备用) - 114.114.114.114 # 国内114 DNS(提升国内访问稳定性) deploy: resources: limits: memory: 211m # 限制内存占用≤250MB(图文视频下载场景不建议设置) ``` ## 🚀 5. 软件截图        
|
|
### 🎁 其他支持方式
- 分享给更多需要的朋友
- 提交 Bug 报告和功能建议
- 贡献代码和文档
---
感谢你的支持!❤️
# 免责声明 本项目(dysync.net)仅作为技术研究与学习交流的开源项目,其所有代码、功能及相关内容均不代表任何第三方平台的官方服务或立场。使用本项目前,请仔细阅读以下条款: ## 1. 授权与使用限制 - 本项目未获得抖音(Douyin)等任何第三方平台的官方授权、合作或认可,与该等平台无任何关联。 - 项目功能仅允许用于个人技术研究和学习目的,严禁用于商业用途、非法活动或违反任何第三方平台规则的行为。 ## 2. 知识产权说明 - 项目中涉及的第三方平台(如抖音)的名称、商标、接口、内容等均为其各自所有者的知识产权。 - 本项目仅对技术实现方式进行研究,不涉及对第三方知识产权的侵占或滥用。如因使用本项目引发知识产权争议,相关责任由使用者自行承担。 ## 3. 风险提示与责任豁免 - 使用本项目可能导致违反第三方平台的用户协议或相关规定,进而导致账号限制、功能封禁等风险,此类风险由使用者自行承担。 - 项目开发者不对使用本项目产生的任何直接或间接损失(包括但不限于数据丢失、设备损坏、账号问题等)承担责任。 - 使用者应确保自身行为符合《网络安全法》《著作权法》等相关法律法规,不得利用本项目从事侵权、违法或违背公序良俗的活动。 ## 4. 声明的修改与生效 - 本免责声明的最终解释权归项目开发者所有,开发者保留随时修改本声明的权利。 - 修改后的声明将在项目仓库中更新,建议使用者定期查阅。 - 一旦使用本项目的代码、功能或相关资源,即视为您已充分理解并同意本免责声明的全部条款。如不同意,请立即停止使用。