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 @@
+