Skip to content

Commit

Permalink
增加--download-danmaku-formats选项以控制弹幕下载格式 (#950)
Browse files Browse the repository at this point in the history
* feat: add -ddf,--download-danmaku-format option to keep only xml/ass file

* chore: fix review advice

* chore: fix ident

* chore: fix flags usage

* chore: use enum.ToString()

* Update BBDown/Program.cs

Co-authored-by: nilaoda <[email protected]>

* chore: rename to plural & add desc help info

* chore: manual format

---------

Co-authored-by: nilaoda <[email protected]>
  • Loading branch information
magicdawn and nilaoda authored Nov 11, 2024
1 parent 77de9cc commit 06ae0e5
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 12 deletions.
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

[*]
indent_style = space
indent_size = 4
charset = utf-8
# end_of_line = crlf
# trim_trailing_whitespace = false
# insert_final_newline = false
4 changes: 2 additions & 2 deletions BBDown/BBDownApiServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@ private async Task AddDownloadTaskAsync(MyOption option)
runningTasks.Add(task);
try
{
var (encodingPriority, dfnPriority, firstEncoding, downloadDanmaku, input, savePathFormat, lang, aidOri, delay) = Program.SetUpWork(option);
var (encodingPriority, dfnPriority, firstEncoding, downloadDanmaku, downloadDanmakuFormats, input, savePathFormat, lang, aidOri, delay) = Program.SetUpWork(option);
var (fetchedAid, vInfo, apiType) = await Program.GetVideoInfoAsync(option, aidOri, input);
task.Title = vInfo.Title;
task.Pic = vInfo.Pic;
task.VideoPubTime = vInfo.PubTime;
await Program.DownloadPagesAsync(option, vInfo, encodingPriority, dfnPriority, firstEncoding, downloadDanmaku,
await Program.DownloadPagesAsync(option, vInfo, encodingPriority, dfnPriority, firstEncoding, downloadDanmaku, downloadDanmakuFormats,
input, savePathFormat, lang, fetchedAid, delay, apiType, task);
task.IsSuccessful = true;
}
Expand Down
29 changes: 29 additions & 0 deletions BBDown/BBDownEnums.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Linq;

namespace BBDown;

public enum BBDownDanmakuFormat
{
Xml,
Ass,
}

public static class BBDownDanmakuFormatInfo
{
// 默认
public static BBDownDanmakuFormat[] DefaultFormats = [BBDownDanmakuFormat.Xml, BBDownDanmakuFormat.Ass];
public static string[] DefaultFormatsNames = DefaultFormats.Select(f => f.ToString().ToLower()).ToArray();
// 可选项
public static string[] AllFormatNames = Enum.GetNames(typeof(BBDownDanmakuFormat)).Select(f => f.ToLower()).ToArray();

public static BBDownDanmakuFormat FromFormatName(string formatName)
{
return formatName switch
{
"xml" => BBDownDanmakuFormat.Xml,
"ass" => BBDownDanmakuFormat.Ass,
_ => BBDownDanmakuFormat.Xml,
};
}
}
3 changes: 3 additions & 0 deletions BBDown/CommandLineInvoker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ internal static class CommandLineInvoker
private static readonly Option<bool> SkipCover = new(["--skip-cover"], "跳过封面下载");
private static readonly Option<bool> ForceHttp = new(["--force-http"], "下载音视频时强制使用HTTP协议替换HTTPS(默认开启)");
private static readonly Option<bool> DownloadDanmaku = new(["--download-danmaku", "-dd"], "下载弹幕");
private static readonly Option<string> DownloadDanmakuFormats = new(["--download-danmaku-formats", "-ddf"], $"指定需下载的弹幕格式, 用逗号分隔, 可选 {string.Join('/', BBDownDanmakuFormatInfo.AllFormatNames)}, 默认: \"{string.Join(',', BBDownDanmakuFormatInfo.AllFormatNames)}\"");
private static readonly Option<bool> SkipAi = new(["--skip-ai"], description: "跳过AI字幕下载(默认开启)");
private static readonly Option<bool> VideoAscending = new(["--video-ascending"], "视频升序(最小体积优先)");
private static readonly Option<bool> AudioAscending = new(["--audio-ascending"], "音频升序(最小体积优先)");
Expand Down Expand Up @@ -120,6 +121,7 @@ protected override MyOption GetBoundValue(BindingContext bindingContext)
if (bindingContext.ParseResult.HasOption(SkipCover)) option.SkipCover = bindingContext.ParseResult.GetValueForOption(SkipCover)!;
if (bindingContext.ParseResult.HasOption(ForceHttp)) option.ForceHttp = bindingContext.ParseResult.GetValueForOption(ForceHttp)!;
if (bindingContext.ParseResult.HasOption(DownloadDanmaku)) option.DownloadDanmaku = bindingContext.ParseResult.GetValueForOption(DownloadDanmaku)!;
if (bindingContext.ParseResult.HasOption(DownloadDanmakuFormats)) option.DownloadDanmakuFormats = bindingContext.ParseResult.GetValueForOption(DownloadDanmakuFormats)!;
if (bindingContext.ParseResult.HasOption(SkipAi)) option.SkipAi = bindingContext.ParseResult.GetValueForOption(SkipAi)!;
if (bindingContext.ParseResult.HasOption(VideoAscending)) option.VideoAscending = bindingContext.ParseResult.GetValueForOption(VideoAscending)!;
if (bindingContext.ParseResult.HasOption(AudioAscending)) option.AudioAscending = bindingContext.ParseResult.GetValueForOption(AudioAscending)!;
Expand Down Expand Up @@ -183,6 +185,7 @@ public static RootCommand GetRootCommand(Func<MyOption, Task> action)
SkipCover,
ForceHttp,
DownloadDanmaku,
DownloadDanmakuFormats,
SkipAi,
VideoAscending,
AudioAscending,
Expand Down
1 change: 1 addition & 0 deletions BBDown/MyOption.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ internal class MyOption
public bool SkipCover { get; set; }
public bool ForceHttp { get; set; } = true;
public bool DownloadDanmaku { get; set; } = false;
public string? DownloadDanmakuFormats { get; set; }
public bool SkipAi { get; set; } = true;
public bool VideoAscending { get; set; } = false;
public bool AudioAscending { get; set; } = false;
Expand Down
14 changes: 14 additions & 0 deletions BBDown/Program.Methods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,20 @@ private static Dictionary<string, byte> ParseEncodingPriority(MyOption myOption,
return encodingPriority;
}

private static BBDownDanmakuFormat[] ParseDownloadDanmakuFormats(MyOption myOption)
{
if (string.IsNullOrEmpty(myOption.DownloadDanmakuFormats)) return BBDownDanmakuFormatInfo.DefaultFormats;

var formats = myOption.DownloadDanmakuFormats.Replace("", ",").ToLower().Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
if (formats.Any(format => !BBDownDanmakuFormatInfo.AllFormatNames.Contains(format)))
{
LogError($"包含不支持的下载弹幕格式:{myOption.DownloadDanmakuFormats}");
return BBDownDanmakuFormatInfo.DefaultFormats;
}

return formats.Select(BBDownDanmakuFormatInfo.FromFormatName).ToArray();
}

/// <summary>
/// 解析用户输入的清晰度规格优先级
/// </summary>
Expand Down
34 changes: 24 additions & 10 deletions BBDown/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ private static void StartServer(string? listenUrl)
}

public static (Dictionary<string, byte> encodingPriority, Dictionary<string, int> dfnPriority, string? firstEncoding,
bool downloadDanmaku, string input, string savePathFormat, string lang, string aidOri, int delay)
bool downloadDanmaku, BBDownDanmakuFormat[] downloadDanmakuFormats, string input, string savePathFormat, string lang, string aidOri, int delay)
SetUpWork(MyOption myOption)
{
//处理废弃选项
Expand All @@ -206,6 +206,8 @@ public static (Dictionary<string, byte> encodingPriority, Dictionary<string, int
HTTPUtil.UserAgent = string.IsNullOrEmpty(myOption.UserAgent) ? HTTPUtil.UserAgent : myOption.UserAgent;

bool downloadDanmaku = myOption.DownloadDanmaku || myOption.DanmakuOnly;
BBDownDanmakuFormat[] downloadDanmakuFormats = ParseDownloadDanmakuFormats(myOption);

string input = myOption.Url;
string savePathFormat = myOption.FilePattern;
string lang = myOption.Language;
Expand All @@ -220,7 +222,7 @@ public static (Dictionary<string, byte> encodingPriority, Dictionary<string, int

LogDebug("AppDirectory: {0}", APP_DIR);
LogDebug("运行参数:{0}", JsonSerializer.Serialize(myOption, MyOptionJsonContext.Default.MyOption));
return (encodingPriority, dfnPriority, firstEncoding, downloadDanmaku, input, savePathFormat, lang, aidOri, delay);
return (encodingPriority, dfnPriority, firstEncoding, downloadDanmaku, downloadDanmakuFormats, input, savePathFormat, lang, aidOri, delay);
}

public static async Task<(string fetchedAid, VInfo vInfo, string apiType)> GetVideoInfoAsync(MyOption myOption, string aidOri, string input)
Expand Down Expand Up @@ -320,7 +322,7 @@ public static (Dictionary<string, byte> encodingPriority, Dictionary<string, int
}

public static async Task DownloadPagesAsync(MyOption myOption, VInfo vInfo, Dictionary<string, byte> encodingPriority, Dictionary<string, int> dfnPriority,
string? firstEncoding, bool downloadDanmaku, string input, string savePathFormat, string lang, string aidOri, int delay, string apiType, DownloadTask? relatedTask = null)
string? firstEncoding, bool downloadDanmaku, BBDownDanmakuFormat[] downloadDanmakuFormats, string input, string savePathFormat, string lang, string aidOri, int delay, string apiType, DownloadTask? relatedTask = null)
{
List<Page> pagesInfo = vInfo.PagesInfo;
bool bangumi = vInfo.IsBangumi;
Expand Down Expand Up @@ -365,7 +367,7 @@ public static async Task DownloadPagesAsync(MyOption myOption, VInfo vInfo, Dict
}

await DownloadPageAsync(p, myOption, vInfo, pagesInfo, encodingPriority, dfnPriority, firstEncoding,
downloadDanmaku, input, savePathFormat, lang, aidOri, apiType, relatedTask);
downloadDanmaku, downloadDanmakuFormats, input, savePathFormat, lang, aidOri, apiType, relatedTask);

if (myOption.SaveArchivesToFile)
{
Expand All @@ -377,7 +379,7 @@ await DownloadPageAsync(p, myOption, vInfo, pagesInfo, encodingPriority, dfnPrio
}

private static async Task DownloadPageAsync(Page p, MyOption myOption, VInfo vInfo, List<Page> selectedPagesInfo, Dictionary<string, byte> encodingPriority, Dictionary<string, int> dfnPriority,
string? firstEncoding, bool downloadDanmaku, string input, string savePathFormat, string lang, string aidOri, string apiType, DownloadTask? relatedTask = null)
string? firstEncoding, bool downloadDanmaku, BBDownDanmakuFormat[] downloadDanmakuFormats, string input, string savePathFormat, string lang, string aidOri, string apiType, DownloadTask? relatedTask = null)
{
string desc = string.IsNullOrEmpty(p.desc) ? vInfo.Desc : p.desc;
bool bangumi = vInfo.IsBangumi;
Expand Down Expand Up @@ -555,16 +557,28 @@ private static async Task DownloadPageAsync(Page p, MyOption myOption, VInfo vIn
string danmakuUrl = $"https://comment.bilibili.com/{p.cid}.xml";
await DownloadFile(danmakuUrl, danmakuXmlPath, downloadConfig);
var danmakus = DanmakuUtil.ParseXml(danmakuXmlPath);
if (danmakus != null)
if (danmakus == null)
{
Log("弹幕Xml解析失败, 删除Xml...");
File.Delete(danmakuXmlPath);
}
else if (danmakus.Length == 0)
{
Log("当前视频没有弹幕, 删除Xml...");
File.Delete(danmakuXmlPath);
}
else if (downloadDanmakuFormats.Contains(BBDownDanmakuFormat.Ass))
{
Log("正在保存弹幕Ass文件...");
await DanmakuUtil.SaveAsAssAsync(danmakus, danmakuAssPath);
}
else

// delete xml if possible
if (!downloadDanmakuFormats.Contains(BBDownDanmakuFormat.Xml) && File.Exists(danmakuXmlPath))
{
Log("弹幕Xml解析失败, 删除Xml...");
File.Delete(danmakuXmlPath);
}

if (myOption.DanmakuOnly)
{
if (Directory.Exists(p.aid))
Expand Down Expand Up @@ -785,10 +799,10 @@ private static async Task DoWorkAsync(MyOption myOption)
{
try
{
var (encodingPriority, dfnPriority, firstEncoding, downloadDanmaku,
var (encodingPriority, dfnPriority, firstEncoding, downloadDanmaku, downloadDanmakuFormats,
input, savePathFormat, lang, aidOri, delay) = SetUpWork(myOption);
var (fetchedAid, vInfo, apiType) = await GetVideoInfoAsync(myOption, aidOri, input);
await DownloadPagesAsync(myOption, vInfo, encodingPriority, dfnPriority, firstEncoding, downloadDanmaku,
await DownloadPagesAsync(myOption, vInfo, encodingPriority, dfnPriority, firstEncoding, downloadDanmaku, downloadDanmakuFormats,
input, savePathFormat, lang, fetchedAid, delay, apiType);
}
catch (Exception e)
Expand Down

0 comments on commit 06ae0e5

Please sign in to comment.