mirror of
https://github.com/BililiveRecorder/BililiveRecorder.git
synced 2024-11-16 03:32:20 +08:00
Add new option FlvProcessorSplitOnScriptTag
This commit is contained in:
parent
8aa53b5b30
commit
232eb1af5b
|
@ -24,6 +24,7 @@ namespace BililiveRecorder.Cli.Configure
|
||||||
RecordDanmakuGuard,
|
RecordDanmakuGuard,
|
||||||
RecordingQuality,
|
RecordingQuality,
|
||||||
FileNameRecordTemplate,
|
FileNameRecordTemplate,
|
||||||
|
FlvProcessorSplitOnScriptTag,
|
||||||
WebHookUrls,
|
WebHookUrls,
|
||||||
WebHookUrlsV2,
|
WebHookUrlsV2,
|
||||||
WpfShowTitleAndArea,
|
WpfShowTitleAndArea,
|
||||||
|
@ -54,7 +55,8 @@ namespace BililiveRecorder.Cli.Configure
|
||||||
RecordDanmakuSuperChat,
|
RecordDanmakuSuperChat,
|
||||||
RecordDanmakuGift,
|
RecordDanmakuGift,
|
||||||
RecordDanmakuGuard,
|
RecordDanmakuGuard,
|
||||||
RecordingQuality
|
RecordingQuality,
|
||||||
|
FlvProcessorSplitOnScriptTag
|
||||||
}
|
}
|
||||||
public static class ConfigInstructions
|
public static class ConfigInstructions
|
||||||
{
|
{
|
||||||
|
@ -73,6 +75,7 @@ namespace BililiveRecorder.Cli.Configure
|
||||||
GlobalConfig.Add(GlobalConfigProperties.RecordDanmakuGuard, new ConfigInstruction<GlobalConfig, bool>(config => config.HasRecordDanmakuGuard = false, (config, value) => config.RecordDanmakuGuard = value) { Name = "RecordDanmakuGuard", CanBeOptional = true });
|
GlobalConfig.Add(GlobalConfigProperties.RecordDanmakuGuard, new ConfigInstruction<GlobalConfig, bool>(config => config.HasRecordDanmakuGuard = false, (config, value) => config.RecordDanmakuGuard = value) { Name = "RecordDanmakuGuard", CanBeOptional = true });
|
||||||
GlobalConfig.Add(GlobalConfigProperties.RecordingQuality, new ConfigInstruction<GlobalConfig, string>(config => config.HasRecordingQuality = false, (config, value) => config.RecordingQuality = value) { Name = "RecordingQuality", CanBeOptional = true });
|
GlobalConfig.Add(GlobalConfigProperties.RecordingQuality, new ConfigInstruction<GlobalConfig, string>(config => config.HasRecordingQuality = false, (config, value) => config.RecordingQuality = value) { Name = "RecordingQuality", CanBeOptional = true });
|
||||||
GlobalConfig.Add(GlobalConfigProperties.FileNameRecordTemplate, new ConfigInstruction<GlobalConfig, string>(config => config.HasFileNameRecordTemplate = false, (config, value) => config.FileNameRecordTemplate = value) { Name = "FileNameRecordTemplate", CanBeOptional = true });
|
GlobalConfig.Add(GlobalConfigProperties.FileNameRecordTemplate, new ConfigInstruction<GlobalConfig, string>(config => config.HasFileNameRecordTemplate = false, (config, value) => config.FileNameRecordTemplate = value) { Name = "FileNameRecordTemplate", CanBeOptional = true });
|
||||||
|
GlobalConfig.Add(GlobalConfigProperties.FlvProcessorSplitOnScriptTag, new ConfigInstruction<GlobalConfig, bool>(config => config.HasFlvProcessorSplitOnScriptTag = false, (config, value) => config.FlvProcessorSplitOnScriptTag = value) { Name = "FlvProcessorSplitOnScriptTag", CanBeOptional = true });
|
||||||
GlobalConfig.Add(GlobalConfigProperties.WebHookUrls, new ConfigInstruction<GlobalConfig, string>(config => config.HasWebHookUrls = false, (config, value) => config.WebHookUrls = value) { Name = "WebHookUrls", CanBeOptional = true });
|
GlobalConfig.Add(GlobalConfigProperties.WebHookUrls, new ConfigInstruction<GlobalConfig, string>(config => config.HasWebHookUrls = false, (config, value) => config.WebHookUrls = value) { Name = "WebHookUrls", CanBeOptional = true });
|
||||||
GlobalConfig.Add(GlobalConfigProperties.WebHookUrlsV2, new ConfigInstruction<GlobalConfig, string>(config => config.HasWebHookUrlsV2 = false, (config, value) => config.WebHookUrlsV2 = value) { Name = "WebHookUrlsV2", CanBeOptional = true });
|
GlobalConfig.Add(GlobalConfigProperties.WebHookUrlsV2, new ConfigInstruction<GlobalConfig, string>(config => config.HasWebHookUrlsV2 = false, (config, value) => config.WebHookUrlsV2 = value) { Name = "WebHookUrlsV2", CanBeOptional = true });
|
||||||
GlobalConfig.Add(GlobalConfigProperties.WpfShowTitleAndArea, new ConfigInstruction<GlobalConfig, bool>(config => config.HasWpfShowTitleAndArea = false, (config, value) => config.WpfShowTitleAndArea = value) { Name = "WpfShowTitleAndArea", CanBeOptional = true });
|
GlobalConfig.Add(GlobalConfigProperties.WpfShowTitleAndArea, new ConfigInstruction<GlobalConfig, bool>(config => config.HasWpfShowTitleAndArea = false, (config, value) => config.WpfShowTitleAndArea = value) { Name = "WpfShowTitleAndArea", CanBeOptional = true });
|
||||||
|
@ -100,6 +103,7 @@ namespace BililiveRecorder.Cli.Configure
|
||||||
RoomConfig.Add(RoomConfigProperties.RecordDanmakuGift, new ConfigInstruction<RoomConfig, bool>(config => config.HasRecordDanmakuGift = false, (config, value) => config.RecordDanmakuGift = value) { Name = "RecordDanmakuGift", CanBeOptional = true });
|
RoomConfig.Add(RoomConfigProperties.RecordDanmakuGift, new ConfigInstruction<RoomConfig, bool>(config => config.HasRecordDanmakuGift = false, (config, value) => config.RecordDanmakuGift = value) { Name = "RecordDanmakuGift", CanBeOptional = true });
|
||||||
RoomConfig.Add(RoomConfigProperties.RecordDanmakuGuard, new ConfigInstruction<RoomConfig, bool>(config => config.HasRecordDanmakuGuard = false, (config, value) => config.RecordDanmakuGuard = value) { Name = "RecordDanmakuGuard", CanBeOptional = true });
|
RoomConfig.Add(RoomConfigProperties.RecordDanmakuGuard, new ConfigInstruction<RoomConfig, bool>(config => config.HasRecordDanmakuGuard = false, (config, value) => config.RecordDanmakuGuard = value) { Name = "RecordDanmakuGuard", CanBeOptional = true });
|
||||||
RoomConfig.Add(RoomConfigProperties.RecordingQuality, new ConfigInstruction<RoomConfig, string>(config => config.HasRecordingQuality = false, (config, value) => config.RecordingQuality = value) { Name = "RecordingQuality", CanBeOptional = true });
|
RoomConfig.Add(RoomConfigProperties.RecordingQuality, new ConfigInstruction<RoomConfig, string>(config => config.HasRecordingQuality = false, (config, value) => config.RecordingQuality = value) { Name = "RecordingQuality", CanBeOptional = true });
|
||||||
|
RoomConfig.Add(RoomConfigProperties.FlvProcessorSplitOnScriptTag, new ConfigInstruction<RoomConfig, bool>(config => config.HasFlvProcessorSplitOnScriptTag = false, (config, value) => config.FlvProcessorSplitOnScriptTag = value) { Name = "FlvProcessorSplitOnScriptTag", CanBeOptional = true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,14 @@ namespace BililiveRecorder.Core.Config.V3
|
||||||
[JsonProperty(nameof(RecordingQuality)), EditorBrowsable(EditorBrowsableState.Never)]
|
[JsonProperty(nameof(RecordingQuality)), EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
public Optional<string?> OptionalRecordingQuality { get => this.GetPropertyValueOptional<string>(nameof(this.RecordingQuality)); set => this.SetPropertyValueOptional(value, nameof(this.RecordingQuality)); }
|
public Optional<string?> OptionalRecordingQuality { get => this.GetPropertyValueOptional<string>(nameof(this.RecordingQuality)); set => this.SetPropertyValueOptional(value, nameof(this.RecordingQuality)); }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// FLV修复-检测到可能缺少数据时分段
|
||||||
|
/// </summary>
|
||||||
|
public bool FlvProcessorSplitOnScriptTag { get => this.GetPropertyValue<bool>(); set => this.SetPropertyValue(value); }
|
||||||
|
public bool HasFlvProcessorSplitOnScriptTag { get => this.GetPropertyHasValue(nameof(this.FlvProcessorSplitOnScriptTag)); set => this.SetPropertyHasValue<bool>(value, nameof(this.FlvProcessorSplitOnScriptTag)); }
|
||||||
|
[JsonProperty(nameof(FlvProcessorSplitOnScriptTag)), EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get => this.GetPropertyValueOptional<bool>(nameof(this.FlvProcessorSplitOnScriptTag)); set => this.SetPropertyValueOptional(value, nameof(this.FlvProcessorSplitOnScriptTag)); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 录制文件名模板
|
/// 录制文件名模板
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -266,6 +274,14 @@ namespace BililiveRecorder.Core.Config.V3
|
||||||
[JsonProperty(nameof(FileNameRecordTemplate)), EditorBrowsable(EditorBrowsableState.Never)]
|
[JsonProperty(nameof(FileNameRecordTemplate)), EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
public Optional<string?> OptionalFileNameRecordTemplate { get => this.GetPropertyValueOptional<string>(nameof(this.FileNameRecordTemplate)); set => this.SetPropertyValueOptional(value, nameof(this.FileNameRecordTemplate)); }
|
public Optional<string?> OptionalFileNameRecordTemplate { get => this.GetPropertyValueOptional<string>(nameof(this.FileNameRecordTemplate)); set => this.SetPropertyValueOptional(value, nameof(this.FileNameRecordTemplate)); }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// FLV修复-检测到可能缺少数据时分段
|
||||||
|
/// </summary>
|
||||||
|
public bool FlvProcessorSplitOnScriptTag { get => this.GetPropertyValue<bool>(); set => this.SetPropertyValue(value); }
|
||||||
|
public bool HasFlvProcessorSplitOnScriptTag { get => this.GetPropertyHasValue(nameof(this.FlvProcessorSplitOnScriptTag)); set => this.SetPropertyHasValue<bool>(value, nameof(this.FlvProcessorSplitOnScriptTag)); }
|
||||||
|
[JsonProperty(nameof(FlvProcessorSplitOnScriptTag)), EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get => this.GetPropertyValueOptional<bool>(nameof(this.FlvProcessorSplitOnScriptTag)); set => this.SetPropertyValueOptional(value, nameof(this.FlvProcessorSplitOnScriptTag)); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// WebhookV1
|
/// WebhookV1
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -413,6 +429,8 @@ namespace BililiveRecorder.Core.Config.V3
|
||||||
|
|
||||||
public string FileNameRecordTemplate => @"{{ roomId }}-{{ name }}/录制-{{ roomId }}-{{ ""now"" | time_zone: ""Asia/Shanghai"" | format_date: ""yyyyMMdd-HHmmss-fff"" }}-{{ title }}.flv";
|
public string FileNameRecordTemplate => @"{{ roomId }}-{{ name }}/录制-{{ roomId }}-{{ ""now"" | time_zone: ""Asia/Shanghai"" | format_date: ""yyyyMMdd-HHmmss-fff"" }}-{{ title }}.flv";
|
||||||
|
|
||||||
|
public bool FlvProcessorSplitOnScriptTag => false;
|
||||||
|
|
||||||
public string WebHookUrls => @"";
|
public string WebHookUrls => @"";
|
||||||
|
|
||||||
public string WebHookUrlsV2 => @"";
|
public string WebHookUrlsV2 => @"";
|
||||||
|
|
|
@ -15,6 +15,7 @@ using BililiveRecorder.Flv;
|
||||||
using BililiveRecorder.Flv.Amf;
|
using BililiveRecorder.Flv.Amf;
|
||||||
using BililiveRecorder.Flv.Pipeline;
|
using BililiveRecorder.Flv.Pipeline;
|
||||||
using BililiveRecorder.Flv.Pipeline.Actions;
|
using BililiveRecorder.Flv.Pipeline.Actions;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace BililiveRecorder.Core.Recording
|
namespace BililiveRecorder.Core.Recording
|
||||||
|
@ -63,10 +64,14 @@ namespace BililiveRecorder.Core.Recording
|
||||||
this.statsRule.StatsUpdated += this.StatsRule_StatsUpdated;
|
this.statsRule.StatsUpdated += this.StatsRule_StatsUpdated;
|
||||||
|
|
||||||
this.pipeline = builder
|
this.pipeline = builder
|
||||||
.Add(this.statsRule)
|
.ConfigureServices(services => services.AddSingleton(new ProcessingPipelineSettings
|
||||||
.Add(this.splitFileRule)
|
{
|
||||||
.AddDefault()
|
SplitOnScriptTag = room.RoomConfig.FlvProcessorSplitOnScriptTag
|
||||||
.AddRemoveFillerData()
|
}))
|
||||||
|
.AddRule(this.statsRule)
|
||||||
|
.AddRule(this.splitFileRule)
|
||||||
|
.AddDefaultRules()
|
||||||
|
.AddRemoveFillerDataRule()
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
this.targetProvider = new WriterTargetProvider(this, paths =>
|
this.targetProvider = new WriterTargetProvider(this, paths =>
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
<PackageReference Include="FastHashes" Version="2.5.0" />
|
<PackageReference Include="FastHashes" Version="2.5.0" />
|
||||||
<PackageReference Include="JsonSubTypes" Version="1.9.0" />
|
<PackageReference Include="JsonSubTypes" Version="1.9.0" />
|
||||||
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="Nullable" Version="1.3.0">
|
<PackageReference Include="Nullable" Version="1.3.0">
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace BililiveRecorder.Flv.Pipeline
|
namespace BililiveRecorder.Flv.Pipeline
|
||||||
{
|
{
|
||||||
public interface IProcessingPipelineBuilder
|
public interface IProcessingPipelineBuilder
|
||||||
{
|
{
|
||||||
IServiceProvider ServiceProvider { get; }
|
IServiceCollection ServiceCollection { get; }
|
||||||
|
|
||||||
IProcessingPipelineBuilder Add(Func<ProcessingDelegate, ProcessingDelegate> rule);
|
IProcessingPipelineBuilder AddRule(Func<ProcessingDelegate, IServiceProvider, ProcessingDelegate> rule);
|
||||||
|
|
||||||
ProcessingDelegate Build();
|
ProcessingDelegate Build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,34 +6,40 @@ namespace BililiveRecorder.Flv.Pipeline
|
||||||
{
|
{
|
||||||
public static class IProcessingPipelineBuilderExtensions
|
public static class IProcessingPipelineBuilderExtensions
|
||||||
{
|
{
|
||||||
public static IProcessingPipelineBuilder Add<T>(this IProcessingPipelineBuilder builder) where T : IProcessingRule =>
|
public static IProcessingPipelineBuilder ConfigureServices(this IProcessingPipelineBuilder builder, Action<IServiceCollection> configure)
|
||||||
builder.Add(next => (ActivatorUtilities.GetServiceOrCreateInstance<T>(builder.ServiceProvider)) switch
|
{
|
||||||
|
configure?.Invoke(builder.ServiceCollection);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IProcessingPipelineBuilder AddRule<T>(this IProcessingPipelineBuilder builder) where T : IProcessingRule =>
|
||||||
|
builder.AddRule((next, services) => ActivatorUtilities.GetServiceOrCreateInstance<T>(services) switch
|
||||||
{
|
{
|
||||||
ISimpleProcessingRule simple => context => simple.Run(context, () => next(context)),
|
ISimpleProcessingRule simple => context => simple.Run(context, () => next(context)),
|
||||||
IFullProcessingRule full => context => full.Run(context, next),
|
IFullProcessingRule full => context => full.Run(context, next),
|
||||||
_ => throw new ArgumentException($"Type ({typeof(T).FullName}) does not ISimpleProcessingRule or IFullProcessingRule")
|
_ => throw new ArgumentException($"Type ({typeof(T).FullName}) does not ISimpleProcessingRule or IFullProcessingRule")
|
||||||
});
|
});
|
||||||
|
|
||||||
public static IProcessingPipelineBuilder Add<T>(this IProcessingPipelineBuilder builder, T instance) where T : IProcessingRule =>
|
public static IProcessingPipelineBuilder AddRule<T>(this IProcessingPipelineBuilder builder, T instance) where T : IProcessingRule =>
|
||||||
instance switch
|
instance switch
|
||||||
{
|
{
|
||||||
ISimpleProcessingRule simple => builder.Add(next => context => simple.Run(context, () => next(context))),
|
ISimpleProcessingRule simple => builder.AddRule((next, services) => context => simple.Run(context, () => next(context))),
|
||||||
IFullProcessingRule full => builder.Add(next => context => full.Run(context, next)),
|
IFullProcessingRule full => builder.AddRule((next, services) => context => full.Run(context, next)),
|
||||||
_ => throw new ArgumentException($"Type ({typeof(T).FullName}) does not ISimpleProcessingRule or IFullProcessingRule")
|
_ => throw new ArgumentException($"Type ({typeof(T).FullName}) does not ISimpleProcessingRule or IFullProcessingRule")
|
||||||
};
|
};
|
||||||
|
|
||||||
public static IProcessingPipelineBuilder AddDefault(this IProcessingPipelineBuilder builder) =>
|
public static IProcessingPipelineBuilder AddDefaultRules(this IProcessingPipelineBuilder builder) =>
|
||||||
builder
|
builder
|
||||||
.Add<HandleEndTagRule>()
|
.AddRule<HandleEndTagRule>()
|
||||||
.Add<HandleDelayedAudioHeaderRule>()
|
.AddRule<HandleDelayedAudioHeaderRule>()
|
||||||
.Add<UpdateTimestampOffsetRule>()
|
.AddRule<UpdateTimestampOffsetRule>()
|
||||||
.Add<UpdateTimestampJumpRule>()
|
.AddRule<UpdateTimestampJumpRule>()
|
||||||
.Add<HandleNewScriptRule>()
|
.AddRule<HandleNewScriptRule>()
|
||||||
.Add<HandleNewHeaderRule>()
|
.AddRule<HandleNewHeaderRule>()
|
||||||
.Add<RemoveDuplicatedChunkRule>()
|
.AddRule<RemoveDuplicatedChunkRule>()
|
||||||
;
|
;
|
||||||
|
|
||||||
public static IProcessingPipelineBuilder AddRemoveFillerData(this IProcessingPipelineBuilder builder) =>
|
public static IProcessingPipelineBuilder AddRemoveFillerDataRule(this IProcessingPipelineBuilder builder) =>
|
||||||
builder.Add<RemoveFillerDataRule>();
|
builder.AddRule<RemoveFillerDataRule>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,36 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
|
|
||||||
namespace BililiveRecorder.Flv.Pipeline
|
namespace BililiveRecorder.Flv.Pipeline
|
||||||
{
|
{
|
||||||
public class ProcessingPipelineBuilder : IProcessingPipelineBuilder
|
public class ProcessingPipelineBuilder : IProcessingPipelineBuilder
|
||||||
{
|
{
|
||||||
public IServiceProvider ServiceProvider { get; }
|
public IServiceCollection ServiceCollection { get; }
|
||||||
|
|
||||||
private readonly List<Func<ProcessingDelegate, ProcessingDelegate>> rules = new List<Func<ProcessingDelegate, ProcessingDelegate>>();
|
private readonly List<Func<ProcessingDelegate, IServiceProvider, ProcessingDelegate>> rules = new();
|
||||||
|
|
||||||
public ProcessingPipelineBuilder(IServiceProvider serviceProvider)
|
public ProcessingPipelineBuilder() : this(new ServiceCollection())
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public ProcessingPipelineBuilder(IServiceCollection servicesCollection)
|
||||||
{
|
{
|
||||||
this.ServiceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
|
this.ServiceCollection = servicesCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IProcessingPipelineBuilder Add(Func<ProcessingDelegate, ProcessingDelegate> rule)
|
public IProcessingPipelineBuilder AddRule(Func<ProcessingDelegate, IServiceProvider, ProcessingDelegate> rule)
|
||||||
{
|
{
|
||||||
this.rules.Add(rule);
|
this.rules.Add(rule);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProcessingDelegate Build()
|
public ProcessingDelegate Build()
|
||||||
=> this.rules.AsEnumerable().Reverse().Aggregate((ProcessingDelegate)(_ => { }), (i, o) => o(i));
|
{
|
||||||
|
this.ServiceCollection.TryAddSingleton(_ => new ProcessingPipelineSettings());
|
||||||
|
var provider = this.ServiceCollection.BuildServiceProvider();
|
||||||
|
return this.rules.AsEnumerable().Reverse().Aggregate((ProcessingDelegate)(_ => { }), (i, o) => o(i, provider));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
BililiveRecorder.Flv/Pipeline/ProcessingPipelineSettings.cs
Normal file
13
BililiveRecorder.Flv/Pipeline/ProcessingPipelineSettings.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
namespace BililiveRecorder.Flv.Pipeline
|
||||||
|
{
|
||||||
|
public class ProcessingPipelineSettings
|
||||||
|
{
|
||||||
|
public ProcessingPipelineSettings()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 控制收到 onMetaData 时是否分段
|
||||||
|
/// </summary>
|
||||||
|
public bool SplitOnScriptTag { get; set; } = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,13 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
|
||||||
private const string onMetaData = "onMetaData";
|
private const string onMetaData = "onMetaData";
|
||||||
private static readonly ProcessingComment comment_onmetadata = new ProcessingComment(CommentType.OnMetaData, false, "收到了 onMetaData");
|
private static readonly ProcessingComment comment_onmetadata = new ProcessingComment(CommentType.OnMetaData, false, "收到了 onMetaData");
|
||||||
|
|
||||||
|
private readonly bool splitOnScriptTag;
|
||||||
|
|
||||||
|
public HandleNewScriptRule(ProcessingPipelineSettings? processingPipelineSettings)
|
||||||
|
{
|
||||||
|
this.splitOnScriptTag = processingPipelineSettings?.SplitOnScriptTag ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
public void Run(FlvProcessingContext context, Action next)
|
public void Run(FlvProcessingContext context, Action next)
|
||||||
{
|
{
|
||||||
context.PerActionRun(this.RunPerAction);
|
context.PerActionRun(this.RunPerAction);
|
||||||
|
@ -93,11 +100,20 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 记录信息,不对文件进行分段。
|
|
||||||
var message = $"收到直播服务器发送的 onMetaData 数据,请检查此位置是否有重复的直播片段或缺少数据。\n造成这个问题的原因可能是录播姬所连接的直播服务器与它的上级服务器的连接断开重连了。\n数据内容: {data?.ToJson() ?? "(null)"}";
|
var message = $"收到直播服务器发送的 onMetaData 数据,请检查此位置是否有重复的直播片段或缺少数据。\n造成这个问题的原因可能是录播姬所连接的直播服务器与它的上级服务器的连接断开重连了。\n数据内容: {data?.ToJson() ?? "(null)"}";
|
||||||
context.AddComment(new ProcessingComment(CommentType.OnMetaData, false, message));
|
context.AddComment(new ProcessingComment(CommentType.OnMetaData, false, message));
|
||||||
|
|
||||||
yield return new PipelineLogMessageWithLocationAction(message);
|
if (this.splitOnScriptTag)
|
||||||
|
{
|
||||||
|
// 对文件进行分段
|
||||||
|
yield return PipelineNewFileAction.Instance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 记录信息,不对文件进行分段。
|
||||||
|
yield return new PipelineLogMessageWithLocationAction(message);
|
||||||
|
}
|
||||||
|
|
||||||
yield return (new PipelineScriptAction(new Tag
|
yield return (new PipelineScriptAction(new Tag
|
||||||
{
|
{
|
||||||
Type = TagType.Script,
|
Type = TagType.Script,
|
||||||
|
@ -107,6 +123,7 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
|
||||||
value
|
value
|
||||||
})
|
})
|
||||||
}));
|
}));
|
||||||
|
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
notOnMetaData:
|
notOnMetaData:
|
||||||
|
|
|
@ -95,7 +95,13 @@ namespace BililiveRecorder.ToolBox.Tool.Analyze
|
||||||
using var writer = new FlvProcessingContextWriter(tagWriter: tagWriter, allowMissingHeader: true, disableKeyframes: true, logger: logger);
|
using var writer = new FlvProcessingContextWriter(tagWriter: tagWriter, allowMissingHeader: true, disableKeyframes: true, logger: logger);
|
||||||
var statsRule = new StatsRule();
|
var statsRule = new StatsRule();
|
||||||
var ffmpegDetectionRule = new FfmpegDetectionRule();
|
var ffmpegDetectionRule = new FfmpegDetectionRule();
|
||||||
var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).Add(statsRule).Add(ffmpegDetectionRule).AddDefault().AddRemoveFillerData().Build();
|
var pipeline = new ProcessingPipelineBuilder()
|
||||||
|
.ConfigureServices(services => services.AddSingleton(request.PipelineSettings ?? new ProcessingPipelineSettings()))
|
||||||
|
.AddRule(statsRule)
|
||||||
|
.AddRule(ffmpegDetectionRule)
|
||||||
|
.AddDefaultRules()
|
||||||
|
.AddRemoveFillerDataRule()
|
||||||
|
.Build();
|
||||||
|
|
||||||
// Run
|
// Run
|
||||||
await Task.Run(async () =>
|
await Task.Run(async () =>
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
namespace BililiveRecorder.ToolBox.Tool.Analyze
|
using BililiveRecorder.Flv.Pipeline;
|
||||||
|
|
||||||
|
namespace BililiveRecorder.ToolBox.Tool.Analyze
|
||||||
{
|
{
|
||||||
public class AnalyzeRequest : ICommandRequest<AnalyzeResponse>
|
public class AnalyzeRequest : ICommandRequest<AnalyzeResponse>
|
||||||
{
|
{
|
||||||
public string Input { get; set; } = string.Empty;
|
public string Input { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public ProcessingPipelineSettings? PipelineSettings { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,13 @@ namespace BililiveRecorder.ToolBox.Tool.Fix
|
||||||
using var writer = new FlvProcessingContextWriter(tagWriter: tagWriter, allowMissingHeader: true, disableKeyframes: false, logger: logger);
|
using var writer = new FlvProcessingContextWriter(tagWriter: tagWriter, allowMissingHeader: true, disableKeyframes: false, logger: logger);
|
||||||
var statsRule = new StatsRule();
|
var statsRule = new StatsRule();
|
||||||
var ffmpegDetectionRule = new FfmpegDetectionRule();
|
var ffmpegDetectionRule = new FfmpegDetectionRule();
|
||||||
var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).Add(statsRule).Add(ffmpegDetectionRule).AddDefault().AddRemoveFillerData().Build();
|
var pipeline = new ProcessingPipelineBuilder()
|
||||||
|
.ConfigureServices(services => services.AddSingleton(request.PipelineSettings ?? new ProcessingPipelineSettings()))
|
||||||
|
.AddRule(statsRule)
|
||||||
|
.AddRule(ffmpegDetectionRule)
|
||||||
|
.AddDefaultRules()
|
||||||
|
.AddRemoveFillerDataRule()
|
||||||
|
.Build();
|
||||||
|
|
||||||
// Run
|
// Run
|
||||||
await Task.Run(async () =>
|
await Task.Run(async () =>
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
namespace BililiveRecorder.ToolBox.Tool.Fix
|
using BililiveRecorder.Flv.Pipeline;
|
||||||
|
|
||||||
|
namespace BililiveRecorder.ToolBox.Tool.Fix
|
||||||
{
|
{
|
||||||
public class FixRequest : ICommandRequest<FixResponse>
|
public class FixRequest : ICommandRequest<FixResponse>
|
||||||
{
|
{
|
||||||
public string Input { get; set; } = string.Empty;
|
public string Input { get; set; } = string.Empty;
|
||||||
|
|
||||||
public string OutputBase { get; set; } = string.Empty;
|
public string OutputBase { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public ProcessingPipelineSettings? PipelineSettings { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.CommandLine;
|
using System.CommandLine;
|
||||||
using System.CommandLine.NamingConventionBinder;
|
using System.CommandLine.NamingConventionBinder;
|
||||||
|
using System.CommandLine.Parsing;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BililiveRecorder.Flv.Pipeline;
|
||||||
using BililiveRecorder.ToolBox.Tool.Analyze;
|
using BililiveRecorder.ToolBox.Tool.Analyze;
|
||||||
using BililiveRecorder.ToolBox.Tool.DanmakuMerger;
|
using BililiveRecorder.ToolBox.Tool.DanmakuMerger;
|
||||||
using BililiveRecorder.ToolBox.Tool.DanmakuStartTime;
|
using BililiveRecorder.ToolBox.Tool.DanmakuStartTime;
|
||||||
|
@ -19,12 +22,14 @@ namespace BililiveRecorder.ToolBox
|
||||||
this.RegisterCommand<AnalyzeHandler, AnalyzeRequest, AnalyzeResponse>("analyze", null, c =>
|
this.RegisterCommand<AnalyzeHandler, AnalyzeRequest, AnalyzeResponse>("analyze", null, c =>
|
||||||
{
|
{
|
||||||
c.Add(new Argument<string>("input", "example: input.flv"));
|
c.Add(new Argument<string>("input", "example: input.flv"));
|
||||||
|
c.Add(new Option<ProcessingPipelineSettings?>(name: "pipeline-settings", parseArgument: this.ParseProcessingPipelineSettings));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.RegisterCommand<FixHandler, FixRequest, FixResponse>("fix", null, c =>
|
this.RegisterCommand<FixHandler, FixRequest, FixResponse>("fix", null, c =>
|
||||||
{
|
{
|
||||||
c.Add(new Argument<string>("input", "example: input.flv"));
|
c.Add(new Argument<string>("input", "example: input.flv"));
|
||||||
c.Add(new Argument<string>("output-base", "example: output.flv"));
|
c.Add(new Argument<string>("output-base", "example: output.flv"));
|
||||||
|
c.Add(new Option<ProcessingPipelineSettings?>(name: "pipeline-settings", parseArgument: this.ParseProcessingPipelineSettings));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.RegisterCommand<ExportHandler, ExportRequest, ExportResponse>("export", null, c =>
|
this.RegisterCommand<ExportHandler, ExportRequest, ExportResponse>("export", null, c =>
|
||||||
|
@ -46,6 +51,21 @@ namespace BililiveRecorder.ToolBox
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ProcessingPipelineSettings? ParseProcessingPipelineSettings(ArgumentResult result)
|
||||||
|
{
|
||||||
|
if (result.Tokens.Count == 0) return null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return JsonConvert.DeserializeObject<ProcessingPipelineSettings>(result.Tokens.Single().Value);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
result.ErrorMessage = "Pipeline settings must be a valid json string";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void RegisterCommand<THandler, TRequest, TResponse>(string name, string? description, Action<Command> configure)
|
private void RegisterCommand<THandler, TRequest, TResponse>(string name, string? description, Action<Command> configure)
|
||||||
where THandler : ICommandHandler<TRequest, TResponse>
|
where THandler : ICommandHandler<TRequest, TResponse>
|
||||||
where TRequest : ICommandRequest<TResponse>
|
where TRequest : ICommandRequest<TResponse>
|
||||||
|
|
|
@ -61,6 +61,15 @@
|
||||||
</local:SettingWithDefault>
|
</local:SettingWithDefault>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
|
<GroupBox Header="标准模式录制修复设置">
|
||||||
|
<StackPanel>
|
||||||
|
<local:SettingWithDefault IsSettingNotUsingDefault="{Binding HasFlvProcessorSplitOnScriptTag}">
|
||||||
|
<StackPanel>
|
||||||
|
<ui:ToggleSwitch IsOn="{Binding FlvProcessorSplitOnScriptTag}" OnContent="检测到可能缺少数据时分段" OffContent="检测到可能缺少数据时分段"/>
|
||||||
|
</StackPanel>
|
||||||
|
</local:SettingWithDefault>
|
||||||
|
</StackPanel>
|
||||||
|
</GroupBox>
|
||||||
<GroupBox Header="{l:Loc Settings_Splitting_Title}">
|
<GroupBox Header="{l:Loc Settings_Splitting_Title}">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<local:SettingWithDefault IsSettingNotUsingDefault="{Binding HasCuttingMode}">
|
<local:SettingWithDefault IsSettingNotUsingDefault="{Binding HasCuttingMode}">
|
||||||
|
|
|
@ -52,6 +52,11 @@
|
||||||
ConverterParameter={x:Static config:RecordMode.RawData}}" />
|
ConverterParameter={x:Static config:RecordMode.RawData}}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
|
<GroupBox Header="标准模式录制修复设置">
|
||||||
|
<StackPanel>
|
||||||
|
<ui:ToggleSwitch IsOn="{Binding FlvProcessorSplitOnScriptTag}" OnContent="检测到可能缺少数据时分段" OffContent="检测到可能缺少数据时分段"/>
|
||||||
|
</StackPanel>
|
||||||
|
</GroupBox>
|
||||||
<GroupBox Header="{l:Loc Settings_Splitting_Title}">
|
<GroupBox Header="{l:Loc Settings_Splitting_Title}">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<RadioButton GroupName="Splitting" Name="CutDisabledRadioButton" Content="{l:Loc Settings_Splitting_RadioButton_Disabled}"
|
<RadioButton GroupName="Splitting" Name="CutDisabledRadioButton" Content="{l:Loc Settings_Splitting_RadioButton_Disabled}"
|
||||||
|
|
|
@ -52,6 +52,21 @@
|
||||||
<TextBlock Text="{l:Loc Toolbox_AutoFix_ButtonAnalyze}"/>
|
<TextBlock Text="{l:Loc Toolbox_AutoFix_ButtonAnalyze}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button VerticalAlignment="Bottom" DockPanel.Dock="Right" Margin="0,0,5,0">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<ui:PathIcon Height="14" Margin="0,0,5,0" Style="{StaticResource PathIconDataCogOutline}"/>
|
||||||
|
<TextBlock Text="设置"/>
|
||||||
|
</StackPanel>
|
||||||
|
<ui:FlyoutService.Flyout>
|
||||||
|
<ui:Flyout Placement="Bottom">
|
||||||
|
<Grid DataContext="{x:Null}" x:Name="SettingsArea">
|
||||||
|
<StackPanel Margin="10" Orientation="Vertical">
|
||||||
|
<CheckBox Content="检测到可能缺少数据时分段" IsChecked="{Binding SplitOnScriptTag}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</ui:Flyout>
|
||||||
|
</ui:FlyoutService.Flyout>
|
||||||
|
</Button>
|
||||||
<Button VerticalAlignment="Bottom" DockPanel.Dock="Right" Margin="0,0,5,0" Content="{l:Loc Toolbox_AutoFix_ButtonSelectInput}" Click="SelectFile_Button_Click"/>
|
<Button VerticalAlignment="Bottom" DockPanel.Dock="Right" Margin="0,0,5,0" Content="{l:Loc Toolbox_AutoFix_ButtonSelectInput}" Click="SelectFile_Button_Click"/>
|
||||||
<TextBox ui:ControlHelper.PlaceholderText="{l:Loc Toolbox_AutoFix_InputPathPlaceholder}" ui:TextBoxHelper.IsDeleteButtonVisible="False" x:Name="FileNameTextBox" />
|
<TextBox ui:ControlHelper.PlaceholderText="{l:Loc Toolbox_AutoFix_InputPathPlaceholder}" ui:TextBoxHelper.IsDeleteButtonVisible="False" x:Name="FileNameTextBox" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
@ -23,9 +26,13 @@ namespace BililiveRecorder.WPF.Pages
|
||||||
private static readonly ILogger logger = Log.ForContext<ToolboxAutoFixPage>();
|
private static readonly ILogger logger = Log.ForContext<ToolboxAutoFixPage>();
|
||||||
private readonly SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
|
private readonly AutoFixSettings settings = new AutoFixSettings();
|
||||||
|
|
||||||
public ToolboxAutoFixPage()
|
public ToolboxAutoFixPage()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
this.InitializeComponent();
|
||||||
|
|
||||||
|
this.SettingsArea.DataContext = this.settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SelectFile_Button_Click(object sender, RoutedEventArgs e)
|
private void SelectFile_Button_Click(object sender, RoutedEventArgs e)
|
||||||
|
@ -104,6 +111,10 @@ namespace BililiveRecorder.WPF.Pages
|
||||||
{
|
{
|
||||||
Input = inputPath,
|
Input = inputPath,
|
||||||
OutputBase = output_path,
|
OutputBase = output_path,
|
||||||
|
PipelineSettings = new Flv.Pipeline.ProcessingPipelineSettings
|
||||||
|
{
|
||||||
|
SplitOnScriptTag = this.settings.SplitOnScriptTag
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var handler = new FixHandler();
|
var handler = new FixHandler();
|
||||||
|
@ -179,7 +190,11 @@ namespace BililiveRecorder.WPF.Pages
|
||||||
|
|
||||||
var req = new AnalyzeRequest
|
var req = new AnalyzeRequest
|
||||||
{
|
{
|
||||||
Input = inputPath
|
Input = inputPath,
|
||||||
|
PipelineSettings = new Flv.Pipeline.ProcessingPipelineSettings
|
||||||
|
{
|
||||||
|
SplitOnScriptTag = this.settings.SplitOnScriptTag
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var handler = new AnalyzeHandler();
|
var handler = new AnalyzeHandler();
|
||||||
|
@ -331,5 +346,25 @@ namespace BililiveRecorder.WPF.Pages
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class AutoFixSettings : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
private bool splitOnScriptTag;
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
private bool SetField<T>(ref T location, T value, [CallerMemberName] string propertyName = "")
|
||||||
|
{
|
||||||
|
if (EqualityComparer<T>.Default.Equals(location, value))
|
||||||
|
return false;
|
||||||
|
location = value;
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// FLV修复-检测到可能缺少数据时分段
|
||||||
|
/// </summary>
|
||||||
|
public bool SplitOnScriptTag { get => this.splitOnScriptTag; set => this.SetField(ref this.splitOnScriptTag, value); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace BililiveRecorder.Web.Models
|
||||||
public Optional<bool>? OptionalRecordDanmakuGift { get; set; }
|
public Optional<bool>? OptionalRecordDanmakuGift { get; set; }
|
||||||
public Optional<bool>? OptionalRecordDanmakuGuard { get; set; }
|
public Optional<bool>? OptionalRecordDanmakuGuard { get; set; }
|
||||||
public Optional<string?>? OptionalRecordingQuality { get; set; }
|
public Optional<string?>? OptionalRecordingQuality { get; set; }
|
||||||
|
public Optional<bool>? OptionalFlvProcessorSplitOnScriptTag { get; set; }
|
||||||
|
|
||||||
public void ApplyTo(RoomConfig config)
|
public void ApplyTo(RoomConfig config)
|
||||||
{
|
{
|
||||||
|
@ -35,6 +36,7 @@ namespace BililiveRecorder.Web.Models
|
||||||
if (this.OptionalRecordDanmakuGift.HasValue) config.OptionalRecordDanmakuGift = this.OptionalRecordDanmakuGift.Value;
|
if (this.OptionalRecordDanmakuGift.HasValue) config.OptionalRecordDanmakuGift = this.OptionalRecordDanmakuGift.Value;
|
||||||
if (this.OptionalRecordDanmakuGuard.HasValue) config.OptionalRecordDanmakuGuard = this.OptionalRecordDanmakuGuard.Value;
|
if (this.OptionalRecordDanmakuGuard.HasValue) config.OptionalRecordDanmakuGuard = this.OptionalRecordDanmakuGuard.Value;
|
||||||
if (this.OptionalRecordingQuality.HasValue) config.OptionalRecordingQuality = this.OptionalRecordingQuality.Value;
|
if (this.OptionalRecordingQuality.HasValue) config.OptionalRecordingQuality = this.OptionalRecordingQuality.Value;
|
||||||
|
if (this.OptionalFlvProcessorSplitOnScriptTag.HasValue) config.OptionalFlvProcessorSplitOnScriptTag = this.OptionalFlvProcessorSplitOnScriptTag.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +52,7 @@ namespace BililiveRecorder.Web.Models
|
||||||
public Optional<bool>? OptionalRecordDanmakuGuard { get; set; }
|
public Optional<bool>? OptionalRecordDanmakuGuard { get; set; }
|
||||||
public Optional<string?>? OptionalRecordingQuality { get; set; }
|
public Optional<string?>? OptionalRecordingQuality { get; set; }
|
||||||
public Optional<string?>? OptionalFileNameRecordTemplate { get; set; }
|
public Optional<string?>? OptionalFileNameRecordTemplate { get; set; }
|
||||||
|
public Optional<bool>? OptionalFlvProcessorSplitOnScriptTag { get; set; }
|
||||||
public Optional<string?>? OptionalWebHookUrls { get; set; }
|
public Optional<string?>? OptionalWebHookUrls { get; set; }
|
||||||
public Optional<string?>? OptionalWebHookUrlsV2 { get; set; }
|
public Optional<string?>? OptionalWebHookUrlsV2 { get; set; }
|
||||||
public Optional<bool>? OptionalWpfShowTitleAndArea { get; set; }
|
public Optional<bool>? OptionalWpfShowTitleAndArea { get; set; }
|
||||||
|
@ -78,6 +81,7 @@ namespace BililiveRecorder.Web.Models
|
||||||
if (this.OptionalRecordDanmakuGuard.HasValue) config.OptionalRecordDanmakuGuard = this.OptionalRecordDanmakuGuard.Value;
|
if (this.OptionalRecordDanmakuGuard.HasValue) config.OptionalRecordDanmakuGuard = this.OptionalRecordDanmakuGuard.Value;
|
||||||
if (this.OptionalRecordingQuality.HasValue) config.OptionalRecordingQuality = this.OptionalRecordingQuality.Value;
|
if (this.OptionalRecordingQuality.HasValue) config.OptionalRecordingQuality = this.OptionalRecordingQuality.Value;
|
||||||
if (this.OptionalFileNameRecordTemplate.HasValue) config.OptionalFileNameRecordTemplate = this.OptionalFileNameRecordTemplate.Value;
|
if (this.OptionalFileNameRecordTemplate.HasValue) config.OptionalFileNameRecordTemplate = this.OptionalFileNameRecordTemplate.Value;
|
||||||
|
if (this.OptionalFlvProcessorSplitOnScriptTag.HasValue) config.OptionalFlvProcessorSplitOnScriptTag = this.OptionalFlvProcessorSplitOnScriptTag.Value;
|
||||||
if (this.OptionalWebHookUrls.HasValue) config.OptionalWebHookUrls = this.OptionalWebHookUrls.Value;
|
if (this.OptionalWebHookUrls.HasValue) config.OptionalWebHookUrls = this.OptionalWebHookUrls.Value;
|
||||||
if (this.OptionalWebHookUrlsV2.HasValue) config.OptionalWebHookUrlsV2 = this.OptionalWebHookUrlsV2.Value;
|
if (this.OptionalWebHookUrlsV2.HasValue) config.OptionalWebHookUrlsV2 = this.OptionalWebHookUrlsV2.Value;
|
||||||
if (this.OptionalWpfShowTitleAndArea.HasValue) config.OptionalWpfShowTitleAndArea = this.OptionalWpfShowTitleAndArea.Value;
|
if (this.OptionalWpfShowTitleAndArea.HasValue) config.OptionalWpfShowTitleAndArea = this.OptionalWpfShowTitleAndArea.Value;
|
||||||
|
@ -112,6 +116,7 @@ namespace BililiveRecorder.Web.Models.Rest
|
||||||
public Optional<bool> OptionalRecordDanmakuGift { get; set; }
|
public Optional<bool> OptionalRecordDanmakuGift { get; set; }
|
||||||
public Optional<bool> OptionalRecordDanmakuGuard { get; set; }
|
public Optional<bool> OptionalRecordDanmakuGuard { get; set; }
|
||||||
public Optional<string?> OptionalRecordingQuality { get; set; }
|
public Optional<string?> OptionalRecordingQuality { get; set; }
|
||||||
|
public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GlobalConfigDto
|
public class GlobalConfigDto
|
||||||
|
@ -126,6 +131,7 @@ namespace BililiveRecorder.Web.Models.Rest
|
||||||
public Optional<bool> OptionalRecordDanmakuGuard { get; set; }
|
public Optional<bool> OptionalRecordDanmakuGuard { get; set; }
|
||||||
public Optional<string?> OptionalRecordingQuality { get; set; }
|
public Optional<string?> OptionalRecordingQuality { get; set; }
|
||||||
public Optional<string?> OptionalFileNameRecordTemplate { get; set; }
|
public Optional<string?> OptionalFileNameRecordTemplate { get; set; }
|
||||||
|
public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get; set; }
|
||||||
public Optional<string?> OptionalWebHookUrls { get; set; }
|
public Optional<string?> OptionalWebHookUrls { get; set; }
|
||||||
public Optional<string?> OptionalWebHookUrlsV2 { get; set; }
|
public Optional<string?> OptionalWebHookUrlsV2 { get; set; }
|
||||||
public Optional<bool> OptionalWpfShowTitleAndArea { get; set; }
|
public Optional<bool> OptionalWpfShowTitleAndArea { get; set; }
|
||||||
|
@ -162,6 +168,7 @@ namespace BililiveRecorder.Web.Models.Graphql
|
||||||
this.Field(x => x.OptionalRecordDanmakuGift, type: typeof(HierarchicalOptionalType<bool>));
|
this.Field(x => x.OptionalRecordDanmakuGift, type: typeof(HierarchicalOptionalType<bool>));
|
||||||
this.Field(x => x.OptionalRecordDanmakuGuard, type: typeof(HierarchicalOptionalType<bool>));
|
this.Field(x => x.OptionalRecordDanmakuGuard, type: typeof(HierarchicalOptionalType<bool>));
|
||||||
this.Field(x => x.OptionalRecordingQuality, type: typeof(HierarchicalOptionalType<string>));
|
this.Field(x => x.OptionalRecordingQuality, type: typeof(HierarchicalOptionalType<string>));
|
||||||
|
this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, type: typeof(HierarchicalOptionalType<bool>));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,6 +186,7 @@ namespace BililiveRecorder.Web.Models.Graphql
|
||||||
this.Field(x => x.OptionalRecordDanmakuGuard, type: typeof(HierarchicalOptionalType<bool>));
|
this.Field(x => x.OptionalRecordDanmakuGuard, type: typeof(HierarchicalOptionalType<bool>));
|
||||||
this.Field(x => x.OptionalRecordingQuality, type: typeof(HierarchicalOptionalType<string>));
|
this.Field(x => x.OptionalRecordingQuality, type: typeof(HierarchicalOptionalType<string>));
|
||||||
this.Field(x => x.OptionalFileNameRecordTemplate, type: typeof(HierarchicalOptionalType<string>));
|
this.Field(x => x.OptionalFileNameRecordTemplate, type: typeof(HierarchicalOptionalType<string>));
|
||||||
|
this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, type: typeof(HierarchicalOptionalType<bool>));
|
||||||
this.Field(x => x.OptionalWebHookUrls, type: typeof(HierarchicalOptionalType<string>));
|
this.Field(x => x.OptionalWebHookUrls, type: typeof(HierarchicalOptionalType<string>));
|
||||||
this.Field(x => x.OptionalWebHookUrlsV2, type: typeof(HierarchicalOptionalType<string>));
|
this.Field(x => x.OptionalWebHookUrlsV2, type: typeof(HierarchicalOptionalType<string>));
|
||||||
this.Field(x => x.OptionalWpfShowTitleAndArea, type: typeof(HierarchicalOptionalType<bool>));
|
this.Field(x => x.OptionalWpfShowTitleAndArea, type: typeof(HierarchicalOptionalType<bool>));
|
||||||
|
@ -211,6 +219,7 @@ namespace BililiveRecorder.Web.Models.Graphql
|
||||||
this.Field(x => x.RecordDanmakuGuard);
|
this.Field(x => x.RecordDanmakuGuard);
|
||||||
this.Field(x => x.RecordingQuality);
|
this.Field(x => x.RecordingQuality);
|
||||||
this.Field(x => x.FileNameRecordTemplate);
|
this.Field(x => x.FileNameRecordTemplate);
|
||||||
|
this.Field(x => x.FlvProcessorSplitOnScriptTag);
|
||||||
this.Field(x => x.WebHookUrls);
|
this.Field(x => x.WebHookUrls);
|
||||||
this.Field(x => x.WebHookUrlsV2);
|
this.Field(x => x.WebHookUrlsV2);
|
||||||
this.Field(x => x.WpfShowTitleAndArea);
|
this.Field(x => x.WpfShowTitleAndArea);
|
||||||
|
@ -243,6 +252,7 @@ namespace BililiveRecorder.Web.Models.Graphql
|
||||||
this.Field(x => x.OptionalRecordDanmakuGift, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
|
this.Field(x => x.OptionalRecordDanmakuGift, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
|
||||||
this.Field(x => x.OptionalRecordDanmakuGuard, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
|
this.Field(x => x.OptionalRecordDanmakuGuard, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
|
||||||
this.Field(x => x.OptionalRecordingQuality, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
|
this.Field(x => x.OptionalRecordingQuality, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
|
||||||
|
this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,6 +270,7 @@ namespace BililiveRecorder.Web.Models.Graphql
|
||||||
this.Field(x => x.OptionalRecordDanmakuGuard, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
|
this.Field(x => x.OptionalRecordDanmakuGuard, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
|
||||||
this.Field(x => x.OptionalRecordingQuality, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
|
this.Field(x => x.OptionalRecordingQuality, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
|
||||||
this.Field(x => x.OptionalFileNameRecordTemplate, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
|
this.Field(x => x.OptionalFileNameRecordTemplate, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
|
||||||
|
this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
|
||||||
this.Field(x => x.OptionalWebHookUrls, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
|
this.Field(x => x.OptionalWebHookUrls, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
|
||||||
this.Field(x => x.OptionalWebHookUrlsV2, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
|
this.Field(x => x.OptionalWebHookUrlsV2, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
|
||||||
this.Field(x => x.OptionalWpfShowTitleAndArea, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
|
this.Field(x => x.OptionalWpfShowTitleAndArea, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
|
||||||
|
|
|
@ -440,6 +440,22 @@
|
||||||
"default": "10000"
|
"default": "10000"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"FlvProcessorSplitOnScriptTag": {
|
||||||
|
"description": "FLV修复-检测到可能缺少数据时分段\n默认: false",
|
||||||
|
"markdownDescription": "FLV修复-检测到可能缺少数据时分段 \n默认: `false `\n\n",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"HasValue": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -637,6 +653,22 @@
|
||||||
"default": "10000"
|
"default": "10000"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"FlvProcessorSplitOnScriptTag": {
|
||||||
|
"description": "FLV修复-检测到可能缺少数据时分段\n默认: false",
|
||||||
|
"markdownDescription": "FLV修复-检测到可能缺少数据时分段 \n默认: `false `\n\n",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"HasValue": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,13 @@ export const data: Array<ConfigEntry> = [
|
||||||
configType: "globalOnly",
|
configType: "globalOnly",
|
||||||
default: '{{ roomId }}-{{ name }}/录制-{{ roomId }}-{{ "now" | time_zone: "Asia/Shanghai" | format_date: "yyyyMMdd-HHmmss-fff" }}-{{ title }}.flv',
|
default: '{{ roomId }}-{{ name }}/录制-{{ roomId }}-{{ "now" | time_zone: "Asia/Shanghai" | format_date: "yyyyMMdd-HHmmss-fff" }}-{{ title }}.flv',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "FlvProcessorSplitOnScriptTag",
|
||||||
|
name: "FLV修复-检测到可能缺少数据时分段",
|
||||||
|
type: "bool",
|
||||||
|
configType: "room",
|
||||||
|
default: false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "WebHookUrls",
|
id: "WebHookUrls",
|
||||||
name: "WebhookV1",
|
name: "WebhookV1",
|
||||||
|
|
|
@ -68,6 +68,7 @@ namespace BililiveRecorder.Core.Config.V3
|
||||||
public BililiveRecorder.Core.Config.CuttingMode CuttingMode { get; }
|
public BililiveRecorder.Core.Config.CuttingMode CuttingMode { get; }
|
||||||
public uint CuttingNumber { get; }
|
public uint CuttingNumber { get; }
|
||||||
public string FileNameRecordTemplate { get; }
|
public string FileNameRecordTemplate { get; }
|
||||||
|
public bool FlvProcessorSplitOnScriptTag { get; }
|
||||||
public string LiveApiHost { get; }
|
public string LiveApiHost { get; }
|
||||||
public BililiveRecorder.Core.Config.AllowedAddressFamily NetworkTransportAllowedAddressFamily { get; }
|
public BililiveRecorder.Core.Config.AllowedAddressFamily NetworkTransportAllowedAddressFamily { get; }
|
||||||
public bool NetworkTransportUseSystemProxy { get; }
|
public bool NetworkTransportUseSystemProxy { get; }
|
||||||
|
@ -98,10 +99,12 @@ namespace BililiveRecorder.Core.Config.V3
|
||||||
public BililiveRecorder.Core.Config.CuttingMode CuttingMode { get; set; }
|
public BililiveRecorder.Core.Config.CuttingMode CuttingMode { get; set; }
|
||||||
public uint CuttingNumber { get; set; }
|
public uint CuttingNumber { get; set; }
|
||||||
public string? FileNameRecordTemplate { get; set; }
|
public string? FileNameRecordTemplate { get; set; }
|
||||||
|
public bool FlvProcessorSplitOnScriptTag { get; set; }
|
||||||
public bool HasCookie { get; set; }
|
public bool HasCookie { get; set; }
|
||||||
public bool HasCuttingMode { get; set; }
|
public bool HasCuttingMode { get; set; }
|
||||||
public bool HasCuttingNumber { get; set; }
|
public bool HasCuttingNumber { get; set; }
|
||||||
public bool HasFileNameRecordTemplate { get; set; }
|
public bool HasFileNameRecordTemplate { get; set; }
|
||||||
|
public bool HasFlvProcessorSplitOnScriptTag { get; set; }
|
||||||
public bool HasLiveApiHost { get; set; }
|
public bool HasLiveApiHost { get; set; }
|
||||||
public bool HasNetworkTransportAllowedAddressFamily { get; set; }
|
public bool HasNetworkTransportAllowedAddressFamily { get; set; }
|
||||||
public bool HasNetworkTransportUseSystemProxy { get; set; }
|
public bool HasNetworkTransportUseSystemProxy { get; set; }
|
||||||
|
@ -134,6 +137,8 @@ namespace BililiveRecorder.Core.Config.V3
|
||||||
public HierarchicalPropertyDefault.Optional<uint> OptionalCuttingNumber { get; set; }
|
public HierarchicalPropertyDefault.Optional<uint> OptionalCuttingNumber { get; set; }
|
||||||
[Newtonsoft.Json.JsonProperty("FileNameRecordTemplate")]
|
[Newtonsoft.Json.JsonProperty("FileNameRecordTemplate")]
|
||||||
public HierarchicalPropertyDefault.Optional<string?> OptionalFileNameRecordTemplate { get; set; }
|
public HierarchicalPropertyDefault.Optional<string?> OptionalFileNameRecordTemplate { get; set; }
|
||||||
|
[Newtonsoft.Json.JsonProperty("FlvProcessorSplitOnScriptTag")]
|
||||||
|
public HierarchicalPropertyDefault.Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get; set; }
|
||||||
[Newtonsoft.Json.JsonProperty("LiveApiHost")]
|
[Newtonsoft.Json.JsonProperty("LiveApiHost")]
|
||||||
public HierarchicalPropertyDefault.Optional<string?> OptionalLiveApiHost { get; set; }
|
public HierarchicalPropertyDefault.Optional<string?> OptionalLiveApiHost { get; set; }
|
||||||
[Newtonsoft.Json.JsonProperty("NetworkTransportAllowedAddressFamily")]
|
[Newtonsoft.Json.JsonProperty("NetworkTransportAllowedAddressFamily")]
|
||||||
|
@ -205,9 +210,11 @@ namespace BililiveRecorder.Core.Config.V3
|
||||||
public BililiveRecorder.Core.Config.CuttingMode CuttingMode { get; set; }
|
public BililiveRecorder.Core.Config.CuttingMode CuttingMode { get; set; }
|
||||||
public uint CuttingNumber { get; set; }
|
public uint CuttingNumber { get; set; }
|
||||||
public string? FileNameRecordTemplate { get; }
|
public string? FileNameRecordTemplate { get; }
|
||||||
|
public bool FlvProcessorSplitOnScriptTag { get; set; }
|
||||||
public bool HasAutoRecord { get; set; }
|
public bool HasAutoRecord { get; set; }
|
||||||
public bool HasCuttingMode { get; set; }
|
public bool HasCuttingMode { get; set; }
|
||||||
public bool HasCuttingNumber { get; set; }
|
public bool HasCuttingNumber { get; set; }
|
||||||
|
public bool HasFlvProcessorSplitOnScriptTag { get; set; }
|
||||||
public bool HasRecordDanmaku { get; set; }
|
public bool HasRecordDanmaku { get; set; }
|
||||||
public bool HasRecordDanmakuGift { get; set; }
|
public bool HasRecordDanmakuGift { get; set; }
|
||||||
public bool HasRecordDanmakuGuard { get; set; }
|
public bool HasRecordDanmakuGuard { get; set; }
|
||||||
|
@ -225,6 +232,8 @@ namespace BililiveRecorder.Core.Config.V3
|
||||||
public HierarchicalPropertyDefault.Optional<BililiveRecorder.Core.Config.CuttingMode> OptionalCuttingMode { get; set; }
|
public HierarchicalPropertyDefault.Optional<BililiveRecorder.Core.Config.CuttingMode> OptionalCuttingMode { get; set; }
|
||||||
[Newtonsoft.Json.JsonProperty("CuttingNumber")]
|
[Newtonsoft.Json.JsonProperty("CuttingNumber")]
|
||||||
public HierarchicalPropertyDefault.Optional<uint> OptionalCuttingNumber { get; set; }
|
public HierarchicalPropertyDefault.Optional<uint> OptionalCuttingNumber { get; set; }
|
||||||
|
[Newtonsoft.Json.JsonProperty("FlvProcessorSplitOnScriptTag")]
|
||||||
|
public HierarchicalPropertyDefault.Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get; set; }
|
||||||
[Newtonsoft.Json.JsonProperty("RecordDanmaku")]
|
[Newtonsoft.Json.JsonProperty("RecordDanmaku")]
|
||||||
public HierarchicalPropertyDefault.Optional<bool> OptionalRecordDanmaku { get; set; }
|
public HierarchicalPropertyDefault.Optional<bool> OptionalRecordDanmaku { get; set; }
|
||||||
[Newtonsoft.Json.JsonProperty("RecordDanmakuGift")]
|
[Newtonsoft.Json.JsonProperty("RecordDanmakuGift")]
|
||||||
|
|
|
@ -725,18 +725,19 @@ namespace BililiveRecorder.Flv.Pipeline
|
||||||
}
|
}
|
||||||
public interface IProcessingPipelineBuilder
|
public interface IProcessingPipelineBuilder
|
||||||
{
|
{
|
||||||
System.IServiceProvider ServiceProvider { get; }
|
Microsoft.Extensions.DependencyInjection.IServiceCollection ServiceCollection { get; }
|
||||||
BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder Add(System.Func<BililiveRecorder.Flv.Pipeline.ProcessingDelegate, BililiveRecorder.Flv.Pipeline.ProcessingDelegate> rule);
|
BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder AddRule(System.Func<BililiveRecorder.Flv.Pipeline.ProcessingDelegate, System.IServiceProvider, BililiveRecorder.Flv.Pipeline.ProcessingDelegate> rule);
|
||||||
BililiveRecorder.Flv.Pipeline.ProcessingDelegate Build();
|
BililiveRecorder.Flv.Pipeline.ProcessingDelegate Build();
|
||||||
}
|
}
|
||||||
public static class IProcessingPipelineBuilderExtensions
|
public static class IProcessingPipelineBuilderExtensions
|
||||||
{
|
{
|
||||||
public static BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder Add<T>(this BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder builder)
|
public static BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder AddDefaultRules(this BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder builder) { }
|
||||||
|
public static BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder AddRemoveFillerDataRule(this BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder builder) { }
|
||||||
|
public static BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder AddRule<T>(this BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder builder)
|
||||||
where T : BililiveRecorder.Flv.Pipeline.IProcessingRule { }
|
where T : BililiveRecorder.Flv.Pipeline.IProcessingRule { }
|
||||||
public static BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder Add<T>(this BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder builder, T instance)
|
public static BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder AddRule<T>(this BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder builder, T instance)
|
||||||
where T : BililiveRecorder.Flv.Pipeline.IProcessingRule { }
|
where T : BililiveRecorder.Flv.Pipeline.IProcessingRule { }
|
||||||
public static BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder AddDefault(this BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder builder) { }
|
public static BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder ConfigureServices(this BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder builder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection> configure) { }
|
||||||
public static BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder AddRemoveFillerData(this BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder builder) { }
|
|
||||||
}
|
}
|
||||||
public interface IProcessingRule { }
|
public interface IProcessingRule { }
|
||||||
public interface ISimpleProcessingRule : BililiveRecorder.Flv.Pipeline.IProcessingRule
|
public interface ISimpleProcessingRule : BililiveRecorder.Flv.Pipeline.IProcessingRule
|
||||||
|
@ -754,11 +755,17 @@ namespace BililiveRecorder.Flv.Pipeline
|
||||||
public delegate void ProcessingDelegate(BililiveRecorder.Flv.Pipeline.FlvProcessingContext context);
|
public delegate void ProcessingDelegate(BililiveRecorder.Flv.Pipeline.FlvProcessingContext context);
|
||||||
public class ProcessingPipelineBuilder : BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder
|
public class ProcessingPipelineBuilder : BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder
|
||||||
{
|
{
|
||||||
public ProcessingPipelineBuilder(System.IServiceProvider serviceProvider) { }
|
public ProcessingPipelineBuilder() { }
|
||||||
public System.IServiceProvider ServiceProvider { get; }
|
public ProcessingPipelineBuilder(Microsoft.Extensions.DependencyInjection.IServiceCollection servicesCollection) { }
|
||||||
public BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder Add(System.Func<BililiveRecorder.Flv.Pipeline.ProcessingDelegate, BililiveRecorder.Flv.Pipeline.ProcessingDelegate> rule) { }
|
public Microsoft.Extensions.DependencyInjection.IServiceCollection ServiceCollection { get; }
|
||||||
|
public BililiveRecorder.Flv.Pipeline.IProcessingPipelineBuilder AddRule(System.Func<BililiveRecorder.Flv.Pipeline.ProcessingDelegate, System.IServiceProvider, BililiveRecorder.Flv.Pipeline.ProcessingDelegate> rule) { }
|
||||||
public BililiveRecorder.Flv.Pipeline.ProcessingDelegate Build() { }
|
public BililiveRecorder.Flv.Pipeline.ProcessingDelegate Build() { }
|
||||||
}
|
}
|
||||||
|
public class ProcessingPipelineSettings
|
||||||
|
{
|
||||||
|
public ProcessingPipelineSettings() { }
|
||||||
|
public bool SplitOnScriptTag { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
namespace BililiveRecorder.Flv.Pipeline.Rules
|
namespace BililiveRecorder.Flv.Pipeline.Rules
|
||||||
{
|
{
|
||||||
|
@ -786,7 +793,7 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
|
||||||
}
|
}
|
||||||
public class HandleNewScriptRule : BililiveRecorder.Flv.Pipeline.IProcessingRule, BililiveRecorder.Flv.Pipeline.ISimpleProcessingRule
|
public class HandleNewScriptRule : BililiveRecorder.Flv.Pipeline.IProcessingRule, BililiveRecorder.Flv.Pipeline.ISimpleProcessingRule
|
||||||
{
|
{
|
||||||
public HandleNewScriptRule() { }
|
public HandleNewScriptRule(BililiveRecorder.Flv.Pipeline.ProcessingPipelineSettings? processingPipelineSettings) { }
|
||||||
public void Run(BililiveRecorder.Flv.Pipeline.FlvProcessingContext context, System.Action next) { }
|
public void Run(BililiveRecorder.Flv.Pipeline.FlvProcessingContext context, System.Action next) { }
|
||||||
}
|
}
|
||||||
public class RemoveDuplicatedChunkRule : BililiveRecorder.Flv.Pipeline.IProcessingRule, BililiveRecorder.Flv.Pipeline.ISimpleProcessingRule
|
public class RemoveDuplicatedChunkRule : BililiveRecorder.Flv.Pipeline.IProcessingRule, BililiveRecorder.Flv.Pipeline.ISimpleProcessingRule
|
||||||
|
|
|
@ -4,7 +4,6 @@ using BililiveRecorder.Flv.Amf;
|
||||||
using BililiveRecorder.Flv.Pipeline;
|
using BililiveRecorder.Flv.Pipeline;
|
||||||
using BililiveRecorder.Flv.Pipeline.Actions;
|
using BililiveRecorder.Flv.Pipeline.Actions;
|
||||||
using BililiveRecorder.Flv.Pipeline.Rules;
|
using BililiveRecorder.Flv.Pipeline.Rules;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace BililiveRecorder.Flv.Tests.RuleTests
|
namespace BililiveRecorder.Flv.Tests.RuleTests
|
||||||
|
@ -16,7 +15,7 @@ namespace BililiveRecorder.Flv.Tests.RuleTests
|
||||||
public void ShouldDetectEndTag(bool expectEndTag, PipelineAction pipelineAction)
|
public void ShouldDetectEndTag(bool expectEndTag, PipelineAction pipelineAction)
|
||||||
{
|
{
|
||||||
var rule = new FfmpegDetectionRule();
|
var rule = new FfmpegDetectionRule();
|
||||||
var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).Add(rule).Build();
|
var pipeline = new ProcessingPipelineBuilder().AddRule(rule).Build();
|
||||||
|
|
||||||
var context = new FlvProcessingContext(pipelineAction, new Dictionary<object, object?>());
|
var context = new FlvProcessingContext(pipelineAction, new Dictionary<object, object?>());
|
||||||
|
|
||||||
|
@ -46,7 +45,7 @@ namespace BililiveRecorder.Flv.Tests.RuleTests
|
||||||
public void ShouldDetectLvafEncoder(bool expectedValue, string metadataJson)
|
public void ShouldDetectLvafEncoder(bool expectedValue, string metadataJson)
|
||||||
{
|
{
|
||||||
var rule = new FfmpegDetectionRule();
|
var rule = new FfmpegDetectionRule();
|
||||||
var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).Add(rule).Build();
|
var pipeline = new ProcessingPipelineBuilder().AddRule(rule).Build();
|
||||||
|
|
||||||
var action = new PipelineScriptAction(new Tag
|
var action = new PipelineScriptAction(new Tag
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,6 @@ using BililiveRecorder.Flv.Pipeline;
|
||||||
using BililiveRecorder.Flv.Pipeline.Rules;
|
using BililiveRecorder.Flv.Pipeline.Rules;
|
||||||
using BililiveRecorder.Flv.Writer;
|
using BililiveRecorder.Flv.Writer;
|
||||||
using BililiveRecorder.Flv.Xml;
|
using BililiveRecorder.Flv.Xml;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace BililiveRecorder.Flv.Tests.RuleTests
|
namespace BililiveRecorder.Flv.Tests.RuleTests
|
||||||
|
@ -18,7 +17,7 @@ namespace BililiveRecorder.Flv.Tests.RuleTests
|
||||||
var writer = new FlvProcessingContextWriter(tagWriter: output, allowMissingHeader: true, disableKeyframes: true, logger: null);
|
var writer = new FlvProcessingContextWriter(tagWriter: output, allowMissingHeader: true, disableKeyframes: true, logger: null);
|
||||||
var session = new Dictionary<object, object?>();
|
var session = new Dictionary<object, object?>();
|
||||||
var context = new FlvProcessingContext();
|
var context = new FlvProcessingContext();
|
||||||
var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).Add<FfmpegDetectionRule>().AddDefault().AddRemoveFillerData().Build();
|
var pipeline = new ProcessingPipelineBuilder().AddRule<FfmpegDetectionRule>().AddDefaultRules().AddRemoveFillerDataRule().Build();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user