feat: add option to disable spliting when H264 Annex-B is detected

This commit is contained in:
genteure 2024-09-28 00:24:36 +08:00 committed by Genteure
parent f48fbf4d38
commit 8b4d467bd5
8 changed files with 159 additions and 2 deletions

View File

@ -27,6 +27,7 @@ namespace BililiveRecorder.Cli.Configure
RecordingQuality, RecordingQuality,
FileNameRecordTemplate, FileNameRecordTemplate,
FlvProcessorSplitOnScriptTag, FlvProcessorSplitOnScriptTag,
FlvProcessorDisableSplitOnH264AnnexB,
FlvWriteMetadata, FlvWriteMetadata,
WebHookUrls, WebHookUrls,
WebHookUrlsV2, WebHookUrlsV2,
@ -65,7 +66,8 @@ namespace BililiveRecorder.Cli.Configure
RecordDanmakuGuard, RecordDanmakuGuard,
SaveStreamCover, SaveStreamCover,
RecordingQuality, RecordingQuality,
FlvProcessorSplitOnScriptTag FlvProcessorSplitOnScriptTag,
FlvProcessorDisableSplitOnH264AnnexB
} }
public static class ConfigInstructions public static class ConfigInstructions
{ {
@ -87,6 +89,7 @@ namespace BililiveRecorder.Cli.Configure
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.FlvProcessorSplitOnScriptTag, new ConfigInstruction<GlobalConfig, bool>(config => config.HasFlvProcessorSplitOnScriptTag = false, (config, value) => config.FlvProcessorSplitOnScriptTag = value) { Name = "FlvProcessorSplitOnScriptTag", CanBeOptional = true });
GlobalConfig.Add(GlobalConfigProperties.FlvProcessorDisableSplitOnH264AnnexB, new ConfigInstruction<GlobalConfig, bool>(config => config.HasFlvProcessorDisableSplitOnH264AnnexB = false, (config, value) => config.FlvProcessorDisableSplitOnH264AnnexB = value) { Name = "FlvProcessorDisableSplitOnH264AnnexB", CanBeOptional = true });
GlobalConfig.Add(GlobalConfigProperties.FlvWriteMetadata, new ConfigInstruction<GlobalConfig, bool>(config => config.HasFlvWriteMetadata = false, (config, value) => config.FlvWriteMetadata = value) { Name = "FlvWriteMetadata", CanBeOptional = true }); GlobalConfig.Add(GlobalConfigProperties.FlvWriteMetadata, new ConfigInstruction<GlobalConfig, bool>(config => config.HasFlvWriteMetadata = false, (config, value) => config.FlvWriteMetadata = value) { Name = "FlvWriteMetadata", 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 });
@ -122,6 +125,7 @@ namespace BililiveRecorder.Cli.Configure
RoomConfig.Add(RoomConfigProperties.SaveStreamCover, new ConfigInstruction<RoomConfig, bool>(config => config.HasSaveStreamCover = false, (config, value) => config.SaveStreamCover = value) { Name = "SaveStreamCover", CanBeOptional = true }); RoomConfig.Add(RoomConfigProperties.SaveStreamCover, new ConfigInstruction<RoomConfig, bool>(config => config.HasSaveStreamCover = false, (config, value) => config.SaveStreamCover = value) { Name = "SaveStreamCover", 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 }); RoomConfig.Add(RoomConfigProperties.FlvProcessorSplitOnScriptTag, new ConfigInstruction<RoomConfig, bool>(config => config.HasFlvProcessorSplitOnScriptTag = false, (config, value) => config.FlvProcessorSplitOnScriptTag = value) { Name = "FlvProcessorSplitOnScriptTag", CanBeOptional = true });
RoomConfig.Add(RoomConfigProperties.FlvProcessorDisableSplitOnH264AnnexB, new ConfigInstruction<RoomConfig, bool>(config => config.HasFlvProcessorDisableSplitOnH264AnnexB = false, (config, value) => config.FlvProcessorDisableSplitOnH264AnnexB = value) { Name = "FlvProcessorDisableSplitOnH264AnnexB", CanBeOptional = true });
} }
} }

View File

