FLV: Refactor ProcessingComment

This commit is contained in:
genteure 2022-06-17 17:42:50 +08:00
parent 97154b5716
commit 46cde4896c
17 changed files with 61 additions and 50 deletions

View File

@ -16,6 +16,7 @@ using BililiveRecorder.Core;
using BililiveRecorder.Core.Config; using BililiveRecorder.Core.Config;
using BililiveRecorder.Core.Config.V3; using BililiveRecorder.Core.Config.V3;
using BililiveRecorder.DependencyInjection; using BililiveRecorder.DependencyInjection;
using BililiveRecorder.Flv.Pipeline;
using BililiveRecorder.ToolBox; using BililiveRecorder.ToolBox;
using BililiveRecorder.Web; using BililiveRecorder.Web;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
@ -409,6 +410,7 @@ namespace BililiveRecorder.Cli
.Enrich.FromLogContext() .Enrich.FromLogContext()
.Enrich.WithExceptionDetails() .Enrich.WithExceptionDetails()
.Destructure.AsScalar<IPAddress>() .Destructure.AsScalar<IPAddress>()
.Destructure.AsScalar<ProcessingComment>()
.Destructure.ByTransforming<Flv.Xml.XmlFlvFile.XmlFlvFileMeta>(x => new .Destructure.ByTransforming<Flv.Xml.XmlFlvFile.XmlFlvFileMeta>(x => new
{ {
x.Version, x.Version,

View File

@ -13,8 +13,8 @@ namespace BililiveRecorder.Core.ProcessingRules
private const int FLAG_BEFORE = 1; private const int FLAG_BEFORE = 1;
private const int FLAG_AFTER = 2; private const int FLAG_AFTER = 2;
private static readonly ProcessingComment comment_before = new ProcessingComment(CommentType.Logging, "New file before data by split rule"); private static readonly ProcessingComment comment_before = new ProcessingComment(CommentType.Logging, false, "New file before data by split rule");
private static readonly ProcessingComment comment_after = new ProcessingComment(CommentType.Logging, "New file after data by split rule"); private static readonly ProcessingComment comment_after = new ProcessingComment(CommentType.Logging, false, "New file after data by split rule");
public void Run(FlvProcessingContext context, System.Action next) public void Run(FlvProcessingContext context, System.Action next)
{ {

View File

@ -4,22 +4,28 @@ namespace BililiveRecorder.Flv.Pipeline
{ {
public class ProcessingComment public class ProcessingComment
{ {
public ProcessingComment(CommentType t, string c) public ProcessingComment(CommentType type, bool actionRequired, string comment)
{ {
this.T = t; this.Type = type;
this.C = c ?? throw new ArgumentNullException(nameof(c)); this.ActionRequired = actionRequired;
this.Comment = comment ?? throw new ArgumentNullException(nameof(comment));
} }
/// <summary> /// <summary>
/// Type /// Type
/// </summary> /// </summary>
public CommentType T { get; } public CommentType Type { get; }
/// <summary>
/// Action Required
/// </summary>
public bool ActionRequired { get; }
/// <summary> /// <summary>
/// Comment /// Comment
/// </summary> /// </summary>
public string C { get; } public string Comment { get; }
public override string ToString() => $"{this.T} {this.C}"; public override string ToString() => $"({this.Type},{(this.ActionRequired ? "A" : "C")}): {this.Comment}";
} }
} }

View File

@ -11,8 +11,8 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
/// </summary> /// </summary>
public class HandleDelayedAudioHeaderRule : ISimpleProcessingRule public class HandleDelayedAudioHeaderRule : ISimpleProcessingRule
{ {
private static readonly ProcessingComment comment1 = new ProcessingComment(CommentType.Unrepairable, "音频数据出现在音频头之前"); private static readonly ProcessingComment comment1 = new ProcessingComment(CommentType.Unrepairable, true, "音频数据出现在音频头之前");
private static readonly ProcessingComment comment2 = new ProcessingComment(CommentType.DecodingHeader, "检测到延后收到的音频头"); private static readonly ProcessingComment comment2 = new ProcessingComment(CommentType.DecodingHeader, true, "检测到延后收到的音频头");
public void Run(FlvProcessingContext context, Action next) public void Run(FlvProcessingContext context, Action next)
{ {

View File

@ -9,7 +9,7 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
/// </summary> /// </summary>
public class HandleEndTagRule : ISimpleProcessingRule public class HandleEndTagRule : ISimpleProcessingRule
{ {
private static readonly ProcessingComment comment = new ProcessingComment(CommentType.Logging, "因收到 End Tag 分段"); private static readonly ProcessingComment comment = new ProcessingComment(CommentType.Logging, false, "因收到 End Tag 分段");
public void Run(FlvProcessingContext context, Action next) public void Run(FlvProcessingContext context, Action next)
{ {

View File

@ -15,8 +15,8 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
private const string VIDEO_HEADER_KEY = "HandleNewHeaderRule_VideoHeader"; private const string VIDEO_HEADER_KEY = "HandleNewHeaderRule_VideoHeader";
private const string AUDIO_HEADER_KEY = "HandleNewHeaderRule_AudioHeader"; private const string AUDIO_HEADER_KEY = "HandleNewHeaderRule_AudioHeader";
private static readonly ProcessingComment MultipleHeaderComment = new ProcessingComment(CommentType.DecodingHeader, "收到了连续多个 Header新建文件"); private static readonly ProcessingComment MultipleHeaderComment = new ProcessingComment(CommentType.DecodingHeader, true, "收到了连续多个 Header新建文件");
private static readonly ProcessingComment SplitFileComment = new ProcessingComment(CommentType.DecodingHeader, "因为 Header 问题新建文件"); private static readonly ProcessingComment SplitFileComment = new ProcessingComment(CommentType.DecodingHeader, true, "因为 Header 问题新建文件");
public void Run(FlvProcessingContext context, Action next) public void Run(FlvProcessingContext context, Action next)
{ {

View File

@ -12,7 +12,7 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
{ {
private const string STORE_KEY = "HandleNewScriptRule_MetaDataReceived"; private const string STORE_KEY = "HandleNewScriptRule_MetaDataReceived";
private const string onMetaData = "onMetaData"; private const string onMetaData = "onMetaData";
private static readonly ProcessingComment comment_onmetadata = new ProcessingComment(CommentType.OnMetaData, "收到了 onMetaData"); private static readonly ProcessingComment comment_onmetadata = new ProcessingComment(CommentType.OnMetaData, false, "收到了 onMetaData");
public void Run(FlvProcessingContext context, Action next) public void Run(FlvProcessingContext context, Action next)
{ {
@ -95,12 +95,12 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
{ {
// 记录信息,不输出到文件,不对文件进行分段。 // 记录信息,不输出到文件,不对文件进行分段。
var message = $"重复收到 onMetaData, onMetaData 内容: {data?.ToJson() ?? "(null)"}"; var message = $"重复收到 onMetaData, onMetaData 内容: {data?.ToJson() ?? "(null)"}";
context.AddComment(new ProcessingComment(CommentType.OnMetaData, message)); context.AddComment(new ProcessingComment(CommentType.OnMetaData, false, message));
yield return new PipelineLogMessageWithLocationAction(Serilog.Events.LogEventLevel.Warning, "重复收到 onMetaData"); yield return new PipelineLogMessageWithLocationAction(Serilog.Events.LogEventLevel.Warning, "重复收到 onMetaData");
yield break; yield break;
} }
notOnMetaData: notOnMetaData:
context.AddComment(new ProcessingComment(CommentType.Logging, "收到了非 onMetaData 的 Script Tag: " + (data?.ToJson() ?? "(null)"))); context.AddComment(new ProcessingComment(CommentType.Logging, false, "收到了非 onMetaData 的 Script Tag: " + (data?.ToJson() ?? "(null)")));
yield break; yield break;
} }
} }

View File

@ -21,7 +21,7 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
private const string QUEUE_KEY = "DeDuplicationQueue"; private const string QUEUE_KEY = "DeDuplicationQueue";
private static readonly FarmHash64 farmHash64 = new(); private static readonly FarmHash64 farmHash64 = new();
private static readonly ProcessingComment comment = new ProcessingComment(CommentType.RepeatingData, "重复数据"); private static readonly ProcessingComment comment = new ProcessingComment(CommentType.RepeatingData, true, "重复数据");
public void Run(FlvProcessingContext context, Action next) public void Run(FlvProcessingContext context, Action next)
{ {

View File

@ -42,12 +42,12 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
var diff = currentTimestamp - ts.LastOriginal; var diff = currentTimestamp - ts.LastOriginal;
if (diff < 0) if (diff < 0)
{ {
context.AddComment(new ProcessingComment(CommentType.TimestampJump, $"时间戳变小, curr: {currentTimestamp}, diff: {diff}")); context.AddComment(new ProcessingComment(CommentType.TimestampJump, true, $"时间戳变小, curr: {currentTimestamp}, diff: {diff}"));
ts.CurrentOffset = currentTimestamp - ts.NextTimestampTarget; ts.CurrentOffset = currentTimestamp - ts.NextTimestampTarget;
} }
else if (diff > JUMP_THRESHOLD) else if (diff > JUMP_THRESHOLD)
{ {
context.AddComment(new ProcessingComment(CommentType.TimestampJump, $"时间戳间隔过大, curr: {currentTimestamp}, diff: {diff}")); context.AddComment(new ProcessingComment(CommentType.TimestampJump, true, $"时间戳间隔过大, curr: {currentTimestamp}, diff: {diff}"));
ts.CurrentOffset = currentTimestamp - ts.NextTimestampTarget; ts.CurrentOffset = currentTimestamp - ts.NextTimestampTarget;
} }

View File

@ -12,8 +12,8 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
/// </summary> /// </summary>
public class UpdateTimestampOffsetRule : ISimpleProcessingRule public class UpdateTimestampOffsetRule : ISimpleProcessingRule
{ {
private static readonly ProcessingComment COMMENT_JumpedWithinGOP = new ProcessingComment(CommentType.Unrepairable, "GOP 内音频或视频时间戳不连续"); private static readonly ProcessingComment COMMENT_JumpedWithinGOP = new ProcessingComment(CommentType.Unrepairable, true, "GOP 内音频或视频时间戳不连续");
private static readonly ProcessingComment COMMENT_CantSolve = new ProcessingComment(CommentType.Unrepairable, "出现了无法计算偏移量的音视频偏移"); private static readonly ProcessingComment COMMENT_CantSolve = new ProcessingComment(CommentType.Unrepairable, true, "出现了无法计算偏移量的音视频偏移");
public void Run(FlvProcessingContext context, Action next) public void Run(FlvProcessingContext context, Action next)
{ {
@ -145,7 +145,7 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
validOffset: validOffset:
if (offset != 0) if (offset != 0)
{ {
context.AddComment(new ProcessingComment(CommentType.TimestampOffset, $"音视频时间戳偏移, D: {offset}")); context.AddComment(new ProcessingComment(CommentType.TimestampOffset, true, $"音视频时间戳偏移, D: {offset}"));
foreach (var tag in data.Tags) foreach (var tag in data.Tags)
if (tag.Type == TagType.Video) if (tag.Type == TagType.Video)

View File

@ -137,25 +137,25 @@ namespace BililiveRecorder.ToolBox.Tool.Analyze
{ {
var (videoStats, audioStats) = statsRule.GetStats(); var (videoStats, audioStats) = statsRule.GetStats();
var countableComments = comments.Where(x => x.T != CommentType.Logging).ToArray(); var countableComments = comments.Where(x => x.Type != CommentType.Logging).ToArray();
return new AnalyzeResponse return new AnalyzeResponse
{ {
InputPath = inputPath, InputPath = inputPath,
NeedFix = tagWriter.OutputFileCount != 1 || countableComments.Any(), NeedFix = tagWriter.OutputFileCount != 1 || countableComments.Any(),
Unrepairable = countableComments.Any(x => x.T == CommentType.Unrepairable), Unrepairable = countableComments.Any(x => x.Type == CommentType.Unrepairable),
OutputFileCount = tagWriter.OutputFileCount, OutputFileCount = tagWriter.OutputFileCount,
VideoStats = videoStats, VideoStats = videoStats,
AudioStats = audioStats, AudioStats = audioStats,
IssueTypeOther = countableComments.Count(x => x.T == CommentType.Other), IssueTypeOther = countableComments.Count(x => x.Type == CommentType.Other),
IssueTypeUnrepairable = countableComments.Count(x => x.T == CommentType.Unrepairable), IssueTypeUnrepairable = countableComments.Count(x => x.Type == CommentType.Unrepairable),
IssueTypeTimestampJump = countableComments.Count(x => x.T == CommentType.TimestampJump), IssueTypeTimestampJump = countableComments.Count(x => x.Type == CommentType.TimestampJump),
IssueTypeTimestampOffset = countableComments.Count(x => x.T == CommentType.TimestampOffset), IssueTypeTimestampOffset = countableComments.Count(x => x.Type == CommentType.TimestampOffset),
IssueTypeDecodingHeader = countableComments.Count(x => x.T == CommentType.DecodingHeader), IssueTypeDecodingHeader = countableComments.Count(x => x.Type == CommentType.DecodingHeader),
IssueTypeRepeatingData = countableComments.Count(x => x.T == CommentType.RepeatingData) IssueTypeRepeatingData = countableComments.Count(x => x.Type == CommentType.RepeatingData)
}; };
}); });

View File

@ -191,7 +191,7 @@ namespace BililiveRecorder.ToolBox.Tool.Fix
{ {
var (videoStats, audioStats) = statsRule.GetStats(); var (videoStats, audioStats) = statsRule.GetStats();
var countableComments = comments.Where(x => x.T != CommentType.Logging).ToArray(); var countableComments = comments.Where(x => x.Type != CommentType.Logging).ToArray();
return new FixResponse return new FixResponse
{ {
InputPath = inputPath, InputPath = inputPath,
@ -199,17 +199,17 @@ namespace BililiveRecorder.ToolBox.Tool.Fix
OutputFileCount = outputPaths.Count, OutputFileCount = outputPaths.Count,
NeedFix = outputPaths.Count != 1 || countableComments.Any(), NeedFix = outputPaths.Count != 1 || countableComments.Any(),
Unrepairable = countableComments.Any(x => x.T == CommentType.Unrepairable), Unrepairable = countableComments.Any(x => x.Type == CommentType.Unrepairable),
VideoStats = videoStats, VideoStats = videoStats,
AudioStats = audioStats, AudioStats = audioStats,
IssueTypeOther = countableComments.Count(x => x.T == CommentType.Other), IssueTypeOther = countableComments.Count(x => x.Type == CommentType.Other),
IssueTypeUnrepairable = countableComments.Count(x => x.T == CommentType.Unrepairable), IssueTypeUnrepairable = countableComments.Count(x => x.Type == CommentType.Unrepairable),
IssueTypeTimestampJump = countableComments.Count(x => x.T == CommentType.TimestampJump), IssueTypeTimestampJump = countableComments.Count(x => x.Type == CommentType.TimestampJump),
IssueTypeTimestampOffset = countableComments.Count(x => x.T == CommentType.TimestampOffset), IssueTypeTimestampOffset = countableComments.Count(x => x.Type == CommentType.TimestampOffset),
IssueTypeDecodingHeader = countableComments.Count(x => x.T == CommentType.DecodingHeader), IssueTypeDecodingHeader = countableComments.Count(x => x.Type == CommentType.DecodingHeader),
IssueTypeRepeatingData = countableComments.Count(x => x.T == CommentType.RepeatingData) IssueTypeRepeatingData = countableComments.Count(x => x.Type == CommentType.RepeatingData)
}; };
}); });

View File

@ -11,6 +11,7 @@ using System.Security;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Threading; using System.Windows.Threading;
using BililiveRecorder.Flv.Pipeline;
using BililiveRecorder.ToolBox; using BililiveRecorder.ToolBox;
using Esprima; using Esprima;
using Jint.Runtime; using Jint.Runtime;
@ -225,6 +226,7 @@ namespace BililiveRecorder.WPF
.Enrich.FromLogContext() .Enrich.FromLogContext()
.Enrich.WithExceptionDetails() .Enrich.WithExceptionDetails()
.Destructure.AsScalar<IPAddress>() .Destructure.AsScalar<IPAddress>()
.Destructure.AsScalar<ProcessingComment>()
.Destructure.ByTransforming<Flv.Xml.XmlFlvFile.XmlFlvFileMeta>(x => new .Destructure.ByTransforming<Flv.Xml.XmlFlvFile.XmlFlvFileMeta>(x => new
{ {
x.Version, x.Version,

View File

@ -752,9 +752,10 @@ namespace BililiveRecorder.Flv.Pipeline
} }
public class ProcessingComment public class ProcessingComment
{ {
public ProcessingComment(BililiveRecorder.Flv.Pipeline.CommentType t, string c) { } public ProcessingComment(BililiveRecorder.Flv.Pipeline.CommentType type, bool actionRequired, string comment) { }
public string C { get; } public bool ActionRequired { get; }
public BililiveRecorder.Flv.Pipeline.CommentType T { get; } public string Comment { get; }
public BililiveRecorder.Flv.Pipeline.CommentType Type { get; }
public override string ToString() { } public override string ToString() { }
} }
public delegate void ProcessingDelegate(BililiveRecorder.Flv.Pipeline.FlvProcessingContext context); public delegate void ProcessingDelegate(BililiveRecorder.Flv.Pipeline.FlvProcessingContext context);

View File

@ -20,7 +20,7 @@ namespace BililiveRecorder.Flv.Tests.RuleTests
[ExpectationPath("Bad")] [ExpectationPath("Bad")]
public class IntegratedBadTests : IntegratedTestBase public class IntegratedBadTests : IntegratedTestBase
{ {
[Theory(Skip = "魔改版,不测试")] [Theory()]
[Expectation("TestBadSamples")] [Expectation("TestBadSamples")]
[SampleFileTestData("../data/flv/TestData/Bad", "*.xml")] [SampleFileTestData("../data/flv/TestData/Bad", "*.xml")]
public async Task TestBadSamples(string path) public async Task TestBadSamples(string path)
@ -35,12 +35,12 @@ namespace BililiveRecorder.Flv.Tests.RuleTests
await RunPipeline(reader, flvTagListWriter, comments).ConfigureAwait(false); await RunPipeline(reader, flvTagListWriter, comments).ConfigureAwait(false);
// Assert // Assert
comments.RemoveAll(x => x.T == CommentType.Logging); comments.RemoveAll(x => !x.ActionRequired);
var outputResult = new OutputResult var outputResult = new OutputResult
{ {
AlternativeHeaders = flvTagListWriter.AlternativeHeaders.Select(x => x.BinaryDataForSerializationUseOnly).ToArray(), AlternativeHeaders = flvTagListWriter.AlternativeHeaders.Select(x => x.BinaryDataForSerializationUseOnly).ToArray(),
Comments = comments.GroupBy(x => x.T).Select(x => new CommentCount(x.Key, x.Count())).ToArray(), Comments = comments.GroupBy(x => x.Type).Select(x => new CommentCount(x.Key, x.Count())).ToArray(),
TagCounts = flvTagListWriter.Files.Select(x => x.Count).ToArray() TagCounts = flvTagListWriter.Files.Select(x => x.Count).ToArray()
}; };

View File

@ -14,7 +14,7 @@ namespace BililiveRecorder.Flv.Tests.RuleTests
[ExpectationPath("Good")] [ExpectationPath("Good")]
public class IntegratedGoodTests : IntegratedTestBase public class IntegratedGoodTests : IntegratedTestBase
{ {
[Theory(Skip = "魔改版,不测试")] [Theory()]
[Expectation("StandardTest")] [Expectation("StandardTest")]
[SampleFileTestData("../data/flv/TestData/Good", "*.xml")] [SampleFileTestData("../data/flv/TestData/Good", "*.xml")]
public async Task StrictTestsAsync(string path) public async Task StrictTestsAsync(string path)
@ -29,7 +29,7 @@ namespace BililiveRecorder.Flv.Tests.RuleTests
await RunPipeline(reader, flvTagListWriter, comments).ConfigureAwait(false); await RunPipeline(reader, flvTagListWriter, comments).ConfigureAwait(false);
// Assert // Assert
comments.RemoveAll(x => x.T == CommentType.Logging); comments.RemoveAll(x => !x.ActionRequired);
Assert.Empty(comments); Assert.Empty(comments);
@ -49,7 +49,7 @@ namespace BililiveRecorder.Flv.Tests.RuleTests
await Verifier.Verify(xmlStr).UseExtension("xml").UseParameters(path); await Verifier.Verify(xmlStr).UseExtension("xml").UseParameters(path);
} }
[Theory(Skip = "魔改版,不测试")] [Theory()]
[Expectation("WithOffsetTest")] [Expectation("WithOffsetTest")]
[SampleFileTestData("../data/flv/TestData/Good", "*.xml")] [SampleFileTestData("../data/flv/TestData/Good", "*.xml")]
public async Task StrictWithArtificalOffsetTestsAsync(string path) public async Task StrictWithArtificalOffsetTestsAsync(string path)
@ -74,8 +74,8 @@ namespace BililiveRecorder.Flv.Tests.RuleTests
await RunPipeline(reader, output, comments).ConfigureAwait(false); await RunPipeline(reader, output, comments).ConfigureAwait(false);
// Assert // Assert
comments.RemoveAll(x => x.T == CommentType.Logging); comments.RemoveAll(x => !x.ActionRequired);
Assert.Equal(CommentType.TimestampJump, Assert.Single(comments).T); Assert.Equal(CommentType.TimestampJump, Assert.Single(comments).Type);
Assert.Empty(output.AlternativeHeaders); Assert.Empty(output.AlternativeHeaders);

View File

@ -43,7 +43,7 @@ namespace BililiveRecorder.Flv.Tests.RuleTests
await RunPipeline(reader, output, comments).ConfigureAwait(false); await RunPipeline(reader, output, comments).ConfigureAwait(false);
// 忽略 ignore Logging // 忽略 ignore Logging
comments.RemoveAll(x => x.T == CommentType.Logging); comments.RemoveAll(x => !x.ActionRequired);
// 不应该有任何问题 Shouldn't have any problems // 不应该有任何问题 Shouldn't have any problems
Assert.Empty(comments); Assert.Empty(comments);
// 不应该有多个 Header Shouldn't have multiple headers // 不应该有多个 Header Shouldn't have multiple headers