diff --git a/src/N_m3u8DL-RE.Common/Entity/StreamSpec.cs b/src/N_m3u8DL-RE.Common/Entity/StreamSpec.cs
index d9db4f1..4c03f2c 100644
--- a/src/N_m3u8DL-RE.Common/Entity/StreamSpec.cs
+++ b/src/N_m3u8DL-RE.Common/Entity/StreamSpec.cs
@@ -39,8 +39,16 @@ namespace N_m3u8DL_RE.Common.Entity
public string? PeriodId { get; set; }
+ ///
+ /// URL
+ ///
public string Url { get; set; }
+ ///
+ /// 原始URL
+ ///
+ public string OriginalUrl { get; set; }
+
public Playlist? Playlist { get; set; }
public string ToShortString()
diff --git a/src/N_m3u8DL-RE.Parser/Config/ParserConfig.cs b/src/N_m3u8DL-RE.Parser/Config/ParserConfig.cs
index e377345..52e2831 100644
--- a/src/N_m3u8DL-RE.Parser/Config/ParserConfig.cs
+++ b/src/N_m3u8DL-RE.Parser/Config/ParserConfig.cs
@@ -9,6 +9,8 @@ namespace N_m3u8DL_RE.Parser.Config
{
public string Url { get; set; }
+ public string OriginalUrl { get; set; }
+
public string BaseUrl { get; set; }
public Dictionary Headers { get; set; } = new Dictionary();
diff --git a/src/N_m3u8DL-RE.Parser/Extractor/DASHExtractor2.cs b/src/N_m3u8DL-RE.Parser/Extractor/DASHExtractor2.cs
index 3a4bb9a..e2391e8 100644
--- a/src/N_m3u8DL-RE.Parser/Extractor/DASHExtractor2.cs
+++ b/src/N_m3u8DL-RE.Parser/Extractor/DASHExtractor2.cs
@@ -138,6 +138,7 @@ namespace N_m3u8DL_RE.Parser.Extractor
}
var bandwidth = representation.Attribute("bandwidth");
StreamSpec streamSpec = new();
+ streamSpec.OriginalUrl = ParserConfig.OriginalUrl;
streamSpec.PeriodId = periodId;
streamSpec.Playlist = new Playlist();
streamSpec.Playlist.MediaParts.Add(new MediaPart());
@@ -481,7 +482,8 @@ namespace N_m3u8DL_RE.Parser.Extractor
public async Task RefreshPlayListAsync(List streamSpecs)
{
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);
foreach (var streamSpec in streamSpecs)
{
diff --git a/src/N_m3u8DL-RE.Parser/Extractor/HLSExtractor.cs b/src/N_m3u8DL-RE.Parser/Extractor/HLSExtractor.cs
index a075fe4..870d4cb 100644
--- a/src/N_m3u8DL-RE.Parser/Extractor/HLSExtractor.cs
+++ b/src/N_m3u8DL-RE.Parser/Extractor/HLSExtractor.cs
@@ -22,6 +22,8 @@ namespace N_m3u8DL_RE.Parser.Extractor
private string M3u8Url = string.Empty;
private string BaseUrl = string.Empty;
private string M3u8Content = string.Empty;
+ private bool MasterM3u8Flag = false;
+ private bool FirstRefreshFlag = true;
public ParserConfig ParserConfig { get; set; }
@@ -84,7 +86,8 @@ namespace N_m3u8DL_RE.Parser.Extractor
private bool IsMaster()
{
- return M3u8Content.Contains(HLSTags.ext_x_stream_inf);
+ MasterM3u8Flag = M3u8Content.Contains(HLSTags.ext_x_stream_inf);
+ return MasterM3u8Flag;
}
private async Task> ParseMasterListAsync()
@@ -104,6 +107,7 @@ namespace N_m3u8DL_RE.Parser.Extractor
if (line.StartsWith(HLSTags.ext_x_stream_inf))
{
streamSpec = new();
+ streamSpec.OriginalUrl = ParserConfig.OriginalUrl;
var bandwidth = string.IsNullOrEmpty(ParserUtil.GetAttribute(line, "AVERAGE-BANDWIDTH")) ? ParserUtil.GetAttribute(line, "BANDWIDTH") : ParserUtil.GetAttribute(line, "AVERAGE-BANDWIDTH");
streamSpec.Bandwidth = Convert.ToInt32(bandwidth);
streamSpec.Codecs = ParserUtil.GetAttribute(line, "CODECS");
@@ -505,6 +509,23 @@ namespace N_m3u8DL_RE.Parser.Extractor
public async Task FetchPlayListAsync(List 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++)
{
//重新加载m3u8
@@ -522,6 +543,9 @@ namespace N_m3u8DL_RE.Parser.Extractor
lists[i].Extension = lists[i].Playlist!.MediaInit != null ? "m4s" : "ts";
}
}
+
+ //首次刷新已结束,后续重新加载时应该从master开始重新加载
+ FirstRefreshFlag = false;
}
public async Task RefreshPlayListAsync(List streamSpecs)
diff --git a/src/N_m3u8DL-RE.Parser/StreamExtractor.cs b/src/N_m3u8DL-RE.Parser/StreamExtractor.cs
index de376de..b487a49 100644
--- a/src/N_m3u8DL-RE.Parser/StreamExtractor.cs
+++ b/src/N_m3u8DL-RE.Parser/StreamExtractor.cs
@@ -34,10 +34,11 @@ namespace N_m3u8DL_RE.Parser
{
var uri = new Uri(url);
this.rawText = File.ReadAllText(uri.LocalPath);
- parserConfig.Url = url;
+ parserConfig.OriginalUrl = parserConfig.Url = url;
}
else if (url.StartsWith("http"))
{
+ parserConfig.OriginalUrl = url;
(this.rawText, url) = HTTPUtil.GetWebSourceAndNewUrlAsync(url, parserConfig.Headers).Result;
parserConfig.Url = url;
}
@@ -45,7 +46,7 @@ namespace N_m3u8DL_RE.Parser
{
url = Path.GetFullPath(url);
this.rawText = File.ReadAllText(url);
- parserConfig.Url = new Uri(url).AbsoluteUri;
+ parserConfig.OriginalUrl = parserConfig.Url = new Uri(url).AbsoluteUri;
}
this.rawText = rawText.Trim();
LoadSourceFromText(this.rawText);
diff --git a/src/N_m3u8DL-RE/DownloadManager/SimpleLiveRecordManager2.cs b/src/N_m3u8DL-RE/DownloadManager/SimpleLiveRecordManager2.cs
index 894a0d3..8f576d9 100644
--- a/src/N_m3u8DL-RE/DownloadManager/SimpleLiveRecordManager2.cs
+++ b/src/N_m3u8DL-RE/DownloadManager/SimpleLiveRecordManager2.cs
@@ -214,7 +214,7 @@ namespace N_m3u8DL_RE.DownloadManager
var seg = segments.First();
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 path = Path.Combine(tmpDir, filename + $".{streamSpec.Extension ?? "clip"}.tmp");
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, _) =>
{
//获取文件名
- 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 path = Path.Combine(tmpDir, filename + $".{streamSpec.Extension ?? "clip"}.tmp");
var result = await Downloader.DownloadSegmentAsync(seg, path, speedContainer, headers);