Skip to content

Commit

Permalink
增加快照切片功能
Browse files Browse the repository at this point in the history
  • Loading branch information
CHKZL committed Sep 7, 2024
1 parent b871d04 commit 5de62af
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 50 deletions.
10 changes: 5 additions & 5 deletions Core/RuntimeObject/Danmu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,11 @@ public static void SevaDanmu(LiveChat.LiveChatListener liveChatListener, bool De
/// <summary>
/// 储存原始弹幕信息到xml文件
/// </summary>
/// <param name="danmuInfo"></param>
/// <param name="FileName"></param>
/// <param name="Name"></param>
/// <param name="roomId"></param>
private static FileInfo SevaDanmu(List<DanmuInfo> danmuInfo, string FileName, string Name, long roomId)
/// <param name="danmuInfo">弹幕信息对象</param>
/// <param name="FileName">保存路径</param>
/// <param name="Name">昵称</param>
/// <param name="roomId">房间号</param>
public static FileInfo SevaDanmu(List<DanmuInfo> danmuInfo, string FileName, string Name, long roomId)
{
string XML = string.Empty;
XML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
Expand Down
10 changes: 8 additions & 2 deletions Core/RuntimeObject/Download/Basics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,12 @@ internal static bool GetHlsHost_avc(RoomCardClass roomCard, ref HostClass hostCl
}



/// <summary>
/// 识别M3U8文件格式适配二级M3U8
/// </summary>
/// <param name="M3U8"></param>
/// <param name="hostClass"></param>
/// <returns></returns>
internal static string Senior_M3U8_Analysis(string M3U8, ref HostClass hostClass)
{
if (string.IsNullOrEmpty(M3U8) || !M3U8.Contains("index.m3u8"))
Expand All @@ -252,6 +257,8 @@ internal static string Senior_M3U8_Analysis(string M3U8, ref HostClass hostClass
}
return M3U8;
}


/// <summary>
/// 刷新HlsHost信息
/// </summary>
Expand Down Expand Up @@ -410,7 +417,6 @@ public static List<long> GetOptionalClarity(long RoomId, string protocol_name, s
}



public static void LiveChatListener_MessageReceived(object? sender, Core.LiveChat.MessageEventArgs e)
{
LiveChatListener liveChatListener = (LiveChatListener)sender;
Expand Down
2 changes: 1 addition & 1 deletion Core/RuntimeObject/Download/FLV.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ await Task.Run(async () =>
HostClass hostClass = GetFlvHost_avc(card);
string DlwnloadURL = $"{hostClass.host}{hostClass.base_url}{hostClass.uri_name}{hostClass.extra}";
//把当前写入文件写入记录
string F_S = Config.Core_RunConfig._RecordingStorageDirectory + "/" + File.Replace(Config.Core_RunConfig._RecFileDirectory, "").Replace("\\", "/");
string F_S = Config.Core_RunConfig._RecFileDirectory + "/" + File.Replace(Config.Core_RunConfig._RecFileDirectory, "").Replace("\\", "/");
card.DownInfo.DownloadFileList.CurrentOperationVideoFile = F_S;
//下载提示
LogDownloadStart(card, "FLV");
Expand Down
2 changes: 1 addition & 1 deletion Core/RuntimeObject/Download/HLS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ await Task.Run(() =>
if (InitialRequest)
{
//把当前写入文件写入记录
string F_S = Config.Core_RunConfig._RecordingStorageDirectory + "/" + fs.Name.Replace(new DirectoryInfo(Config.Core_RunConfig._RecFileDirectory).FullName, "").Replace("\\", "/");
string F_S = Config.Core_RunConfig._RecFileDirectory + "/" + fs.Name.Replace(new DirectoryInfo(Config.Core_RunConfig._RecFileDirectory).FullName, "").Replace("\\", "/");
card.DownInfo.DownloadFileList.CurrentOperationVideoFile = F_S;
Log.Debug("test",card.DownInfo.DownloadFileList.CurrentOperationVideoFile);
//正式开始下载提示
Expand Down
42 changes: 42 additions & 0 deletions Core/RuntimeObject/Download/Snapshot.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Core.LogModule;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Core.RuntimeObject.Download
{
public class Snapshot
{
/// <summary>
/// 生成录制中的直播间快照用于切片
/// </summary>
/// <param name="Uid"></param>
/// <returns></returns>
public static (bool state,string message) CreateRecordingSnapshot(long Uid)
{
if (Uid == 0) return (false,"UID不能为空");

RoomCardClass Card = new();
if (!_Room.GetCardForUID(Uid, ref Card) || Card == null || !Card.DownInfo.IsDownload) return (false,"当前房间未开播或未录制");

string videoFile = Card.DownInfo.DownloadFileList.CurrentOperationVideoFile;
if (!File.Exists(videoFile)) return (false,"当前直播间还未开始录制流");

string tempFile = $"{Core.Config.Core_RunConfig._TemporaryFileDirectory}{Path.GetFileName(videoFile)}";
File.Copy(videoFile, tempFile, true);

var listener = Card.DownInfo.LiveChatListener;
if (listener != null)
{
Danmu.SevaDanmu(listener.DanmuMessage.Danmu, tempFile, Card.Name, Card.RoomId);
Danmu.SevaGift(listener.DanmuMessage.Gift, tempFile);
Danmu.SevaGuardBuy(listener.DanmuMessage.GuardBuy, tempFile);
Danmu.SevaSuperChat(listener.DanmuMessage.SuperChat, tempFile);
}
return (true,tempFile);
}
}
}
82 changes: 41 additions & 41 deletions Core/RuntimeObject/RoomInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -725,28 +725,28 @@ internal static void BatchUpdateRoomStatusForLiveStream(List<long>? UIDList = nu
/// <param name="UIDList"></param>
internal static void _BatchUpdateRoomStatusForLiveStream(List<long> UIDList)
{

UidsInfo_Class uidsInfo_Class = GetRoomList(UIDList);
UIDList = null;
if (uidsInfo_Class != null && uidsInfo_Class.data != null && uidsInfo_Class.data.Count > 0)

UidsInfo_Class uidsInfo_Class = GetRoomList(UIDList);
UIDList = null;
if (uidsInfo_Class != null && uidsInfo_Class.data != null && uidsInfo_Class.data.Count > 0)
{
foreach (var item in uidsInfo_Class.data)
{
foreach (var item in uidsInfo_Class.data)
long.TryParse(item.Key, out long uid);
if (uid > 0)
{
long.TryParse(item.Key, out long uid);
if (uid > 0)
RoomCardClass roomCard = new();
if (_Room.GetCardForUID(uid, ref roomCard))
{
RoomCardClass roomCard = new();
if (_Room.GetCardForUID(uid, ref roomCard))
{
_Room.SetRoomCardByUid(uid, ToRoomCard(item.Value, roomCard));
}
roomCard = null;
_Room.SetRoomCardByUid(uid, ToRoomCard(item.Value, roomCard));
}
roomCard = null;
}
}
uidsInfo_Class = null;


}
uidsInfo_Class = null;


}

#endregion
Expand All @@ -756,7 +756,7 @@ internal static void _BatchUpdateRoomStatusForLiveStream(List<long> UIDList)

private static long _GetLiveTime(long Uid)
{
RoomCardClass roomCard = new();
RoomCardClass roomCard = new();
if (!_Room.GetCardForUID(Uid, ref roomCard))
{
roomCard = ToRoomCard(GetRoomInfo(GetRoomId(Uid)), roomCard);
Expand Down Expand Up @@ -903,7 +903,7 @@ private static RoomCardClass ToRoomCard(UidsInfo_Class.Data data, RoomCardClass
RoomCardClass card = new RoomCardClass()
{
UID = data.uid,
Title = new() { Value = data.title.Replace("/","-").Replace("\\","-"), ExpirationTime = DateTime.Now.AddSeconds(30) },
Title = new() { Value = data.title.Replace("/", "-").Replace("\\", "-"), ExpirationTime = DateTime.Now.AddSeconds(30) },
RoomId = data.room_id,
live_time = new() { Value = data.live_time, ExpirationTime = DateTime.Now.AddSeconds(30) },
live_status = new() { Value = data.live_status, ExpirationTime = DateTime.Now.AddSeconds(3) },
Expand Down Expand Up @@ -934,7 +934,7 @@ private static RoomCardClass ToRoomCard(UidsInfo_Class.Data data, RoomCardClass
else
{
OldCard.UID = data.uid;
OldCard.Title = new() { Value = data.title.Replace("/","-").Replace("\\","-"), ExpirationTime = DateTime.Now.AddSeconds(30) };
OldCard.Title = new() { Value = data.title.Replace("/", "-").Replace("\\", "-"), ExpirationTime = DateTime.Now.AddSeconds(30) };
OldCard.RoomId = data.room_id;
OldCard.live_time = new() { Value = data.live_time, ExpirationTime = DateTime.Now.AddSeconds(30) };

Expand Down Expand Up @@ -976,8 +976,8 @@ private static RoomCardClass ToRoomCard(UidsInfo_Class.Data data, RoomCardClass
}
catch (Exception ex)
{
string A = data != null ? JsonSerializer.Serialize(data, new JsonSerializerOptions() { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)}) : "内容为空";
string B = OldCard != null ? JsonSerializer.Serialize(OldCard, new JsonSerializerOptions() { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)}) : "内容为空";
string A = data != null ? JsonSerializer.Serialize(data, new JsonSerializerOptions() { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) }) : "内容为空";
string B = OldCard != null ? JsonSerializer.Serialize(OldCard, new JsonSerializerOptions() { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) }) : "内容为空";
Log.Error(nameof(ToRoomCard), $"在UidsInfo_Class.Data的TRC操作中出现意料外的错误,错误堆栈:[UidsInfo_Class.Data:{A}];[RoomCard:{B}]", ex, true);
return null;
}
Expand Down Expand Up @@ -1051,8 +1051,8 @@ private static RoomCardClass ToRoomCard(RoomInfo_Class roomInfo, RoomCardClass O
}
catch (Exception ex)
{
string A = roomInfo != null ? JsonSerializer.Serialize(roomInfo, new JsonSerializerOptions() { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)}) : "内容为空";
string B = OldCard != null ? JsonSerializer.Serialize(OldCard, new JsonSerializerOptions() { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)}) : "内容为空";
string A = roomInfo != null ? JsonSerializer.Serialize(roomInfo, new JsonSerializerOptions() { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) }) : "内容为空";
string B = OldCard != null ? JsonSerializer.Serialize(OldCard, new JsonSerializerOptions() { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) }) : "内容为空";
Log.Error(nameof(ToRoomCard), $"在RoomInfo_Class的TRC操作中出现意料外的错误,错误堆栈:[RoomInfo_Class:{A}];[RoomCard:{B}]", ex, true);
return null;
}
Expand All @@ -1073,7 +1073,7 @@ private static RoomCardClass ToRoomCard(UserInfo userInfo, RoomCardClass OldCard
Name = userInfo.data.name,
url = new() { Value = $"https://live.bilibili.com/{userInfo.data.live_room.roomid}", ExpirationTime = DateTime.MaxValue },
roomStatus = new() { Value = userInfo.data.live_room.liveStatus, ExpirationTime = DateTime.Now.AddSeconds(3) },
Title = new() { Value = userInfo.data.live_room.title.Replace("/","-").Replace("\\","-"), ExpirationTime = DateTime.Now.AddSeconds(30) },
Title = new() { Value = userInfo.data.live_room.title.Replace("/", "-").Replace("\\", "-"), ExpirationTime = DateTime.Now.AddSeconds(30) },
cover_from_user = new() { Value = userInfo.data.live_room.cover, ExpirationTime = DateTime.Now.AddMinutes(10) },
face = new() { Value = userInfo.data.face, ExpirationTime = DateTime.MaxValue },
sex = new() { Value = userInfo.data.sex, ExpirationTime = DateTime.MaxValue },
Expand All @@ -1089,7 +1089,7 @@ private static RoomCardClass ToRoomCard(UserInfo userInfo, RoomCardClass OldCard
OldCard.Name = userInfo.data.name;
OldCard.url = new() { Value = $"https://live.bilibili.com/{userInfo.data.live_room.roomid}", ExpirationTime = DateTime.MaxValue };
OldCard.roomStatus = new() { Value = userInfo.data.live_room.liveStatus, ExpirationTime = DateTime.Now.AddSeconds(3) };
OldCard.Title = new() { Value = userInfo.data.live_room.title.Replace("/","-").Replace("\\","-"), ExpirationTime = DateTime.Now.AddSeconds(30) };
OldCard.Title = new() { Value = userInfo.data.live_room.title.Replace("/", "-").Replace("\\", "-"), ExpirationTime = DateTime.Now.AddSeconds(30) };
OldCard.cover_from_user = new() { Value = userInfo.data.live_room.cover, ExpirationTime = DateTime.Now.AddMinutes(10) };
OldCard.face = new() { Value = userInfo.data.face, ExpirationTime = DateTime.MaxValue };
OldCard.sex = new() { Value = userInfo.data.sex, ExpirationTime = DateTime.MaxValue };
Expand All @@ -1106,8 +1106,8 @@ private static RoomCardClass ToRoomCard(UserInfo userInfo, RoomCardClass OldCard
catch (Exception ex)
{

string userInfoContent = userInfo != null ? JsonSerializer.Serialize(userInfo, new JsonSerializerOptions() { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)}) : "内容为空";
string oldCardContent = OldCard != null ? JsonSerializer.Serialize(OldCard, new JsonSerializerOptions() { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)}) : "内容为空";
string userInfoContent = userInfo != null ? JsonSerializer.Serialize(userInfo, new JsonSerializerOptions() { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) }) : "内容为空";
string oldCardContent = OldCard != null ? JsonSerializer.Serialize(OldCard, new JsonSerializerOptions() { Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) }) : "内容为空";
Log.Error(nameof(ToRoomCard), $"在UserInfo的TRC操作中出现意料外的错误,错误原始数据:[userInfo:{userInfoContent}];[RoomCard:{oldCardContent}];堆栈:{ex.ToString}", ex, true);
return null;
}
Expand Down Expand Up @@ -1340,22 +1340,22 @@ public class RoomCardClass
/// 轮播状态(0:未轮播 1:轮播)
/// </summary>
public ExpansionType<int> roundStatus = new() { ExpirationTime = DateTime.UnixEpoch, Value = -1 };
[JsonIgnore]
[JsonIgnore]
/// <summary>
/// 直播间网页url
/// </summary>
public ExpansionType<string> url = new() { ExpirationTime = DateTime.UnixEpoch, Value = string.Empty };
[JsonIgnore]
[JsonIgnore]
/// <summary>
/// 用户等级
/// </summary>
public ExpansionType<int> level = new() { ExpirationTime = DateTime.UnixEpoch, Value = -1 };
[JsonIgnore]
[JsonIgnore]
/// <summary>
/// 主播性别
/// </summary>
public ExpansionType<string> sex = new() { ExpirationTime = DateTime.UnixEpoch, Value = string.Empty };
[JsonIgnore]
[JsonIgnore]
/// <summary>
/// 主播简介
/// </summary>
Expand All @@ -1378,35 +1378,35 @@ public class DownloadInfo
/// <summary>
/// 当前是否在下载
/// </summary>
public bool IsDownload = false;
public bool IsDownload { set; get; } = false;
/// <summary>
/// 是否触发瞎几把剪
/// </summary>
public bool IsCut = false;
public bool IsCut { set; get; } = false;
/// <summary>
/// 任务类型
/// </summary>
public TaskType taskType = TaskType.NewTask;
public TaskType taskType { set; get; } = TaskType.NewTask;
/// <summary>
/// 当前房间下载任务总大小
/// </summary>
public long DownloadSize = 0;
public long DownloadSize { set; get; } = 0;
/// <summary>
/// 实时下载速度
/// </summary>
public double RealTimeDownloadSpe = 0;
public double RealTimeDownloadSpe { set; get; } = 0;
/// <summary>
/// 任务状态
/// </summary>
public DownloadStatus Status = DownloadStatus.NewTask;
public DownloadStatus Status { set; get; } = DownloadStatus.NewTask;
/// <summary>
/// 任务开始时间
/// </summary>
public DateTime StartTime = DateTime.UnixEpoch;
public DateTime StartTime { set; get; } = DateTime.UnixEpoch;
/// <summary>
/// 任务结束时间
/// </summary>
public DateTime EndTime = DateTime.UnixEpoch;
public DateTime EndTime { set; get; } = DateTime.UnixEpoch;
/// <summary>
/// 弹幕对象
/// </summary>
Expand All @@ -1416,11 +1416,11 @@ public class DownloadInfo
/// <summary>
/// 取消录制标记
/// </summary>
public bool Unmark = false;
public bool Unmark { set; get; } = false;
/// <summary>
/// 该录制任务的文件名缓存
/// </summary>
public DownloadFile DownloadFileList = new();
public DownloadFile DownloadFileList { set; get; } = new();

public class DownloadFile
{
Expand Down
3 changes: 3 additions & 0 deletions Desktop/NetWork/Post.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ public class Post
/// <returns>请求返回体</returns>
public static async Task<T> PostBody<T>(string url, Dictionary<string, string> _dic = null)
{

if (!string.IsNullOrEmpty(url) && url.Length > 5 && url.Substring(0, 4) != "http")
{
url = "http://" + url;
}

try
{
Dictionary<string, string> dic = new Dictionary<string, string>
Expand All @@ -58,6 +60,7 @@ public static async Task<T> PostBody<T>(string url, Dictionary<string, string> _
var response = await client.PostAsync(url, content);
var responseString = response.Content.ReadAsStringAsync().Result;
OperationQueue.pack<T> A = JsonConvert.DeserializeObject<OperationQueue.pack<T>>(responseString);

return A.data;
}
}
Expand Down
3 changes: 3 additions & 0 deletions Desktop/Views/Control/CardControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
<MenuItem Header="切换提醒开关" Click="MenuItem_ModifyRoom_Remind_Click"/>
<Separator Visibility="{Binding Rec_Status_IsVisible}"/>
<MenuItem Visibility="{Binding Rec_Status_IsVisible}" Header="取消录制" Click="Cancel_Task_Click"/>
<Separator Visibility="{Binding Rec_Status_IsVisible}"/>
<MenuItem Visibility="{Binding Rec_Status_IsVisible}" Header="生成快照用于切片" Click="Snapshot_Task_Click"
ToolTipService.InitialShowDelay="100" ToolTipService.Placement="MousePoint" ToolTipService.ToolTip="【弱鸡硬盘慎用,会卡】在不影响主进程录制的情况下,将当前录制中的文件输出一份到临时文件夹方便使用(需要自行fix或转码,临时文件夹为DDTV文件中的Temporary)"/>
<Separator />
<MenuItem Header="删除房间" Click="DelRoom_Click"/>
</ContextMenu>
Expand Down
Loading

0 comments on commit 5de62af

Please sign in to comment.