Fix processing bug

This commit is contained in:
Genteure 2021-02-27 13:28:21 +08:00
parent 479a205abd
commit d3a5158093
5 changed files with 70 additions and 33 deletions

View File

@ -20,6 +20,8 @@ namespace BililiveRecorder.Core.Event
public long TotalOutputVideoByteCount { get; set; }
public long TotalOutputAudioByteCount { get; set; }
public long CurrnetFileSize { get; set; }
public double AddedDuration { get; set; }
public double PassedTime { get; set; }
public double DuraionRatio { get; set; }

View File

@ -7,22 +7,37 @@ namespace BililiveRecorder.Core.ProcessingRules
{
public class SplitRule : IFullProcessingRule
{
private static readonly FlvProcessingContext NewFileContext = new FlvProcessingContext(PipelineNewFileAction.Instance, new Dictionary<object, object?>());
private static readonly FlvProcessingContext NewFileContext =
new FlvProcessingContext(PipelineNewFileAction.Instance, new Dictionary<object, object?>());
// 0 = false, 1 = true
// 0 = none, 1 = after, 2 = before
private int splitFlag = 0;
private const int FLAG_NONE = 0;
private const int FLAG_BEFORE = 1;
private const int FLAG_AFTER = 2;
public async Task RunAsync(FlvProcessingContext context, ProcessingDelegate next)
{
await next(context).ConfigureAwait(false);
var flag = Interlocked.Exchange(ref this.splitFlag, FLAG_NONE);
if (1 == Interlocked.Exchange(ref this.splitFlag, 0))
if (FLAG_BEFORE == flag)
{
await next(NewFileContext).ConfigureAwait(false);
context.AddNewFileAtStart();
}
await next(context).ConfigureAwait(false);
if (FLAG_AFTER == flag)
{
await next(NewFileContext).ConfigureAwait(false);
context.AddNewFileAtEnd();
}
}
public void SetSplitFlag() => Interlocked.Exchange(ref this.splitFlag, 1);
public void SetSplitBeforeFlag() => Interlocked.Exchange(ref this.splitFlag, FLAG_BEFORE);
public void SetSplitAfterFlag() => Interlocked.Exchange(ref this.splitFlag, FLAG_AFTER);
}
}

View File

@ -10,23 +10,34 @@ namespace BililiveRecorder.Core.ProcessingRules
{
public class StatsRule : ISimpleProcessingRule
{
public const string SkipStatsKey = nameof(SkipStatsKey);
public event EventHandler<RecordingStatsEventArgs>? StatsUpdated;
public long TotalInputVideoByteCount { get; private set; }
public long TotalInputAudioByteCount { get; private set; }
// 两个值相加可得出总数据量
public int TotalOutputVideoFrameCount { get; private set; }
public int TotalOutputAudioFrameCount { get; private set; }
public long TotalOutputVideoByteCount { get; private set; }
public long TotalOutputAudioByteCount { get; private set; }
public long CurrnetFileSize { get; private set; } = 13;
public int SumOfMaxTimestampOfClosedFiles { get; private set; }
public int CurrentFileMaxTimestamp { get; private set; }
public DateTimeOffset LastWriteTime { get; private set; }
public async Task RunAsync(FlvProcessingContext context, Func<Task> next)
public Task RunAsync(FlvProcessingContext context, Func<Task> next)
{
if (context.LocalItems.ContainsKey(SkipStatsKey))
return next();
else
return this.RunCoreAsync(context, next);
}
private async Task RunCoreAsync(FlvProcessingContext context, Func<Task> next)
{
var e = new RecordingStatsEventArgs();
@ -60,8 +71,6 @@ namespace BililiveRecorder.Core.ProcessingRules
}
}
var maxTimestampBeforeCalc = this.CurrentFileMaxTimestamp;
foreach (var item in groups)
{
if (item is null)
@ -70,7 +79,6 @@ namespace BililiveRecorder.Core.ProcessingRules
CalcStats(e, item);
}
e.AddedDuration = (this.CurrentFileMaxTimestamp - maxTimestampBeforeCalc) / 1000d;
var now = DateTimeOffset.UtcNow;
e.PassedTime = (now - this.LastWriteTime).TotalSeconds;
this.LastWriteTime = now;
@ -88,10 +96,17 @@ namespace BililiveRecorder.Core.ProcessingRules
e.TotalOutputVideoByteCount = this.TotalOutputVideoByteCount += e.OutputVideoByteCount = dataActions.Sum(x => x.Tags.Where(x => x.Type == TagType.Video).Sum(x => (x.Nalus == null ? x.Size : (5 + x.Nalus.Sum(n => n.FullSize + 4))) + (11 + 4)));
e.TotalOutputAudioByteCount = this.TotalOutputAudioByteCount += e.OutputAudioByteCount = dataActions.Sum(x => x.Tags.Where(x => x.Type == TagType.Audio).Sum(x => x.Size + (11 + 4)));
var lastTags = dataActions[dataActions.Count - 1].Tags;
if (lastTags.Count > 0)
this.CurrentFileMaxTimestamp = e.FileMaxTimestamp = lastTags[lastTags.Count - 1].Timestamp;
e.CurrnetFileSize = this.CurrnetFileSize += e.OutputVideoByteCount + e.OutputAudioByteCount;
foreach (var action in dataActions)
{
var tags = action.Tags;
if (tags.Count > 0)
{
e.AddedDuration += (tags[tags.Count - 1].Timestamp - tags[0].Timestamp) / 1000d;
this.CurrentFileMaxTimestamp = e.FileMaxTimestamp = tags[tags.Count - 1].Timestamp;
}
}
}
e.SessionMaxTimestamp = this.SumOfMaxTimestampOfClosedFiles + this.CurrentFileMaxTimestamp;
@ -101,6 +116,7 @@ namespace BililiveRecorder.Core.ProcessingRules
{
this.SumOfMaxTimestampOfClosedFiles += this.CurrentFileMaxTimestamp;
this.CurrentFileMaxTimestamp = 0;
this.CurrnetFileSize = 13;
}
}
}