@ -125,6 +125,14 @@ namespace BililiveRecorder.Core.Config.V3
[JsonProperty(nameof(FlvProcessorSplitOnScriptTag)), EditorBrowsable(EditorBrowsableState.Never)] [JsonProperty(nameof(FlvProcessorSplitOnScriptTag)), EditorBrowsable(EditorBrowsableState.Never)]
public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get => this.GetPropertyValueOptional<bool>(nameof(this.FlvProcessorSplitOnScriptTag)); set => this.SetPropertyValueOptional(value, nameof(this.FlvProcessorSplitOnScriptTag)); } public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get => this.GetPropertyValueOptional<bool>(nameof(this.FlvProcessorSplitOnScriptTag)); set => this.SetPropertyValueOptional(value, nameof(this.FlvProcessorSplitOnScriptTag)); }
/// <summary>
/// FLV修复-检测到 H264 Annex-B 时禁用修复分段
/// </summary>
public bool FlvProcessorDisableSplitOnH264AnnexB { get => this.GetPropertyValue<bool>(); set => this.SetPropertyValue(value); }
public bool HasFlvProcessorDisableSplitOnH264AnnexB { get => this.GetPropertyHasValue(nameof(this.FlvProcessorDisableSplitOnH264AnnexB)); set => this.SetPropertyHasValue<bool>(value, nameof(this.FlvProcessorDisableSplitOnH264AnnexB)); }
[JsonProperty(nameof(FlvProcessorDisableSplitOnH264AnnexB)), EditorBrowsable(EditorBrowsableState.Never)]
public Optional<bool> OptionalFlvProcessorDisableSplitOnH264AnnexB { get => this.GetPropertyValueOptional<bool>(nameof(this.FlvProcessorDisableSplitOnH264AnnexB)); set => this.SetPropertyValueOptional(value, nameof(this.FlvProcessorDisableSplitOnH264AnnexB)); }
/// <summary> /// <summary>
/// 录制文件名模板 /// 录制文件名模板
/// </summary> /// </summary>
@ -339,6 +347,14 @@ namespace BililiveRecorder.Core.Config.V3
[JsonProperty(nameof(FlvProcessorSplitOnScriptTag)), EditorBrowsable(EditorBrowsableState.Never)] [JsonProperty(nameof(FlvProcessorSplitOnScriptTag)), EditorBrowsable(EditorBrowsableState.Never)]
public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get => this.GetPropertyValueOptional<bool>(nameof(this.FlvProcessorSplitOnScriptTag)); set => this.SetPropertyValueOptional(value, nameof(this.FlvProcessorSplitOnScriptTag)); } public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get => this.GetPropertyValueOptional<bool>(nameof(this.FlvProcessorSplitOnScriptTag)); set => this.SetPropertyValueOptional(value, nameof(this.FlvProcessorSplitOnScriptTag)); }
/// <summary>
/// FLV修复-检测到 H264 Annex-B 时禁用修复分段
/// </summary>
public bool FlvProcessorDisableSplitOnH264AnnexB { get => this.GetPropertyValue<bool>(); set => this.SetPropertyValue(value); }
public bool HasFlvProcessorDisableSplitOnH264AnnexB { get => this.GetPropertyHasValue(nameof(this.FlvProcessorDisableSplitOnH264AnnexB)); set => this.SetPropertyHasValue<bool>(value, nameof(this.FlvProcessorDisableSplitOnH264AnnexB)); }
[JsonProperty(nameof(FlvProcessorDisableSplitOnH264AnnexB)), EditorBrowsable(EditorBrowsableState.Never)]
public Optional<bool> OptionalFlvProcessorDisableSplitOnH264AnnexB { get => this.GetPropertyValueOptional<bool>(nameof(this.FlvProcessorDisableSplitOnH264AnnexB)); set => this.SetPropertyValueOptional(value, nameof(this.FlvProcessorDisableSplitOnH264AnnexB)); }
/// <summary> /// <summary>
/// 是否在视频文件写入直播信息 metadata /// 是否在视频文件写入直播信息 metadata
/// </summary> /// </summary>
@ -532,6 +548,8 @@ namespace BililiveRecorder.Core.Config.V3
public bool FlvProcessorSplitOnScriptTag => false; public bool FlvProcessorSplitOnScriptTag => false;
public bool FlvProcessorDisableSplitOnH264AnnexB => false;
public bool FlvWriteMetadata => true; public bool FlvWriteMetadata => true;
public string WebHookUrls => @""; public string WebHookUrls => @"";

View File

