diff --git a/BililiveRecorder.ToolBox/ProcessingRules/FfmpegDetectionRule.cs b/BililiveRecorder.ToolBox/ProcessingRules/FfmpegDetectionRule.cs new file mode 100644 index 0000000..1507a3e --- /dev/null +++ b/BililiveRecorder.ToolBox/ProcessingRules/FfmpegDetectionRule.cs @@ -0,0 +1,41 @@ +using System; +using System.Linq; +using BililiveRecorder.Flv.Amf; +using BililiveRecorder.Flv.Pipeline; +using BililiveRecorder.Flv.Pipeline.Actions; + +namespace BililiveRecorder.ToolBox.ProcessingRules +{ + public class FfmpegDetectionRule : ISimpleProcessingRule + { + public bool EndTagDetected { get; private set; } + public bool LavfEncoderDetected { get; private set; } + + public void Run(FlvProcessingContext context, Action next) + { + if (!this.EndTagDetected && context.Actions.Any(x => x is PipelineEndAction)) + { + this.EndTagDetected = true; + } + + if (!this.LavfEncoderDetected) + { + if (context.Actions.Any(action => + { + if (action is PipelineScriptAction scriptAction) + { + var encoder = scriptAction?.Tag?.ScriptData?.GetMetadataValue()?.Value?["encoder"] as ScriptDataString; + if (encoder is not null) + { + return encoder.Value.StartsWith("Lavf", StringComparison.Ordinal); + } + } + return false; + })) + { + this.LavfEncoderDetected = true; + } + } + } + } +} diff --git a/BililiveRecorder.ToolBox/Tool/Analyze/AnalyzeHandler.cs b/BililiveRecorder.ToolBox/Tool/Analyze/AnalyzeHandler.cs index f5de3c7..2d2b51b 100644 --- a/BililiveRecorder.ToolBox/Tool/Analyze/AnalyzeHandler.cs +++ b/BililiveRecorder.ToolBox/Tool/Analyze/AnalyzeHandler.cs @@ -93,7 +93,8 @@ namespace BililiveRecorder.ToolBox.Tool.Analyze using var grouping = new TagGroupReader(tagReader); using var writer = new FlvProcessingContextWriter(tagWriter: tagWriter, allowMissingHeader: true, disableKeyframes: true, logger: logger); var statsRule = new StatsRule(); - var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).Add(statsRule).AddDefault().AddRemoveFillerData().Build(); + var ffmpegDetectionRule = new FfmpegDetectionRule(); + var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).Add(statsRule).Add(ffmpegDetectionRule).AddDefault().AddRemoveFillerData().Build(); // Run await Task.Run(async () => @@ -144,6 +145,7 @@ namespace BililiveRecorder.ToolBox.Tool.Analyze NeedFix = tagWriter.OutputFileCount != 1 || countableComments.Any(), Unrepairable = countableComments.Any(x => x.Type == CommentType.Unrepairable), + FfmpegDetected = ffmpegDetectionRule.LavfEncoderDetected && ffmpegDetectionRule.EndTagDetected, OutputFileCount = tagWriter.OutputFileCount, diff --git a/BililiveRecorder.ToolBox/Tool/Analyze/AnalyzeResponse.cs b/BililiveRecorder.ToolBox/Tool/Analyze/AnalyzeResponse.cs index a6b7fcb..4bf94c5 100644 --- a/BililiveRecorder.ToolBox/Tool/Analyze/AnalyzeResponse.cs +++ b/BililiveRecorder.ToolBox/Tool/Analyze/AnalyzeResponse.cs @@ -9,6 +9,7 @@ namespace BililiveRecorder.ToolBox.Tool.Analyze public bool NeedFix { get; set; } public bool Unrepairable { get; set; } + public bool FfmpegDetected { get; set; } public int OutputFileCount { get; set; } @@ -41,6 +42,18 @@ namespace BililiveRecorder.ToolBox.Tool.Analyze }); } + if (this.FfmpegDetected) + { + AnsiConsole.Write(new Panel("This file seems like it was written by FFmpeg.\n" + + "It might no longer possible to fix this file, if there's any problem.\n" + + "Only unprocessed data taken directly from the stream server could be fixed.") + { + Header = new PanelHeader("[bold yellow]FFmpeg Detected[/]"), + Border = BoxBorder.Rounded, + BorderStyle = new Style(foreground: Color.Yellow) + }); + } + AnsiConsole.Write(new Panel(this.InputPath.EscapeMarkup()) { Header = new PanelHeader("Input"), diff --git a/BililiveRecorder.ToolBox/Tool/Fix/FixHandler.cs b/BililiveRecorder.ToolBox/Tool/Fix/FixHandler.cs index 5ed44fe..a1989d1 100644 --- a/BililiveRecorder.ToolBox/Tool/Fix/FixHandler.cs +++ b/BililiveRecorder.ToolBox/Tool/Fix/FixHandler.cs @@ -112,7 +112,8 @@ namespace BililiveRecorder.ToolBox.Tool.Fix using var grouping = new TagGroupReader(tagReader); using var writer = new FlvProcessingContextWriter(tagWriter: tagWriter, allowMissingHeader: true, disableKeyframes: false, logger: logger); var statsRule = new StatsRule(); - var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).Add(statsRule).AddDefault().AddRemoveFillerData().Build(); + var ffmpegDetectionRule = new FfmpegDetectionRule(); + var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).Add(statsRule).Add(ffmpegDetectionRule).AddDefault().AddRemoveFillerData().Build(); // Run await Task.Run(async () => @@ -200,6 +201,7 @@ namespace BililiveRecorder.ToolBox.Tool.Fix NeedFix = outputPaths.Count != 1 || countableComments.Any(), Unrepairable = countableComments.Any(x => x.Type == CommentType.Unrepairable), + FfmpegDetected = ffmpegDetectionRule.LavfEncoderDetected && ffmpegDetectionRule.EndTagDetected, VideoStats = videoStats, AudioStats = audioStats, diff --git a/BililiveRecorder.ToolBox/Tool/Fix/FixResponse.cs b/BililiveRecorder.ToolBox/Tool/Fix/FixResponse.cs index 69e339a..9271a3d 100644 --- a/BililiveRecorder.ToolBox/Tool/Fix/FixResponse.cs +++ b/BililiveRecorder.ToolBox/Tool/Fix/FixResponse.cs @@ -12,6 +12,7 @@ namespace BililiveRecorder.ToolBox.Tool.Fix public bool NeedFix { get; set; } public bool Unrepairable { get; set; } + public bool FfmpegDetected { get; set; } public int OutputFileCount { get; set; } @@ -41,6 +42,18 @@ namespace BililiveRecorder.ToolBox.Tool.Fix }); } + if (this.FfmpegDetected) + { + AnsiConsole.Write(new Panel("This file seems like it was written by FFmpeg.\n" + + "It might no longer possible to fix this file, if there's any problem.\n" + + "Only unprocessed data taken directly from the stream server could be fixed.") + { + Header = new PanelHeader("[bold yellow]FFmpeg Detected[/]"), + Border = BoxBorder.Rounded, + BorderStyle = new Style(foreground: Color.Yellow) + }); + } + AnsiConsole.Write(new Panel(this.InputPath.EscapeMarkup()) { Header = new PanelHeader("Input"), diff --git a/BililiveRecorder.WPF/Pages/ToolboxAutoFixPage.xaml b/BililiveRecorder.WPF/Pages/ToolboxAutoFixPage.xaml index e8c95a9..d28a90f 100644 --- a/BililiveRecorder.WPF/Pages/ToolboxAutoFixPage.xaml +++ b/BililiveRecorder.WPF/Pages/ToolboxAutoFixPage.xaml @@ -121,6 +121,9 @@ +