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
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace BililiveRecorder.FlvProcessor
|
|
|
|
|
{
|
2018-03-21 20:56:56 +08:00
|
|
|
|
public class FlvClipProcessor
|
2018-03-12 18:57:20 +08:00
|
|
|
|
{
|
2018-03-24 04:58:13 +08:00
|
|
|
|
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
|
|
|
|
|
2018-03-19 01:05:02 +08:00
|
|
|
|
public readonly FlvMetadata Header;
|
2018-03-24 08:34:57 +08:00
|
|
|
|
public readonly List<FlvTag> HTags;
|
2018-03-21 00:33:34 +08:00
|
|
|
|
public readonly List<FlvTag> Tags;
|
2018-03-19 16:51:35 +08:00
|
|
|
|
private int target = -1;
|
2018-03-12 18:57:20 +08:00
|
|
|
|
|
2018-03-20 00:12:32 +08:00
|
|
|
|
public Func<string> GetFileName;
|
|
|
|
|
|
2018-03-24 11:07:43 +08:00
|
|
|
|
public FlvClipProcessor(FlvMetadata header, List<FlvTag> head, List<FlvTag> past, uint future)
|
2018-03-12 18:57:20 +08:00
|
|
|
|
{
|
2018-03-13 13:21:01 +08:00
|
|
|
|
Header = header;
|
2018-03-24 08:34:57 +08:00
|
|
|
|
HTags = head;
|
2018-03-19 16:51:35 +08:00
|
|
|
|
Tags = past;
|
2018-03-24 11:07:43 +08:00
|
|
|
|
target = Tags[Tags.Count - 1].TimeStamp + (int)(future * 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-03-12 18:57:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-19 01:05:02 +08:00
|
|
|
|
public void AddTag(FlvTag 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()
|
2018-03-26 02:56:56 +08:00
|
|
|
|
{
|
|
|
|
|
try
|
2018-03-19 16:51:35 +08:00
|
|
|
|
{
|
2018-03-27 06:10:30 +08:00
|
|
|
|
string filepath = GetFileName();
|
|
|
|
|
using (var fs = new FileStream(filepath, FileMode.CreateNew, FileAccess.ReadWrite))
|
2018-03-26 02:57:17 +08:00
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
2018-03-26 02:57:17 +08:00
|
|
|
|
var offset = Tags[0].TimeStamp;
|
2018-03-27 15:53:14 +08:00
|
|
|
|
Tags.ForEach(tag => tag.TimeStamp -= (tag.TimeStamp < offset ? tag.TimeStamp : offset));
|
2018-03-19 16:51:35 +08:00
|
|
|
|
|
2018-03-26 02:57:17 +08:00
|
|
|
|
Header.Meta["duration"] = Tags[Tags.Count - 1].TimeStamp / 1000.0;
|
|
|
|
|
Header.Meta["lasttimestamp"] = (double)Tags[Tags.Count - 1].TimeStamp;
|
2018-03-19 16:51:35 +08:00
|
|
|
|
|
2018-03-26 02:57:17 +08:00
|
|
|
|
var t = new FlvTag
|
|
|
|
|
{
|
|
|
|
|
TagType = TagType.DATA,
|
|
|
|
|
Data = Header.ToBytes()
|
|
|
|
|
};
|
|
|
|
|
t.WriteTo(fs);
|
2018-03-19 16:51:35 +08:00
|
|
|
|
|
2018-03-26 02:57:17 +08:00
|
|
|
|
HTags.ForEach(tag => tag.WriteTo(fs));
|
|
|
|
|
Tags.ForEach(tag => tag.WriteTo(fs));
|
|
|
|
|
|
2018-03-27 06:10:30 +08:00
|
|
|
|
logger.Info("剪辑已保存:{0}", Path.GetFileName(filepath));
|
|
|
|
|
|
2018-03-26 02:57:17 +08:00
|
|
|
|
fs.Close();
|
|
|
|
|
}
|
|
|
|
|
Tags.Clear();
|
2018-03-19 16:51:35 +08:00
|
|
|
|
|
2018-03-26 02:57:17 +08:00
|
|
|
|
ClipFinalized?.Invoke(this, new ClipFinalizedArgs() { ClipProcessor = this });
|
2018-03-26 02:56:56 +08:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
logger.Error(ex, "保存剪辑文件时出错");
|
|
|
|
|
}
|
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
|
|
|
|
}
|
|
|
|
|
}
|