Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/N_m3u8DL-RE.Common/Resource/ResString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public static class ResString
public static string liveLimit => GetText("liveLimit");
public static string realTimeDecMessage => GetText("realTimeDecMessage");
public static string liveLimitReached => GetText("liveLimitReached");
public static string liveFinished => GetText("liveFinished");
public static string saveName => GetText("saveName");
public static string taskStartAt => GetText("taskStartAt");
public static string namedPipeCreated => GetText("namedPipeCreated");
Expand Down
6 changes: 6 additions & 0 deletions src/N_m3u8DL-RE.Common/Resource/StaticText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,12 @@ internal static class StaticText
zhTW: "到達直播錄製上限,即將停止錄製",
enUS: "Live recording limit reached, will stop recording soon"
),
["liveFinished"] = new TextContainer
(
zhCN: "直播已结束,即将停止录制",
zhTW: "直播已結束,即將停止錄製",
enUS: "Livestream seems to have ended, will stop recording"
),
["saveName"] = new TextContainer
(
zhCN: "保存文件名: ",
Expand Down
8 changes: 6 additions & 2 deletions src/N_m3u8DL-RE.Parser/Extractor/HLSExtractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -547,10 +547,14 @@ public async Task FetchPlayListAsync(List<StreamSpec> lists)

var newPlaylist = await ParseListAsync();
if (lists[i].Playlist?.MediaInit != null)
{
lists[i].Playlist!.MediaParts = newPlaylist.MediaParts; // 不更新init
lists[i].Playlist!.IsLive = newPlaylist.IsLive;
}
else
{
lists[i].Playlist = newPlaylist;

}
if (lists[i].MediaType == MediaType.SUBTITLES)
{
var a = lists[i].Playlist!.MediaParts.Any(p => p.MediaSegments.Any(m => m.Url.Contains(".ttml")));
Expand All @@ -569,4 +573,4 @@ public async Task RefreshPlayListAsync(List<StreamSpec> streamSpecs)
{
await FetchPlayListAsync(streamSpecs);
}
}
}
20 changes: 17 additions & 3 deletions src/N_m3u8DL-RE/DownloadManager/SimpleLiveRecordManager2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ internal class SimpleLiveRecordManager2
ConcurrentDictionary<int, BufferBlock<List<MediaSegment>>> BlockDic = new(); // 各流的Block
ConcurrentDictionary<int, bool> SamePathDic = new(); // 各流是否allSamePath
ConcurrentDictionary<int, bool> RecordLimitReachedDic = new(); // 各流是否达到上限
ConcurrentDictionary<int, bool> LiveFinishedDic = new(); // 各流是否已完成
ConcurrentDictionary<int, string> LastFileNameDic = new(); // 上次下载的文件名
ConcurrentDictionary<int, long> MaxIndexDic = new(); // 最大Index
ConcurrentDictionary<int, long> DateTimeDic = new(); // 上次下载的dateTime
Expand Down Expand Up @@ -644,7 +645,6 @@ private async Task PlayListProduceAsync(Dictionary<StreamSpec, ProgressTask> dic
while (!STOP_FLAG)
{
if (WAIT_SEC == 0) continue;

// 1. MPD 所有URL相同 单次请求即可获得所有轨道的信息
// 2. M3U8 所有URL不同 才需要多次请求
await Parallel.ForEachAsync(dic, async (dic, _) =>
Expand All @@ -653,7 +653,7 @@ await Parallel.ForEachAsync(dic, async (dic, _) =>
var task = dic.Value;

// 达到上限时 不需要刷新了
if (RecordLimitReachedDic[task.Id])
if (RecordLimitReachedDic[task.Id] || LiveFinishedDic[task.Id])
return;

var allHasDatetime = streamSpec.Playlist!.MediaParts[0].MediaSegments.All(s => s.DateTime != null);
Expand All @@ -679,10 +679,16 @@ await Parallel.ForEachAsync(dic, async (dic, _) =>
// 累加已获取到的时长
RefreshedDurDic[task.Id] += (int)newList.Sum(s => s.Duration);
}
else if (!streamSpec.Playlist!.IsLive && BlockDic[task.Id].Count == 0)
{
LiveFinishedDic[task.Id] = true;
BlockDic[task.Id].Complete();
}

if (!STOP_FLAG && RefreshedDurDic[task.Id] >= DownloaderConfig.MyOptions.LiveRecordLimit?.TotalSeconds)
{
RecordLimitReachedDic[task.Id] = true;
BlockDic[task.Id].Complete();
}

// 检测时长限制
Expand All @@ -692,6 +698,13 @@ await Parallel.ForEachAsync(dic, async (dic, _) =>
STOP_FLAG = true;
CancellationTokenSource.Cancel();
}

// 检测直播是否已结束
if (!STOP_FLAG && LiveFinishedDic.Values.All(x => x))
{
Logger.WarnMarkUp($"[darkorange3_1]{ResString.liveFinished}[/]");
STOP_FLAG = true;
}
});

try
Expand Down Expand Up @@ -822,6 +835,7 @@ await progress.StartAsync(async ctx =>
}
LastFileNameDic[task.Id] = "";
RecordLimitReachedDic[task.Id] = false;
LiveFinishedDic[task.Id] = false;
DateTimeDic[task.Id] = 0L;
RecordedDurDic[task.Id] = 0;
RefreshedDurDic[task.Id] = 0;
Expand Down Expand Up @@ -918,4 +932,4 @@ await Parallel.ForEachAsync(dic, options, async (kp, _) =>

return success;
}
}
}