BililiveRecorder/BililiveRecorder.Core/Recorder.cs

163 lines
5.8 KiB
C#
Raw Normal View History

2018-11-01 23:40:50 +08:00
using BililiveRecorder.Core.Config;
using NLog;
2018-03-21 20:56:56 +08:00
using System;
using System.Collections.Generic;
2018-03-12 18:57:20 +08:00
using System.Collections.ObjectModel;
2018-03-24 09:48:06 +08:00
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
2018-03-12 18:57:20 +08:00
namespace BililiveRecorder.Core
{
public class Recorder
{
2018-03-21 20:56:56 +08:00
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
2018-10-24 14:33:05 +08:00
public ObservableCollection<IRecordedRoom> Rooms { get; } = new ObservableCollection<IRecordedRoom>();
2018-11-01 23:40:50 +08:00
public ConfigV1 Config { get; }
2018-03-20 00:12:32 +08:00
2018-10-25 19:20:23 +08:00
private readonly Func<int, IRecordedRoom> newIRecordedRoom;
private CancellationTokenSource tokenSource;
2018-11-01 23:40:50 +08:00
private bool _valid = false;
public Recorder(ConfigV1 config, Func<int, IRecordedRoom> iRecordedRoom)
2018-03-20 00:12:32 +08:00
{
2018-11-01 23:40:50 +08:00
Config = config;
2018-10-25 19:20:23 +08:00
newIRecordedRoom = iRecordedRoom;
tokenSource = new CancellationTokenSource();
Repeat.Interval(TimeSpan.FromSeconds(6), DownloadWatchdog, tokenSource.Token);
2018-11-10 12:17:41 +08:00
Rooms.CollectionChanged += (sender, e) =>
{
logger.Debug($"Rooms.CollectionChanged;{e.Action};" +
$"O:{e.OldItems.Cast<IRecordedRoom>().Select(rr => rr.RealRoomid.ToString()).Aggregate((current, next) => current + "," + next)};" +
$"N:{e.NewItems.Cast<IRecordedRoom>().Select(rr => rr.RealRoomid.ToString()).Aggregate((current, next) => current + "," + next)}");
};
}
2018-03-20 00:12:32 +08:00
2018-11-01 23:40:50 +08:00
public bool Initialize(string workdir)
{
2018-11-10 12:17:41 +08:00
logger.Debug("Initialize: " + workdir);
2018-11-01 23:40:50 +08:00
if (ConfigParser.Load(directory: workdir, config: Config))
{
2018-11-01 23:40:50 +08:00
_valid = true;
Config.WorkDirectory = workdir;
if ((Config.RoomList?.Count ?? 0) > 0)
{
2018-11-01 23:40:50 +08:00
Config.RoomList.ForEach((r) => AddRoom(r.Roomid, r.Enabled));
}
ConfigParser.Save(Config.WorkDirectory, Config);
return true;
}
2018-11-01 23:40:50 +08:00
else
{
2018-11-01 23:40:50 +08:00
return false;
}
2018-03-20 00:12:32 +08:00
}
2018-03-12 18:57:20 +08:00
2018-03-24 02:27:58 +08:00
/// <summary>
/// 添加直播间到录播姬
/// </summary>
/// <param name="roomid">房间号(支持短号)</param>
/// <exception cref="ArgumentOutOfRangeException"/>
2018-11-10 12:17:41 +08:00
public void AddRoom(int roomid) => AddRoom(roomid, false);
/// <summary>
/// 添加直播间到录播姬
/// </summary>
/// <param name="roomid">房间号(支持短号)</param>
/// <param name="enabled">是否默认启用</param>
/// <exception cref="ArgumentOutOfRangeException"/>
public void AddRoom(int roomid, bool enabled)
2018-03-21 20:56:56 +08:00
{
2018-11-01 23:40:50 +08:00
if (!_valid) { throw new InvalidOperationException("Not Initialized"); }
2018-03-21 20:56:56 +08:00
if (roomid <= 0)
2018-10-25 19:20:23 +08:00
{
2018-03-21 20:56:56 +08:00
throw new ArgumentOutOfRangeException(nameof(roomid), "房间号需要大于0");
2018-10-25 19:20:23 +08:00
}
// var rr = new RecordedRoom(Settings, roomid);
var rr = newIRecordedRoom(roomid);
2018-03-24 09:48:06 +08:00
if (enabled)
2018-10-25 19:20:23 +08:00
{
Task.Run(() => rr.Start());
2018-10-25 19:20:23 +08:00
}
2018-03-24 09:48:06 +08:00
Rooms.Add(rr);
2018-11-10 12:17:41 +08:00
logger.Debug("AddRoom 添加了直播间 " + rr.RealRoomid);
2018-03-21 20:56:56 +08:00
}
2018-03-24 02:27:58 +08:00
/// <summary>
/// 从录播姬移除直播间
/// </summary>
/// <param name="rr">直播间</param>
2018-10-24 14:33:05 +08:00
public void RemoveRoom(IRecordedRoom rr)
2018-03-24 02:27:58 +08:00
{
2018-11-01 23:40:50 +08:00
if (!_valid) { throw new InvalidOperationException("Not Initialized"); }
rr.Shutdown();
2018-03-24 08:58:46 +08:00
Rooms.Remove(rr);
2018-11-10 12:17:41 +08:00
logger.Debug("RemoveRoom 移除了直播间 " + rr.RealRoomid);
2018-03-24 02:27:58 +08:00
}
2018-03-24 09:48:06 +08:00
public void Shutdown()
{
2018-11-01 23:40:50 +08:00
if (!_valid) { throw new InvalidOperationException("Not Initialized"); }
2018-11-10 12:17:41 +08:00
logger.Debug("Shutdown called.");
tokenSource.Cancel();
Config.RoomList = new List<RoomV1>();
Rooms.ToList().ForEach(rr =>
{
Config.RoomList.Add(new RoomV1()
{
Roomid = rr.RealRoomid,
Enabled = rr.IsMonitoring,
});
});
2018-03-24 09:48:06 +08:00
Rooms.ToList().ForEach(rr =>
{
rr.Shutdown();
2018-03-24 09:48:06 +08:00
});
2018-11-01 23:57:15 +08:00
ConfigParser.Save(Config.WorkDirectory, Config);
2018-03-24 09:48:06 +08:00
}
2018-11-01 23:40:50 +08:00
private void DownloadWatchdog()
{
if (!_valid) { return; }
try
{
Rooms.ToList().ForEach(room =>
{
if (room.IsRecording)
{
if (DateTime.Now - room.LastUpdateDateTime > TimeSpan.FromSeconds(3))
{
logger.Warn("服务器停止提供 {0} 直播间的直播数据,通常是录制时网络不稳定导致,将会断开重连", room.Roomid);
room.StopRecord();
room.StreamMonitor.CheckAfterSeconeds(1, TriggerType.HttpApi);
}
2018-11-03 07:45:56 +08:00
else if (room.Processor != null &&
((DateTime.Now - room.Processor.StartDateTime).TotalMilliseconds
>
2018-11-07 06:07:49 +08:00
(room.Processor.TotalMaxTimestamp + (10 * 1000)))
2018-11-03 07:45:56 +08:00
)
{
logger.Warn("{0} 直播间的下载速度达不到录制标准,将断开重连。请检查网络是否稳定", room.Roomid);
room.StopRecord();
room.StreamMonitor.CheckAfterSeconeds(1, TriggerType.HttpApi);
}
2018-11-01 23:40:50 +08:00
}
});
}
catch (Exception ex)
{
logger.Error(ex, "直播流下载监控出错");
}
}
2018-03-12 18:57:20 +08:00
}
}