@ -64,7 +64,8 @@ namespace BililiveRecorder.Core.Recording
this.pipeline = builder this.pipeline = builder
.ConfigureServices(services => services.AddSingleton(new ProcessingPipelineSettings .ConfigureServices(services => services.AddSingleton(new ProcessingPipelineSettings
{ {
SplitOnScriptTag = room.RoomConfig.FlvProcessorSplitOnScriptTag SplitOnScriptTag = room.RoomConfig.FlvProcessorSplitOnScriptTag,
DisableSplitOnH264AnnexB = room.RoomConfig.FlvProcessorDisableSplitOnH264AnnexB,
})) }))
.AddRule(this.statsRule) .AddRule(this.statsRule)
.AddRule(this.splitFileRule) .AddRule(this.splitFileRule)

View File

@ -9,5 +9,10 @@ namespace BililiveRecorder.Flv.Pipeline
/// 控制收到 onMetaData 时是否分段 /// 控制收到 onMetaData 时是否分段
/// </summary> /// </summary>
public bool SplitOnScriptTag { get; set; } = false; public bool SplitOnScriptTag { get; set; } = false;
/// <summary>
/// 检测到 H264 Annex-B 时禁用修复分段
/// </summary>
public bool DisableSplitOnH264AnnexB { get; set; } = false;
} }
} }

View File

