优化直播刷新逻辑

This commit is contained in:
nilaoda 2022-09-27 18:28:14 +08:00
parent f2a70562cd
commit c0c821da63
6 changed files with 43 additions and 6 deletions

View File

@ -39,8 +39,16 @@ namespace N_m3u8DL_RE.Common.Entity
public string? PeriodId { get; set; } public string? PeriodId { get; set; }
/// <summary>
/// URL
/// </summary>
public string Url { get; set; } public string Url { get; set; }
/// <summary>
/// 原始URL
/// </summary>
public string OriginalUrl { get; set; }
public Playlist? Playlist { get; set; } public Playlist? Playlist { get; set; }
public string ToShortString() public string ToShortString()

View File

@ -9,6 +9,8 @@ namespace N_m3u8DL_RE.Parser.Config
{ {
public string Url { get; set; } public string Url { get; set; }
public string OriginalUrl { get; set; }
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
public Dictionary<string, string> Headers { get; set; } = new Dictionary<string, string>(); public Dictionary<string, string> Headers { get; set; } = new Dictionary<string, string>();

View File

@ -138,6 +138,7 @@ namespace N_m3u8DL_RE.Parser.Extractor
} }
var bandwidth = representation.Attribute("bandwidth"); var bandwidth = representation.Attribute("bandwidth");
StreamSpec streamSpec = new(); StreamSpec streamSpec = new();
streamSpec.OriginalUrl = ParserConfig.OriginalUrl;
streamSpec.PeriodId = periodId; streamSpec.PeriodId = periodId;
streamSpec.Playlist = new Playlist(); streamSpec.Playlist = new Playlist();
streamSpec.Playlist.MediaParts.Add(new MediaPart()); streamSpec.Playlist.MediaParts.Add(new MediaPart());
@ -481,7 +482,8 @@ namespace N_m3u8DL_RE.Parser.Extractor
public async Task RefreshPlayListAsync(List<StreamSpec> streamSpecs) public async Task RefreshPlayListAsync(List<StreamSpec> streamSpecs)
{ {
if (streamSpecs.Count == 0) return; if (streamSpecs.Count == 0) return;
var rawText = await HTTPUtil.GetWebSourceAsync(ParserConfig.Url); var (rawText, url) = await HTTPUtil.GetWebSourceAndNewUrlAsync(ParserConfig.OriginalUrl, ParserConfig.Headers);
ParserConfig.Url = url;
var newStreams = await ExtractStreamsAsync(rawText); var newStreams = await ExtractStreamsAsync(rawText);
foreach (var streamSpec in streamSpecs) foreach (var streamSpec in streamSpecs)
{ {

View File

@ -22,6 +22,8 @@ namespace N_m3u8DL_RE.Parser.Extractor
private string M3u8Url = string.Empty; private string M3u8Url = string.Empty;
private string BaseUrl = string.Empty; private string BaseUrl = string.Empty;
private string M3u8Content = string.Empty; private string M3u8Content = string.Empty;
private bool MasterM3u8Flag = false;
private bool FirstRefreshFlag = true;
public ParserConfig ParserConfig { get; set; } public ParserConfig ParserConfig { get; set; }
@ -84,7 +86,8 @@ namespace N_m3u8DL_RE.Parser.Extractor
private bool IsMaster() private bool IsMaster()
{ {
return M3u8Content.Contains(HLSTags.ext_x_stream_inf); MasterM3u8Flag = M3u8Content.Contains(HLSTags.ext_x_stream_inf);
return MasterM3u8Flag;
} }
private async Task<List<StreamSpec>> ParseMasterListAsync() private async Task<List<StreamSpec>> ParseMasterListAsync()
@ -104,6 +107,7 @@ namespace N_m3u8DL_RE.Parser.Extractor
if (line.StartsWith(HLSTags.ext_x_stream_inf)) if (line.StartsWith(HLSTags.ext_x_stream_inf))
{ {
streamSpec = new(); streamSpec = new();
streamSpec.OriginalUrl = ParserConfig.OriginalUrl;
var bandwidth = string.IsNullOrEmpty(ParserUtil.GetAttribute(line, "AVERAGE-BANDWIDTH")) ? ParserUtil.GetAttribute(line, "BANDWIDTH") : ParserUtil.GetAttribute(line, "AVERAGE-BANDWIDTH"); var bandwidth = string.IsNullOrEmpty(ParserUtil.GetAttribute(line, "AVERAGE-BANDWIDTH")) ? ParserUtil.GetAttribute(line, "BANDWIDTH") : ParserUtil.GetAttribute(line, "AVERAGE-BANDWIDTH");
streamSpec.Bandwidth = Convert.ToInt32(bandwidth); streamSpec.Bandwidth = Convert.ToInt32(bandwidth);
streamSpec.Codecs = ParserUtil.GetAttribute(line, "CODECS"); streamSpec.Codecs = ParserUtil.GetAttribute(line, "CODECS");
@ -505,6 +509,23 @@ namespace N_m3u8DL_RE.Parser.Extractor
public async Task FetchPlayListAsync(List<StreamSpec> lists) public async Task FetchPlayListAsync(List<StreamSpec> lists)
{ {
if (MasterM3u8Flag && !FirstRefreshFlag)
{
//重新加载master m3u8, 刷新选中流的URL
await LoadM3u8FromUrlAsync(ParserConfig.OriginalUrl);
var newStreams = await ParseMasterListAsync();
newStreams = newStreams.DistinctBy(p => p.Url).ToList();
foreach (var l in lists)
{
var match = newStreams.Where(n => n.ToShortString() == l.ToShortString());
if (match.Any())
{
Logger.DebugMarkUp($"{l.Url} => {match.First().Url}");
l.Url = match.First().Url;
}
}
}
for (int i = 0; i < lists.Count; i++) for (int i = 0; i < lists.Count; i++)
{ {
//重新加载m3u8 //重新加载m3u8
@ -522,6 +543,9 @@ namespace N_m3u8DL_RE.Parser.Extractor
lists[i].Extension = lists[i].Playlist!.MediaInit != null ? "m4s" : "ts"; lists[i].Extension = lists[i].Playlist!.MediaInit != null ? "m4s" : "ts";
} }
} }
//首次刷新已结束后续重新加载时应该从master开始重新加载
FirstRefreshFlag = false;
} }
public async Task RefreshPlayListAsync(List<StreamSpec> streamSpecs) public async Task RefreshPlayListAsync(List<StreamSpec> streamSpecs)

View File

@ -34,10 +34,11 @@ namespace N_m3u8DL_RE.Parser
{ {
var uri = new Uri(url); var uri = new Uri(url);
this.rawText = File.ReadAllText(uri.LocalPath); this.rawText = File.ReadAllText(uri.LocalPath);
parserConfig.Url = url; parserConfig.OriginalUrl = parserConfig.Url = url;
} }
else if (url.StartsWith("http")) else if (url.StartsWith("http"))
{ {
parserConfig.OriginalUrl = url;
(this.rawText, url) = HTTPUtil.GetWebSourceAndNewUrlAsync(url, parserConfig.Headers).Result; (this.rawText, url) = HTTPUtil.GetWebSourceAndNewUrlAsync(url, parserConfig.Headers).Result;
parserConfig.Url = url; parserConfig.Url = url;
} }
@ -45,7 +46,7 @@ namespace N_m3u8DL_RE.Parser
{ {
url = Path.GetFullPath(url); url = Path.GetFullPath(url);
this.rawText = File.ReadAllText(url); this.rawText = File.ReadAllText(url);
parserConfig.Url = new Uri(url).AbsoluteUri; parserConfig.OriginalUrl = parserConfig.Url = new Uri(url).AbsoluteUri;
} }
this.rawText = rawText.Trim(); this.rawText = rawText.Trim();
LoadSourceFromText(this.rawText); LoadSourceFromText(this.rawText);

View File

@ -214,7 +214,7 @@ namespace N_m3u8DL_RE.DownloadManager
var seg = segments.First(); var seg = segments.First();
segments = segments.Skip(1); segments = segments.Skip(1);
//获取文件名 //获取文件名
var filename = hls ? seg.Index.ToString(pad) : OtherUtil.GetFileNameFromInput(seg.Url, false); var filename = hls && seg.Index > 10 ? seg.Index.ToString(pad) : OtherUtil.GetFileNameFromInput(seg.Url, false);
var index = seg.Index; var index = seg.Index;
var path = Path.Combine(tmpDir, filename + $".{streamSpec.Extension ?? "clip"}.tmp"); var path = Path.Combine(tmpDir, filename + $".{streamSpec.Extension ?? "clip"}.tmp");
var result = await Downloader.DownloadSegmentAsync(seg, path, speedContainer, headers); var result = await Downloader.DownloadSegmentAsync(seg, path, speedContainer, headers);
@ -262,7 +262,7 @@ namespace N_m3u8DL_RE.DownloadManager
await Parallel.ForEachAsync(segments, options, async (seg, _) => await Parallel.ForEachAsync(segments, options, async (seg, _) =>
{ {
//获取文件名 //获取文件名
var filename = hls ? seg.Index.ToString(pad) : OtherUtil.GetFileNameFromInput(seg.Url, false); var filename = hls && seg.Index > 10 ? seg.Index.ToString(pad) : OtherUtil.GetFileNameFromInput(seg.Url, false);
var index = seg.Index; var index = seg.Index;
var path = Path.Combine(tmpDir, filename + $".{streamSpec.Extension ?? "clip"}.tmp"); var path = Path.Combine(tmpDir, filename + $".{streamSpec.Extension ?? "clip"}.tmp");
var result = await Downloader.DownloadSegmentAsync(seg, path, speedContainer, headers); var result = await Downloader.DownloadSegmentAsync(seg, path, speedContainer, headers);