Skip to content

Commit

Permalink
fix: interactive_video
Browse files Browse the repository at this point in the history
BREAKING CHANGE: 重构 ivi 文件架构,抹除错误的剧情树架构
  • Loading branch information
Nemo2011 committed Aug 29, 2024
1 parent 19524c3 commit afbbc41
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 149 deletions.
138 changes: 25 additions & 113 deletions bilibili_api/interactive_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ async def get_jumping_type(self) -> int:
"""
获取子节点跳转方式 (参考 InteractiveNodeJumpingType)
"""
edge_info = await self.__parent.get_edge_info(self.__id)
edge_info = await self.__get_cached_edge_info()
return edge_info["edges"]["questions"][0]["type"]

def get_node_id(self) -> int:
Expand Down Expand Up @@ -846,11 +846,6 @@ def createEdge(edge_id: int):
edges_info[edge_id] = {
"title": None,
"cid": None,
"button": None,
"condition": None,
"jump_type": None,
"is_default": None,
"command": None,
"sub": [],
}

Expand All @@ -876,18 +871,9 @@ def var2dict(var: InteractiveVariable):
if n.get_node_id() not in edges_info:
createEdge(n.get_node_id())
edges_info[n.get_node_id()]["cid"] = n.get_cid()
edges_info[n.get_node_id()]["button"] = {
"text": n.get_self_button().get_text(),
"align": n.get_self_button().get_align(),
"pos": (n.get_self_button().get_pos()),
}
edges_info[n.get_node_id()]["vars"] = [
var2dict(var) for var in (await n.get_vars())
]
edges_info[n.get_node_id()]["condition"] = n.get_jumping_condition()._InteractiveJumpingCondition__command # type: ignore
edges_info[n.get_node_id()]["jump_type"] = 0
edges_info[n.get_node_id()]["is_default"] = True
edges_info[n.get_node_id()]["command"] = n._InteractiveNode__command._InteractiveJumpingCommand__command # type: ignore

while queue:
# 出队
Expand Down Expand Up @@ -939,31 +925,19 @@ def var2dict(var: InteractiveVariable):
if n.get_node_id() not in edges_info:
createEdge(n.get_node_id())
edges_info[n.get_node_id()]["cid"] = n.get_cid()
edges_info[n.get_node_id()]["button"] = {
"text": n.get_self_button().get_text(),
"align": n.get_self_button().get_align(),
"pos": n.get_self_button().get_pos(),
}

