Skip to content

Commit

Permalink
docs: 差不多了
Browse files Browse the repository at this point in the history
  • Loading branch information
amtoaer committed Jul 21, 2024
1 parent 177172e commit d63bd43
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 8 deletions.
Binary file added docs/assets/multi_page.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/multi_page_detail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/single_page.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 41 additions & 8 deletions docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

在了解程序工作原理之前,我们需要先对 b 站视频的组织结构有一个大概的了解。简单来说:

- 收藏夹、稍后再看、视频合集、视频列表等结构都是由一系列视频构成的一个列表
- 收藏夹、稍后再看、视频合集、视频列表等结构都是由一系列视频构成的列表
- 每个视频都有唯一的 bvid,包含了封面、描述和标签信息,并包含了一个或多个分页;
- 每个分页都有一个唯一的 cid,包含了封面、视频、音频、弹幕。

Expand All @@ -27,16 +27,38 @@

这说明它们是处于两个不同层级的结构,因此程序对其的处理方式也有着相当大的不同。

## 与 EMBY 媒体库的对应关系

EMBY 的一般结构是: `媒体库 - 文件夹 - 电影/电视剧 - 分季/分集`,方便起见,我采用了如下的对应关系:

1. **文件夹**:对应 b 站的 video list;
2. **电视剧**: 对应 b 站的 video;
3. **第一季的所有分集**:对应 b 站的 page。

特别的,当 video 仅有一个 page 时,为了避免过多的层级,bili-sync 会将 page 展开到第二层级,变成与电视剧同级的电影。

因此,**需要将媒体库类型设置为“混合内容”以支持在同个媒体库中同时显示电视剧与电影**

### 单 page 的 video

![single_page](./assets/single_page.png)

### 多 page 的 video

![multi_page](./assets/multi_page.png)

![multi_page_detail](./assets/multi_page_detail.png)

## 数据库设计

> [!NOTE]
> 可以[前往此处](https://github.com/amtoaer/bili-sync/tree/main/crates/bili_sync_entity/src/entities)实时查看当前版本的数据库表结构。
既然拥有着明显的层级关系,那数据库表实际上是非常好设计的。为了简化实现,程序没有额外考虑单个 video 被多个 video list 引用的情况(如一个视频同时在收藏夹和稍后再看中)。而是简单的将其设计为了不交叉的层级结构。
既然拥有着明显的层级关系,那数据库表就很容易设计了。为了简化实现,程序没有额外考虑单个 video 被多个 video list 引用的情况(如一个视频同时在收藏夹和稍后再看中)。而是简单的将其设计为了不交叉的层级结构。

### video list 表

从上面的介绍可以看出,video list 并不是一个特定的结构,而是一个抽象的概念。我选择将其特化实现为多张表:
从上面的介绍可以看出,video list 并不是一个具体的结构,而是拥有多种实现的抽象概念。我选择将其特化实现为多张表:

1. favorite:收藏夹;
2. watch_later:稍后再看;
Expand All @@ -47,7 +69,7 @@

video 表包含了 video 的基本信息,如 bvid、标题、封面、描述、标签等。此外,video 表还包含了与 video list 的关联。

具体来说,每一种 video list 都在 video 表中有一个对应的列,指向 video list 表中的 id,如 favorite_id、collection_id 等。接下来将这些键与 video 的 bvid 绑在一起建立唯一索引,就可以保证 video list 中不会有重复的 video。
具体来说,每一种 video list 都在 video 表中有一个对应的列,指向 video list 表中的 id,如 favorite_id、collection_id 等。接下来将这些键与 video 的 bvid 绑在一起建立唯一索引,就可以保证在同一个 video list 中不会有重复的 video。

### page 表

Expand All @@ -64,14 +86,25 @@ page 表包含了 page 的基本信息,如 cid、标题、封面等。与 vide
> [!WARNING]
> b 站实现接口时为了节省资源,通过 video list 获取到的 video 列表通常是分页且不包含详细信息的。
程序会扫描所有配置文件中包含的 video list,获取其中包含的 video 的简单信息并填充到数据库。在实现时需要避免频繁的全量扫描以降低请求次数
程序会扫描所有配置文件中包含的 video list,获取其中包含的 video 的简单信息并填充到数据库。在实现时需要避免频繁的全量扫描

程序会使用视频的 bvid 与 time 字段来检验视频是否已经存在于数据库中。实际拉取时会逐页请求,发现 bvid 与 time 均相同的记录会认为已经到达扫描过的位置,停止拉取。
具体到 bili-sync 的实现中,程序在请求接口时会设置按时间顺序排序的参数,确保新发布的视频位于前面。拉取过程会逐页请求,使用视频的 bvid 与 time 字段来检验视频是否已经存在于数据库中。一旦发现 bvid 与 time 均相同的记录则认为已经到达扫描过的位置,停止拉取。

### 填充 video 详情

将新增视频的简单信息写入数据库后,下一步会填充 video 详情。
将新增视频的简单信息写入数据库后,下一步会填充 video 详情。正如上文所述:**通过 video list 获取到的 video 列表通常是不包含详细信息的**,因此需要额外的请求来填充这些信息。

具体来说,这一部会筛选出所有未完全填充信息的 video,逐个对详细信息(如标签、完整分页这种不会包含在列表中的信息)做请求并填充到数据库中
这一步会筛选出所有未完全填充信息的 video,逐个获取 video 的详细信息(如标签、视频分页等)并填充到数据库中

在这个过程中,如果遇到 -404 错误码则说明视频无法被正常访问,程序会将该视频标记为无效并跳过。


### 下载未处理的视频

经过上面处理后,数据库中已经包含了所有需要的 video 信息,接下来只需要筛选其中“未完全下载”、“成功填充详细信息”的所有视频,并发下载即可。程序在 video 层级最多允许 3 个任务同时下载,page 层级最多允许 2 个任务同时下载。

数据库中的 status 字段用于标记 video 和 page 的下载状态,视频的各个部分(封面、视频、nfo 等)包含在 status 的不同位中。程序会根据 status 的不同位来判断视频的下载状态,以此来决定是否需要下载。

如果某些部分下载失败,status 字段会记录这些部分的失败次数,程序会在下次下载时重试。如果重试次数超过了设定的阈值,那么视频会被标记为下载失败,后续直接忽略。

此处程序对风控做了额外的处理,一般风控发生时接下来的所有请求都会失败,因此程序检测到风控时不会认为是某个视频下载失败,而是直接终止 video list 的全部下载任务,等待下次扫描时重试。

0 comments on commit d63bd43

Please sign in to comment.