View File

@ -79,8 +79,8 @@ namespace BililiveRecorder.Core.Recording
this.statsRule.StatsUpdated += this.StatsRule_StatsUpdated;
this.pipeline = builder
.Add(this.splitFileRule)
.Add(this.statsRule)
.Add(this.splitFileRule)
.AddDefault()
.AddRemoveFillerData()
.Build();
@ -111,7 +111,7 @@ namespace BililiveRecorder.Core.Recording
public event EventHandler<RecordFileClosedEventArgs>? RecordFileClosed;
public event EventHandler? RecordSessionEnded;
public void SplitOutput() => this.splitFileRule.SetSplitFlag();
public void SplitOutput() => this.splitFileRule.SetSplitBeforeFlag();
public void RequestStop() => this.cts.Cancel();
@ -252,10 +252,11 @@ namespace BililiveRecorder.Core.Recording
private async Task RecordingLoopAsync()
{
if (this.reader is null) return;
if (this.writer is null) return;
try
{
if (this.reader is null) return;
if (this.writer is null) return;
while (!this.ct.IsCancellationRequested)
{
var group = await this.reader.ReadGroupAsync(this.ct).ConfigureAwait(false);
@ -383,12 +384,16 @@ namespace BililiveRecorder.Core.Recording
private void StatsRule_StatsUpdated(object sender, RecordingStatsEventArgs e)
{
if (this.room.RoomConfig.CuttingMode == Config.V2.CuttingMode.ByTime)
switch (this.room.RoomConfig.CuttingMode)
{
if (e.FileMaxTimestamp > (this.room.RoomConfig.CuttingNumber * (60 * 1000)))
{
this.splitFileRule.SetSplitFlag();
}
case Config.V2.CuttingMode.ByTime:
if (e.FileMaxTimestamp > this.room.RoomConfig.CuttingNumber * (60u * 1000u))
this.splitFileRule.SetSplitBeforeFlag();
break;
case Config.V2.CuttingMode.BySize:
if ((e.CurrnetFileSize + (e.OutputVideoByteCount * 1.1) + e.OutputAudioByteCount) / (1024d * 1024d) > this.room.RoomConfig.CuttingNumber)
this.splitFileRule.SetSplitBeforeFlag();
break;
}
RecordingStats?.Invoke(this, e);
@ -411,15 +416,7 @@ namespace BililiveRecorder.Core.Recording
this.OnNewFile = onNewFile ?? throw new ArgumentNullException(nameof(onNewFile));
}
public bool ShouldCreateNewFile(Stream outputStream, IList<Tag> tags)
{
if (this.room.RoomConfig.CuttingMode == Config.V2.CuttingMode.BySize)
{
var pendingSize = tags.Sum(x => (x.Nalus == null ? x.Size : (5 + x.Nalus.Sum(n => n.FullSize + 4))) + (11 + 4));
return (outputStream.Length + pendingSize) > (this.room.RoomConfig.CuttingNumber * (1024 * 1024));
}
return false;
}
public bool ShouldCreateNewFile(Stream outputStream, IList<Tag> tags) => false;
public (Stream stream, object state) CreateOutputStream()
{

View File

@ -1,6 +1,7 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Diagnostics;
using System.IO;
using System.Runtime.ExceptionServices;
using System.Security;
@ -29,6 +30,8 @@ namespace BililiveRecorder.WPF
static Program()
{
levelSwitchGlobal = new LoggingLevelSwitch(Serilog.Events.LogEventLevel.Debug);
if (Debugger.IsAttached)
levelSwitchGlobal.MinimumLevel = Serilog.Events.LogEventLevel.Verbose;
levelSwitchConsole = new LoggingLevelSwitch(Serilog.Events.LogEventLevel.Error);
logger = BuildLogger();
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
@ -144,9 +147,13 @@ namespace BililiveRecorder.WPF
.Enrich.WithThreadName()
.Enrich.FromLogContext()
.Enrich.WithExceptionDetails()
.WriteTo.Debug()
.WriteTo.Console(levelSwitch: levelSwitchConsole)
.WriteTo.Sink<WpfLogEventSink>(Serilog.Events.LogEventLevel.Debug) // TODO level
#if DEBUG
.WriteTo.Debug()
.WriteTo.Sink<WpfLogEventSink>(Serilog.Events.LogEventLevel.Debug)
#else
.WriteTo.Sink<WpfLogEventSink>(Serilog.Events.LogEventLevel.Information)
#endif
.WriteTo.File(new CompactJsonFormatter(), "./logs/bilirec.txt", shared: true, rollingInterval: RollingInterval.Day)
.WriteTo.Sentry(o =>
{