@ -15,9 +15,26 @@ 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 const string ANNEXB_KEY = "HandleNewHeaderRule_AnnexB";
private enum AnnexBState
{
Unknown,
Pending,
IsAnnexB,
}
private static readonly ProcessingComment MultipleHeaderComment = new ProcessingComment(CommentType.DecodingHeader, true, "收到了连续多个 Header新建文件"); private static readonly ProcessingComment MultipleHeaderComment = new ProcessingComment(CommentType.DecodingHeader, true, "收到了连续多个 Header新建文件");
private static readonly ProcessingComment SplitFileComment = new ProcessingComment(CommentType.DecodingHeader, true, "因为 Header 问题新建文件"); private static readonly ProcessingComment SplitFileComment = new ProcessingComment(CommentType.DecodingHeader, true, "因为 Header 问题新建文件");
private static readonly ProcessingComment AnnexBCommentFirst = new ProcessingComment(CommentType.DecodingHeader, true, "检测到一次 AnnexB 格式");
private static readonly ProcessingComment AnnexBComment = new ProcessingComment(CommentType.DecodingHeader, true, "检测到 AnnexB 格式,不再切割文件");
private readonly bool disableSplitOnH264AnnexB;
public HandleNewHeaderRule(ProcessingPipelineSettings? processingPipelineSettings)
{
this.disableSplitOnH264AnnexB = processingPipelineSettings?.DisableSplitOnH264AnnexB ?? false;
}
public void Run(FlvProcessingContext context, Action next) public void Run(FlvProcessingContext context, Action next)
{ {
@ -27,8 +44,70 @@ namespace BililiveRecorder.Flv.Pipeline.Rules
private IEnumerable<PipelineAction?> RunPerAction(FlvProcessingContext context, PipelineAction action) private IEnumerable<PipelineAction?> RunPerAction(FlvProcessingContext context, PipelineAction action)
{ {
if (this.disableSplitOnH264AnnexB)
{
var state = context.SessionItems.ContainsKey(ANNEXB_KEY) ? (AnnexBState)context.SessionItems[ANNEXB_KEY] : AnnexBState.Unknown;
if (state == AnnexBState.IsAnnexB)
{
// 如果已经检测到 Annex B 格式则不再切割文件
yield return action;
yield break;
}
if (action is PipelineDataAction data)
{
var annexb = false;
for (var i = 0; i < data.Tags.Count; i++)
{
var tag = data.Tags[i];
if (tag.IsKeyframeData())
{
// Check nalu
if (tag.Nalus is { } nalus)
{
bool sps = false, pps = false;
foreach (var nalu in nalus)
{
if (nalu.Type == H264NaluType.Sps)
sps = true;
if (nalu.Type == H264NaluType.Pps)
pps = true;
}
annexb = sps && pps;
}
break;
}
}
if (annexb)
{
if (state == AnnexBState.Unknown)
{
context.SessionItems[ANNEXB_KEY] = AnnexBState.Pending;
context.AddComment(AnnexBCommentFirst);
}
else
{
context.SessionItems[ANNEXB_KEY] = AnnexBState.IsAnnexB;
context.AddComment(AnnexBComment);
}
}
yield return action;
yield break;
} // if (action is PipelineDataAction data)
} // if (this.disableSplitOnH264AnnexB)
if (action is PipelineHeaderAction header) if (action is PipelineHeaderAction header)
{ {
if (this.disableSplitOnH264AnnexB)
{
context.SessionItems.Remove(ANNEXB_KEY);
}
// 从 Session Items 里取上次写入的 Header // 从 Session Items 里取上次写入的 Header
var lastVideoHeader = context.SessionItems.ContainsKey(VIDEO_HEADER_KEY) ? context.SessionItems[VIDEO_HEADER_KEY] as Tag : null; var lastVideoHeader = context.SessionItems.ContainsKey(VIDEO_HEADER_KEY) ? context.SessionItems[VIDEO_HEADER_KEY] as Tag : null;
var lastAudioHeader = context.SessionItems.ContainsKey(AUDIO_HEADER_KEY) ? context.SessionItems[AUDIO_HEADER_KEY] as Tag : null; var lastAudioHeader = context.SessionItems.ContainsKey(AUDIO_HEADER_KEY) ? context.SessionItems[AUDIO_HEADER_KEY] as Tag : null;

View File

@ -25,6 +25,7 @@ namespace BililiveRecorder.Web.Models
public Optional<bool>? OptionalSaveStreamCover { get; set; } public Optional<bool>? OptionalSaveStreamCover { get; set; }
public Optional<string?>? OptionalRecordingQuality { get; set; } public Optional<string?>? OptionalRecordingQuality { get; set; }
public Optional<bool>? OptionalFlvProcessorSplitOnScriptTag { get; set; } public Optional<bool>? OptionalFlvProcessorSplitOnScriptTag { get; set; }
public Optional<bool>? OptionalFlvProcessorDisableSplitOnH264AnnexB { get; set; }
public void ApplyTo(RoomConfig config) public void ApplyTo(RoomConfig config)
{ {
@ -41,6 +42,7 @@ namespace BililiveRecorder.Web.Models
if (this.OptionalSaveStreamCover.HasValue) config.OptionalSaveStreamCover = this.OptionalSaveStreamCover.Value; if (this.OptionalSaveStreamCover.HasValue) config.OptionalSaveStreamCover = this.OptionalSaveStreamCover.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; if (this.OptionalFlvProcessorSplitOnScriptTag.HasValue) config.OptionalFlvProcessorSplitOnScriptTag = this.OptionalFlvProcessorSplitOnScriptTag.Value;
if (this.OptionalFlvProcessorDisableSplitOnH264AnnexB.HasValue) config.OptionalFlvProcessorDisableSplitOnH264AnnexB = this.OptionalFlvProcessorDisableSplitOnH264AnnexB.Value;
} }
} }
@ -59,6 +61,7 @@ namespace BililiveRecorder.Web.Models
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<bool>? OptionalFlvProcessorSplitOnScriptTag { get; set; }
public Optional<bool>? OptionalFlvProcessorDisableSplitOnH264AnnexB { get; set; }
public Optional<bool>? OptionalFlvWriteMetadata { get; set; } public Optional<bool>? OptionalFlvWriteMetadata { 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; }
@ -95,6 +98,7 @@ namespace BililiveRecorder.Web.Models
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.OptionalFlvProcessorSplitOnScriptTag.HasValue) config.OptionalFlvProcessorSplitOnScriptTag = this.OptionalFlvProcessorSplitOnScriptTag.Value;
if (this.OptionalFlvProcessorDisableSplitOnH264AnnexB.HasValue) config.OptionalFlvProcessorDisableSplitOnH264AnnexB = this.OptionalFlvProcessorDisableSplitOnH264AnnexB.Value;
if (this.OptionalFlvWriteMetadata.HasValue) config.OptionalFlvWriteMetadata = this.OptionalFlvWriteMetadata.Value; if (this.OptionalFlvWriteMetadata.HasValue) config.OptionalFlvWriteMetadata = this.OptionalFlvWriteMetadata.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;
@ -137,6 +141,7 @@ namespace BililiveRecorder.Web.Models.Rest
public Optional<bool> OptionalSaveStreamCover { get; set; } public Optional<bool> OptionalSaveStreamCover { get; set; }
public Optional<string?> OptionalRecordingQuality { get; set; } public Optional<string?> OptionalRecordingQuality { get; set; }
public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get; set; } public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get; set; }
public Optional<bool> OptionalFlvProcessorDisableSplitOnH264AnnexB { get; set; }
} }
public class GlobalConfigDto public class GlobalConfigDto
@ -154,6 +159,7 @@ namespace BililiveRecorder.Web.Models.Rest
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<bool> OptionalFlvProcessorSplitOnScriptTag { get; set; }
public Optional<bool> OptionalFlvProcessorDisableSplitOnH264AnnexB { get; set; }
public Optional<bool> OptionalFlvWriteMetadata { get; set; } public Optional<bool> OptionalFlvWriteMetadata { 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; }
@ -198,6 +204,7 @@ namespace BililiveRecorder.Web.Models.Graphql
this.Field(x => x.OptionalSaveStreamCover, type: typeof(HierarchicalOptionalType<bool>)); this.Field(x => x.OptionalSaveStreamCover, 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>)); this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, type: typeof(HierarchicalOptionalType<bool>));
this.Field(x => x.OptionalFlvProcessorDisableSplitOnH264AnnexB, type: typeof(HierarchicalOptionalType<bool>));
} }
} }
@ -218,6 +225,7 @@ namespace BililiveRecorder.Web.Models.Graphql
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.OptionalFlvProcessorSplitOnScriptTag, type: typeof(HierarchicalOptionalType<bool>));
this.Field(x => x.OptionalFlvProcessorDisableSplitOnH264AnnexB, type: typeof(HierarchicalOptionalType<bool>));
this.Field(x => x.OptionalFlvWriteMetadata, type: typeof(HierarchicalOptionalType<bool>)); this.Field(x => x.OptionalFlvWriteMetadata, 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>));
@ -258,6 +266,7 @@ namespace BililiveRecorder.Web.Models.Graphql
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.FlvProcessorSplitOnScriptTag);
this.Field(x => x.FlvProcessorDisableSplitOnH264AnnexB);
this.Field(x => x.FlvWriteMetadata); this.Field(x => x.FlvWriteMetadata);
this.Field(x => x.WebHookUrls); this.Field(x => x.WebHookUrls);
this.Field(x => x.WebHookUrlsV2); this.Field(x => x.WebHookUrlsV2);
@ -298,6 +307,7 @@ namespace BililiveRecorder.Web.Models.Graphql
this.Field(x => x.OptionalSaveStreamCover, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>)); this.Field(x => x.OptionalSaveStreamCover, 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>)); this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
this.Field(x => x.OptionalFlvProcessorDisableSplitOnH264AnnexB, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
} }
} }
@ -318,6 +328,7 @@ namespace BililiveRecorder.Web.Models.Graphql
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.OptionalFlvProcessorSplitOnScriptTag, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
this.Field(x => x.OptionalFlvProcessorDisableSplitOnH264AnnexB, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
this.Field(x => x.OptionalFlvWriteMetadata, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>)); this.Field(x => x.OptionalFlvWriteMetadata, 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>));