def var2dict(var: InteractiveVariable):
return {
"name": var.get_name(),
"id": var.get_id(),
"value": var.get_value(),
"show": var.is_show(),
"random": var.is_random(),
edges_info[now_node.get_node_id()]["sub"].append(
{
"id": n.get_node_id(),
"text": n.get_self_button().get_text(),
"align": n.get_self_button().get_align(),
"pos": n.get_self_button().get_pos(),
"condition": n.get_jumping_condition()._InteractiveJumpingCondition__command, # type: ignore
"jump_type": await now_node.get_jumping_type(),
"is_default": n.is_default(),
"command": n._InteractiveNode__command._InteractiveJumpingCommand__command, # type: ignore
}

edges_info[n.get_node_id()]["condition"] = n.get_jumping_condition()._InteractiveJumpingCondition__command # type: ignore
edges_info[n.get_node_id()][
"jump_type"
] = await now_node.get_jumping_type()
edges_info[n.get_node_id()]["is_default"] = n.is_default()
edges_info[n.get_node_id()]["command"] = n._InteractiveNode__command._InteractiveJumpingCommand__command # type: ignore
edges_info[now_node.get_node_id()]["sub"] = [
n.get_node_id() for n in subs
]
# 所有可达顶点 ID 入队
)
# # 所有可达顶点 ID 入队
queue.insert(0, n)

json.dump(
Expand Down Expand Up @@ -1060,18 +1034,6 @@ def var2dict(var: InteractiveVariable):
if n.get_node_id() not in edges_info:
createEdge(n.get_node_id())
edges_info[n.get_node_id()]["cid"] = n.get_cid()
edges_info[n.get_node_id()]["button"] = {
"text": n.get_self_button().get_text(),
"align": n.get_self_button().get_align(),
"pos": (n.get_self_button().get_pos()),
}
edges_info[n.get_node_id()]["vars"] = [
var2dict(var) for var in (await n.get_vars())
]
edges_info[n.get_node_id()]["condition"] = n.get_jumping_condition()._InteractiveJumpingCondition__command # type: ignore
edges_info[n.get_node_id()]["jump_type"] = 0
edges_info[n.get_node_id()]["is_default"] = True
edges_info[n.get_node_id()]["command"] = n._InteractiveNode__command._InteractiveJumpingCommand__command # type: ignore

while queue:
# 出队
Expand Down Expand Up @@ -1119,30 +1081,6 @@ def var2dict(var: InteractiveVariable):
if n.get_node_id() not in edges_info:
createEdge(n.get_node_id())
edges_info[n.get_node_id()]["cid"] = n.get_cid()
edges_info[n.get_node_id()]["button"] = {
"text": n.get_self_button().get_text(),
"align": n.get_self_button().get_align(),
"pos": n.get_self_button().get_pos(),
}

def var2dict(var: InteractiveVariable):
return {
"name": var.get_name(),
"id": var.get_id(),
"value": var.get_value(),
"show": var.is_show(),
"random": var.is_random(),
}

edges_info[n.get_node_id()]["condition"] = n.get_jumping_condition()._InteractiveJumpingCondition__command # type: ignore
edges_info[n.get_node_id()][
"jump_type"
] = await now_node.get_jumping_type()
edges_info[n.get_node_id()]["is_default"] = n.is_default()
edges_info[n.get_node_id()]["command"] = n._InteractiveNode__command._InteractiveJumpingCommand__command # type: ignore
edges_info[now_node.get_node_id()]["sub"] = [
n.get_node_id() for n in subs
]
# 所有可达顶点 ID 入队
queue.insert(0, n)

Expand Down Expand Up @@ -1288,11 +1226,6 @@ def createEdge(edge_id: int):
edges_info[edge_id] = {
"title": None,
"cid": None,
"button": None,
"condition": None,
"jump_type": None,
"is_default": None,
"command": None,
"sub": [],
}

Expand All @@ -1318,18 +1251,9 @@ def var2dict(var: InteractiveVariable):
if n.get_node_id() not in edges_info:
createEdge(n.get_node_id())
edges_info[n.get_node_id()]["cid"] = n.get_cid()
edges_info[n.get_node_id()]["button"] = {
"text": n.get_self_button().get_text(),
"align": n.get_self_button().get_align(),
"pos": (n.get_self_button().get_pos()),
}
edges_info[n.get_node_id()]["vars"] = [
var2dict(var) for var in (await n.get_vars())
]
edges_info[n.get_node_id()]["condition"] = n.get_jumping_condition()._InteractiveJumpingCondition__command # type: ignore
edges_info[n.get_node_id()]["jump_type"] = 0
edges_info[n.get_node_id()]["is_default"] = True
edges_info[n.get_node_id()]["command"] = n._InteractiveNode__command._InteractiveJumpingCommand__command # type: ignore

while queue:
# 出队
Expand Down Expand Up @@ -1377,31 +1301,19 @@ def var2dict(var: InteractiveVariable):
if n.get_node_id() not in edges_info:
createEdge(n.get_node_id())
edges_info[n.get_node_id()]["cid"] = n.get_cid()
edges_info[n.get_node_id()]["button"] = {
"text": n.get_self_button().get_text(),
"align": n.get_self_button().get_align(),
"pos": n.get_self_button().get_pos(),
}

def var2dict(var: InteractiveVariable):
return {
"name": var.get_name(),
"id": var.get_id(),
"value": var.get_value(),
"show": var.is_show(),
"random": var.is_random(),
edges_info[now_node.get_node_id()]["sub"].append(
{
"id": n.get_node_id(),
"text": n.get_self_button().get_text(),
"align": n.get_self_button().get_align(),
"pos": n.get_self_button().get_pos(),
"condition": n.get_jumping_condition()._InteractiveJumpingCondition__command, # type: ignore
"jump_type": await now_node.get_jumping_type(),
"is_default": n.is_default(),
"command": n._InteractiveNode__command._InteractiveJumpingCommand__command, # type: ignore
}

edges_info[n.get_node_id()]["condition"] = n.get_jumping_condition()._InteractiveJumpingCondition__command # type: ignore
edges_info[n.get_node_id()][
"jump_type"
] = await now_node.get_jumping_type()
edges_info[n.get_node_id()]["is_default"] = n.is_default()
edges_info[n.get_node_id()]["command"] = n._InteractiveNode__command._InteractiveJumpingCommand__command # type: ignore
edges_info[now_node.get_node_id()]["sub"] = [
n.get_node_id() for n in subs
]
# 所有可达顶点 ID 入队
)
# # 所有可达顶点 ID 入队
queue.insert(0, n)

json.dump(
Expand Down
48 changes: 21 additions & 27 deletions bilibili_api/tools/ivitools/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,17 +390,17 @@ def timerEvent(*args, **kwargs):
else:
# 跳转类型
if (
self.graph[str(children[0])]["jump_type"]
self.graph[str(self.current_node)]["sub"][0]["jump_type"]
== InteractiveNodeJumpingType.DEFAULT.value
):
# 直接跳转
for node_id in children:
for node in children:
btn = Button(
node_id,
node["id"],
[0, 0],
"",
self.graph[str(node_id)]["condition"],
self.graph[str(node_id)]["command"],
node["condition"],
node["command"],
)
condition = InteractiveJumpingCondition(
self.variables, btn.condition
Expand All @@ -415,36 +415,31 @@ def timerEvent(*args, **kwargs):
self.set_source(self.graph[str(btn_id)]["cid"])
self.current_node = btn.node_id
self.volume_change_event()
title = self.graph[str(node_id)]["title"]
title = self.graph[str(btn_id)]["title"]
self.node.setText(f"(当前节点: {title})")
break
else:
# 进行选择
def get_info(node_id: int):
return self.graph[str(node_id)]

cnt = 0
for idx, child in enumerate(children):
pos_x = cnt * 200
pos_y = 600
cur_info = get_info(child)
# 生成 Button 对象
self.choice_buttons.append(
Button(
child,
child["id"],
[pos_x, pos_y],
cur_info["button"]["text"],
cur_info["condition"],
cur_info["command"],
child["text"],
child["condition"],
child["command"],
)
)
# 生成 ButtonLabel 对象
if cur_info["button"]["pos"][0] == None:
if child["pos"][0] == None:
if idx != 0:
previous_info = get_info(children[idx - 1])
previous_info = children[idx - 1]
curtext, previoustext = (
cur_info["button"]["text"],
previous_info["button"]["text"],
child["text"],
previous_info["text"],
)
if curtext[2:] == previoustext[2:]:
# 可确定与上一个按钮同一个位置(即概率按钮)
Expand All @@ -454,16 +449,16 @@ def get_info(node_id: int):
cnt += 1
lbl = ButtonLabel(self.win)
lbl.prep_text(
cur_info["button"]["text"], pos_x, pos_y
child["text"], pos_x, pos_y
)
lbl.show()
self.choice_labels.append(lbl)
continue
if idx != 0:
previous_info = get_info(children[idx - 1])
previous_info = children[idx - 1]
curpos, previouspos = (
cur_info["button"]["pos"],
previous_info["button"]["pos"],
child["pos"],
previous_info["pos"],
)
if (abs(curpos[0] - previouspos[0]) <= 5) and (
abs(curpos[1] - previouspos[1]) <= 5
Expand All @@ -476,7 +471,7 @@ def get_info(node_id: int):
cnt += 1
lbl = ButtonLabel(self.win)
lbl.prep_text(
cur_info["button"]["text"], pos_x, pos_y
child["text"], pos_x, pos_y
)
lbl.show()
self.choice_labels.append(lbl)
Expand All @@ -485,7 +480,7 @@ def get_info(node_id: int):
cnt += 1
lbl = ButtonLabel(self.win)
lbl.prep_text(
cur_info["button"]["text"], pos_x, pos_y
child["text"], pos_x, pos_y
)
lbl.show()
self.choice_labels.append(lbl)
Expand All @@ -510,8 +505,7 @@ def get_info(node_id: int):
self.label.setText("--:--/--:--")
return
if (
(self.mediaplayer.duration() // 1000)
== ((self.mediaplayer.position() // 1000))
abs(self.mediaplayer.duration() - self.mediaplayer.position()) <= 500
) and (not self.has_end):
self.has_end = True
self.mediaplayer.pause()
Expand Down
18 changes: 9 additions & 9 deletions docs/ivifile.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,28 @@
- test_ivi
- bilivideo.json
- ivideo.json
- xxxxx.mp4
- xxxxx.video.mp4
- xxxxx.audio.mp4

**提示:所有除二进制文件以外的文件请采用 `utf-8` 编码或是 `ascii` 编码打开/保存,请不要用 `gbk` 编码。建议使用 `ascii` 编码**

其中,`bilivideo.json` 存放了视频的基本信息(`BVID` 和视频标题)。而 `ivideo.json` 则是剧情树。还有许多的 `mp4` 文件,这些都对应了一个个的节点,举个例子,`123.mp4``cid``123` 的节点对应的视频。节点的 `cid` 可以在 `ivideo.json` 中找到。

`ivideo.json` 存放的是一个字典,字典的 `key` 对应了节点的 `id`,而内容则是节点的信息。无论哪个视频,初始的节点的 `id` 永远都是 `1`。以下为一个节点的信息的详解:
`ivideo.json` 存放的是一个字典,字典的 `key` 对应了节点的 `id`,而内容则是节点的信息。初始的节点的 `id` `bilivideo.json` 中的 `root_id`。以下为一个节点的信息的详解:

- "1" (str: 节点 ID 转为字符串的结果)
- "114514" (str: 节点 ID 转为字符串的结果)
- `title` (str: 标题)
- `cid` (int: CID)
- `button` (dict: 跳转对应按钮的信息)
- `sub` (list: 子节点列表)
- `text` (str: 按钮文字)
- `align` (int: 按钮文字相对于定位的位置,有上左下右中五种,可以参考 `interactive_video.InteractiveButtonAlign`,里面有详细注释)
- `pos` (list: 按钮位置信息 (如果所有按钮都照正常布局,那么此数据的值为 `[null, null]`))
- `0`: X 坐标
- `1`: Y 坐标
- `condition` (str: 节点跳转必须符合的表达式,默认为 `""`。为 `javascript` 语言。主要作用为实现随机跳转。)
- `jump_type` (int: 跳转方式,有直接跳转和选择跳转两种,可查看 `interactive_video.InteractiveJumpingType`)
- `is_default` (bool: 是否为默认节点,如果是直接跳转则会跳转至默认节点,或者是定时选择后直接跳转至默认节点(定时选择后直接跳转目前不支持))
- `command` (str: 跳转成功后需要对变量做的操作。为 `javascript` 语言。)
- `sub` (list: 子节点列表)
- `condition` (str: 节点跳转必须符合的表达式,默认为 `""`。为 `javascript` 语言。主要作用为实现随机跳转。)
- `jump_type` (int: 跳转方式,有直接跳转和选择跳转两种,可查看 `interactive_video.InteractiveJumpingType`)
- `is_default` (bool: 是否为默认节点,如果是直接跳转则会跳转至默认节点,或者是定时选择后直接跳转至默认节点(定时选择后直接跳转目前不支持))
- `command` (str: 跳转成功后需要对变量做的操作。为 `javascript` 语言。)
- `vars` (list: 初始化时的变量设置)
- `每一项` (dict)
- `name` (str: 变量名)
Expand Down

0 comments on commit afbbc41

Please sign in to comment.