BililiveRecorder/BililiveRecorder.FlvProcessor/FlvClipProcessor.cs

98 lines
3.4 KiB
C#
Raw Normal View History

2018-03-24 04:58:13 +08:00
using NLog;
using System;
2018-03-12 18:57:20 +08:00
using System.Collections.Generic;
2018-03-19 16:51:35 +08:00
using System.IO;
2018-03-12 18:57:20 +08:00
namespace BililiveRecorder.FlvProcessor
{
2018-10-24 13:33:43 +08:00
public class FlvClipProcessor : IFlvClipProcessor
2018-03-12 18:57:20 +08:00
{
2018-03-24 04:58:13 +08:00
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
2019-01-16 23:05:54 +08:00
private readonly Func<IFlvTag> funcFlvTag;
2018-10-25 19:20:23 +08:00
public IFlvMetadata Header { get; private set; }
public List<IFlvTag> HTags { get; private set; }
public List<IFlvTag> Tags { get; private set; }
private int target = -1;
2018-10-31 06:22:38 +08:00
private string path;
2018-03-20 00:12:32 +08:00
2019-01-16 23:05:54 +08:00
public FlvClipProcessor(Func<IFlvTag> funcFlvTag)
2018-03-12 18:57:20 +08:00
{
2019-01-16 23:05:54 +08:00
this.funcFlvTag = funcFlvTag;
2018-10-25 19:20:23 +08:00
}
2018-10-31 06:22:38 +08:00
public IFlvClipProcessor Initialize(string path, IFlvMetadata metadata, List<IFlvTag> head, List<IFlvTag> data, uint seconds)
2018-10-25 19:20:23 +08:00
{
2018-10-31 06:22:38 +08:00
this.path = path;
2018-11-07 06:07:49 +08:00
Header = metadata; // TODO: Copy a copy, do not share
2018-03-24 08:34:57 +08:00
HTags = head;
2018-10-25 19:20:23 +08:00
Tags = data;
target = Tags[Tags.Count - 1].TimeStamp + (int)(seconds * FlvStreamProcessor.SEC_TO_MS);
2018-03-27 06:10:30 +08:00
logger.Debug("Clip 创建 Tags.Count={0} Tags[0].TimeStamp={1} Tags[Tags.Count-1].TimeStamp={2} Tags里秒数={3}",
2018-03-24 04:58:13 +08:00
Tags.Count, Tags[0].TimeStamp, Tags[Tags.Count - 1].TimeStamp, (Tags[Tags.Count - 1].TimeStamp - Tags[0].TimeStamp) / 1000d);
2018-10-25 19:20:23 +08:00
return this;
2018-03-12 18:57:20 +08:00
}
2018-10-24 13:33:43 +08:00
public void AddTag(IFlvTag tag)
2018-03-13 13:21:01 +08:00
{
2018-03-19 16:51:35 +08:00
Tags.Add(tag);
if (tag.TimeStamp >= target)
{
FinallizeFile();
}
2018-03-13 13:21:01 +08:00
}
2018-03-19 16:51:35 +08:00
public void FinallizeFile()
{
try
2018-03-19 16:51:35 +08:00
{
if (!Directory.Exists(Path.GetDirectoryName(path)))
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
}
2018-10-31 06:22:38 +08:00
using (var fs = new FileStream(path, FileMode.CreateNew, FileAccess.ReadWrite))
{
fs.Write(FlvStreamProcessor.FLV_HEADER_BYTES, 0, FlvStreamProcessor.FLV_HEADER_BYTES.Length);
fs.Write(new byte[] { 0, 0, 0, 0, }, 0, 4);
2018-03-19 16:51:35 +08:00
2019-03-01 17:20:58 +08:00
double clipDuration = (Tags[Tags.Count - 1].TimeStamp - Tags[0].TimeStamp) / 1000d;
Header["duration"] = clipDuration;
Header["lasttimestamp"] = (double)(Tags[Tags.Count - 1].TimeStamp - Tags[0].TimeStamp);
2018-03-19 16:51:35 +08:00
2019-01-16 23:05:54 +08:00
var t = funcFlvTag();
t.TagType = TagType.DATA;
2019-01-17 22:29:49 +08:00
if (Header.ContainsKey("BililiveRecorder"))
{
// TODO: 更好的写法
2019-03-01 17:20:58 +08:00
(Header["BililiveRecorder"] as Dictionary<string, object>)["starttime"] = DateTime.UtcNow - TimeSpan.FromSeconds(clipDuration);
2019-01-17 22:29:49 +08:00
}
2019-01-16 23:05:54 +08:00
t.Data = Header.ToBytes();
t.WriteTo(fs);
2018-03-19 16:51:35 +08:00
2018-03-29 21:51:23 +08:00
int offset = Tags[0].TimeStamp;
HTags.ForEach(tag => tag.WriteTo(fs));
Tags.ForEach(tag => tag.WriteTo(fs, offset));
2018-10-31 06:22:38 +08:00
logger.Info("剪辑已保存:{0}", Path.GetFileName(path));
2018-03-27 06:10:30 +08:00
fs.Close();
}
Tags.Clear();
2018-03-19 16:51:35 +08:00
}
catch (Exception ex)
{
logger.Error(ex, "保存剪辑文件时出错");
}
ClipFinalized?.Invoke(this, new ClipFinalizedArgs() { ClipProcessor = this });
2018-03-19 16:51:35 +08:00
}
2018-03-13 13:21:01 +08:00
public event ClipFinalizedEvent ClipFinalized;
2018-03-12 18:57:20 +08:00
}
}