Skip to content

Commit

Permalink
Feature: 支持交互/互动视频下载 (#913)
Browse files Browse the repository at this point in the history
* feat: Support interactive video

* fix: fixed xml parsing failure caused by multiple root tags

* fix: fixed Json parsing type errors and add compatibility with multiple problem interactions

* fix: Unknown video duration should be 0

* fix: If it is interactive video and used tv api, then remove tv api flag
  • Loading branch information
LyceumHewun authored Aug 2, 2024
1 parent 9c876ab commit 73f9035
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 3 deletions.
5 changes: 5 additions & 0 deletions BBDown.Core/Entity/VInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,10 @@ public class VInfo
/// 视频分P信息
/// </summary>
public required List<Page> PagesInfo { get; set; }

/// <summary>
/// 是否为互动视频
/// </summary>
public bool IsSteinGate { get; set; }
}
}
61 changes: 58 additions & 3 deletions BBDown.Core/Fetcher/NormalInfoFetcher.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using BBDown.Core.Entity;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Xml;
using static BBDown.Core.Entity.Entity;
using static BBDown.Core.Util.HTTPUtil;

Expand All @@ -22,9 +23,15 @@ public async Task<VInfo> FetchAsync(string id)
string ownerName = owner.GetProperty("name").ToString();
long pubTime = data.GetProperty("pubdate").GetInt64();
bool bangumi = false;
var bvid = data.GetProperty("bvid").ToString();
var cid = data.GetProperty("cid").GetInt64();

var pages = data.GetProperty("pages").EnumerateArray().ToList();
// 互动视频 1:是 0:否
var isSteinGate = data.GetProperty("rights").GetProperty("is_stein_gate").GetInt16();

// 分p信息
List<Page> pagesInfo = new();
var pages = data.GetProperty("pages").EnumerateArray().ToList();
foreach (var page in pages)
{
Page p = new(page.GetProperty("page").GetInt32(),
Expand All @@ -39,10 +46,57 @@ public async Task<VInfo> FetchAsync(string id)
"",
ownerName,
ownerMid
);
);
pagesInfo.Add(p);
}

if (isSteinGate == 1) // 互动视频获取分P信息
{
var playerSoApi = $"https://api.bilibili.com/x/player.so?bvid={bvid}&id=cid:{cid}";
var playerSoText = await GetWebSourceAsync(playerSoApi);
var playerSoXml = new XmlDocument();
playerSoXml.LoadXml($"<root>{playerSoText}</root>");

var interactionNode = playerSoXml.SelectSingleNode("//interaction");

if (interactionNode is { InnerText.Length: > 0 })
{
var graphVersion = JsonDocument.Parse(interactionNode.InnerText).RootElement
.GetProperty("graph_version").GetInt64();
var edgeInfoApi = $"https://api.bilibili.com/x/stein/edgeinfo_v2?graph_version={graphVersion}&bvid={bvid}";
var edgeInfoJson = await GetWebSourceAsync(edgeInfoApi);
var edgeInfoData = JsonDocument.Parse(edgeInfoJson).RootElement.GetProperty("data");
var questions = edgeInfoData.GetProperty("edges").GetProperty("questions").EnumerateArray()
.ToList();
var index = 2; // 互动视频分P索引从2开始
foreach (var question in questions)
{
var choices = question.GetProperty("choices").EnumerateArray().ToList();
foreach (var page in choices)
{
Page p = new(index++,
id,
page.GetProperty("cid").ToString(),
"", //epid
page.GetProperty("option").ToString().Trim(),
0,
"",
pubTime, //分p视频没有发布时间
"",
"",
ownerName,
ownerMid
);
pagesInfo.Add(p);
}
}
}
else
{
throw new Exception("互动视频获取分P信息失败");
}
}

try
{
if (data.GetProperty("redirect_url").ToString().Contains("bangumi"))
Expand All @@ -65,7 +119,8 @@ public async Task<VInfo> FetchAsync(string id)
Pic = pic,
PubTime = pubTime,
PagesInfo = pagesInfo,
IsBangumi = bangumi
IsBangumi = bangumi,
IsSteinGate = isSteinGate == 1
};

return info;
Expand Down
6 changes: 6 additions & 0 deletions BBDown/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,12 @@ public static (Dictionary<string, byte> encodingPriority, Dictionary<string, int
{
Log($"UP主页: https://space.bilibili.com/{mid}");
}

if (vInfo.IsSteinGate && myOption.UseTvApi)
{
Log("视频为互动视频,暂时不支持tv下载,修改为默认下载");
myOption.UseTvApi = false;
}
string apiType = myOption.UseTvApi ? "TV" : (myOption.UseAppApi ? "APP" : (myOption.UseIntlApi ? "INTL" : "WEB"));

//打印分P信息
Expand Down

0 comments on commit 73f9035

Please sign in to comment.