View File

@ -577,6 +577,22 @@
"default": false "default": false
} }
} }
},
"FlvProcessorDisableSplitOnH264AnnexB": {
"description": "FLV修复-检测到 H264 Annex-B 时禁用修复分段\n默认: false",
"markdownDescription": "FLV修复-检测到 H264 Annex-B 时禁用修复分段 \n默认: `false `\n\n",
"type": "object",
"additionalProperties": false,
"properties": {
"HasValue": {
"type": "boolean",
"default": true
},
"Value": {
"type": "boolean",
"default": false
}
}
} }
} }
}, },
@ -822,6 +838,22 @@
"default": false "default": false
} }
} }
},
"FlvProcessorDisableSplitOnH264AnnexB": {
"description": "FLV修复-检测到 H264 Annex-B 时禁用修复分段\n默认: false",
"markdownDescription": "FLV修复-检测到 H264 Annex-B 时禁用修复分段 \n默认: `false `\n\n",
"type": "object",
"additionalProperties": false,
"properties": {
"HasValue": {
"type": "boolean",
"default": true
},
"Value": {
"type": "boolean",
"default": false
}
}
} }
} }
} }

View File

@ -107,6 +107,13 @@ export const data: Array<ConfigEntry> = [
configType: "room", configType: "room",
default: false default: false
}, },
{
id: "FlvProcessorDisableSplitOnH264AnnexB",
name: "FLV修复-检测到 H264 Annex-B 时禁用修复分段",
type: "bool",
configType: "room",
default: false
},
{ {
id: "FlvWriteMetadata", id: "FlvWriteMetadata",
name: "是否在视频文件写入直播信息 metadata", name: "是否在视频文件写入直播信息 metadata",