Merge branch 'nilaoda:main' into main
This commit is contained in:
commit
22b103ae3f
|
@ -312,13 +312,14 @@ namespace N_m3u8DL_RE.Parser.Extractor
|
||||||
var initialization = segmentTemplate.Attribute("initialization")?.Value ?? segmentTemplateOuter.Attribute("initialization")?.Value;
|
var initialization = segmentTemplate.Attribute("initialization")?.Value ?? segmentTemplateOuter.Attribute("initialization")?.Value;
|
||||||
if (initialization != null)
|
if (initialization != null)
|
||||||
{
|
{
|
||||||
var initUrl = ParserUtil.ReplaceVars(ParserUtil.CombineURL(segBaseUrl, initialization), varDic);
|
var _init = ParserUtil.ReplaceVars(initialization, varDic);
|
||||||
|
var initUrl = ParserUtil.CombineURL(segBaseUrl, _init);
|
||||||
streamSpec.Playlist.MediaInit = new MediaSegment();
|
streamSpec.Playlist.MediaInit = new MediaSegment();
|
||||||
streamSpec.Playlist.MediaInit.Index = -1; //便于排序
|
streamSpec.Playlist.MediaInit.Index = -1; //便于排序
|
||||||
streamSpec.Playlist.MediaInit.Url = initUrl;
|
streamSpec.Playlist.MediaInit.Url = initUrl;
|
||||||
}
|
}
|
||||||
//处理分片
|
//处理分片
|
||||||
var media = segmentTemplate.Attribute("media")?.Value ?? segmentTemplateOuter.Attribute("media")?.Value;
|
var mediaTemplate = segmentTemplate.Attribute("media")?.Value ?? segmentTemplateOuter.Attribute("media")?.Value;
|
||||||
var segmentTimeline = segmentTemplate.Elements().Where(e => e.Name.LocalName == "SegmentTimeline").FirstOrDefault();
|
var segmentTimeline = segmentTemplate.Elements().Where(e => e.Name.LocalName == "SegmentTimeline").FirstOrDefault();
|
||||||
if (segmentTimeline != null)
|
if (segmentTimeline != null)
|
||||||
{
|
{
|
||||||
|
@ -340,11 +341,12 @@ namespace N_m3u8DL_RE.Parser.Extractor
|
||||||
var _repeatCount = Convert.ToInt64(_repeatCountStr);
|
var _repeatCount = Convert.ToInt64(_repeatCountStr);
|
||||||
varDic[DASHTags.TemplateTime] = currentTime;
|
varDic[DASHTags.TemplateTime] = currentTime;
|
||||||
varDic[DASHTags.TemplateNumber] = segNumber++;
|
varDic[DASHTags.TemplateNumber] = segNumber++;
|
||||||
var oriUrl = ParserUtil.CombineURL(segBaseUrl, media!);
|
var hasTime = mediaTemplate!.Contains(DASHTags.TemplateTime);
|
||||||
var mediaUrl = ParserUtil.ReplaceVars(oriUrl, varDic);
|
var media = ParserUtil.ReplaceVars(mediaTemplate!, varDic);
|
||||||
|
var mediaUrl = ParserUtil.CombineURL(segBaseUrl, media!);
|
||||||
MediaSegment mediaSegment = new();
|
MediaSegment mediaSegment = new();
|
||||||
mediaSegment.Url = mediaUrl;
|
mediaSegment.Url = mediaUrl;
|
||||||
if (oriUrl.Contains(DASHTags.TemplateTime))
|
if (hasTime)
|
||||||
mediaSegment.NameFromVar = currentTime.ToString();
|
mediaSegment.NameFromVar = currentTime.ToString();
|
||||||
mediaSegment.Duration = _duration / (double)timescale;
|
mediaSegment.Duration = _duration / (double)timescale;
|
||||||
mediaSegment.Index = segIndex++;
|
mediaSegment.Index = segIndex++;
|
||||||
|
@ -360,12 +362,13 @@ namespace N_m3u8DL_RE.Parser.Extractor
|
||||||
MediaSegment _mediaSegment = new();
|
MediaSegment _mediaSegment = new();
|
||||||
varDic[DASHTags.TemplateTime] = currentTime;
|
varDic[DASHTags.TemplateTime] = currentTime;
|
||||||
varDic[DASHTags.TemplateNumber] = segNumber++;
|
varDic[DASHTags.TemplateNumber] = segNumber++;
|
||||||
var _oriUrl = ParserUtil.CombineURL(segBaseUrl, media!);
|
var _hashTime = mediaTemplate!.Contains(DASHTags.TemplateTime);
|
||||||
var _mediaUrl = ParserUtil.ReplaceVars(_oriUrl, varDic);
|
var _media = ParserUtil.ReplaceVars(mediaTemplate!, varDic);
|
||||||
|
var _mediaUrl = ParserUtil.CombineURL(segBaseUrl, _media);
|
||||||
_mediaSegment.Url = _mediaUrl;
|
_mediaSegment.Url = _mediaUrl;
|
||||||
_mediaSegment.Index = segIndex++;
|
_mediaSegment.Index = segIndex++;
|
||||||
_mediaSegment.Duration = _duration / (double)timescale;
|
_mediaSegment.Duration = _duration / (double)timescale;
|
||||||
if (_oriUrl.Contains(DASHTags.TemplateTime))
|
if (_hashTime)
|
||||||
_mediaSegment.NameFromVar = currentTime.ToString();
|
_mediaSegment.NameFromVar = currentTime.ToString();
|
||||||
streamSpec.Playlist.MediaParts[0].MediaSegments.Add(_mediaSegment);
|
streamSpec.Playlist.MediaParts[0].MediaSegments.Add(_mediaSegment);
|
||||||
}
|
}
|
||||||
|
@ -396,11 +399,12 @@ namespace N_m3u8DL_RE.Parser.Extractor
|
||||||
for (long index = startNumber, segIndex = 0; index < startNumber + totalNumber; index++, segIndex++)
|
for (long index = startNumber, segIndex = 0; index < startNumber + totalNumber; index++, segIndex++)
|
||||||
{
|
{
|
||||||
varDic[DASHTags.TemplateNumber] = index;
|
varDic[DASHTags.TemplateNumber] = index;
|
||||||
var oriUrl = ParserUtil.CombineURL(segBaseUrl, media!);
|
var hasNumber = mediaTemplate!.Contains(DASHTags.TemplateNumber);
|
||||||
var mediaUrl = ParserUtil.ReplaceVars(oriUrl, varDic);
|
var media = ParserUtil.ReplaceVars(mediaTemplate!, varDic);
|
||||||
|
var mediaUrl = ParserUtil.CombineURL(segBaseUrl, media!);
|
||||||
MediaSegment mediaSegment = new();
|
MediaSegment mediaSegment = new();
|
||||||
mediaSegment.Url = mediaUrl;
|
mediaSegment.Url = mediaUrl;
|
||||||
if (oriUrl.Contains(DASHTags.TemplateNumber))
|
if (hasNumber)
|
||||||
mediaSegment.NameFromVar = index.ToString();
|
mediaSegment.NameFromVar = index.ToString();
|
||||||
mediaSegment.Index = isLive ? index : segIndex; //直播直接用startNumber
|
mediaSegment.Index = isLive ? index : segIndex; //直播直接用startNumber
|
||||||
mediaSegment.Duration = duration / (double)timescale;
|
mediaSegment.Duration = duration / (double)timescale;
|
||||||
|
|
|
@ -23,7 +23,6 @@ namespace N_m3u8DL_RE.Parser.Extractor
|
||||||
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 MasterM3u8Flag = false;
|
||||||
private bool FirstFetchFlag = true;
|
|
||||||
|
|
||||||
public ParserConfig ParserConfig { get; set; }
|
public ParserConfig ParserConfig { get; set; }
|
||||||
|
|
||||||
|
@ -84,14 +83,10 @@ namespace N_m3u8DL_RE.Parser.Extractor
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsMaster()
|
|
||||||
{
|
|
||||||
MasterM3u8Flag = M3u8Content.Contains(HLSTags.ext_x_stream_inf);
|
|
||||||
return MasterM3u8Flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<List<StreamSpec>> ParseMasterListAsync()
|
private async Task<List<StreamSpec>> ParseMasterListAsync()
|
||||||
{
|
{
|
||||||
|
MasterM3u8Flag = true;
|
||||||
|
|
||||||
List<StreamSpec> streams = new List<StreamSpec>();
|
List<StreamSpec> streams = new List<StreamSpec>();
|
||||||
|
|
||||||
using StringReader sr = new StringReader(M3u8Content);
|
using StringReader sr = new StringReader(M3u8Content);
|
||||||
|
@ -475,7 +470,7 @@ namespace N_m3u8DL_RE.Parser.Extractor
|
||||||
{
|
{
|
||||||
this.M3u8Content = rawText;
|
this.M3u8Content = rawText;
|
||||||
this.PreProcessContent();
|
this.PreProcessContent();
|
||||||
if (IsMaster())
|
if (M3u8Content.Contains(HLSTags.ext_x_stream_inf))
|
||||||
{
|
{
|
||||||
Logger.Warn(ResString.masterM3u8Found);
|
Logger.Warn(ResString.masterM3u8Found);
|
||||||
var lists = await ParseMasterListAsync();
|
var lists = await ParseMasterListAsync();
|
||||||
|
@ -523,30 +518,44 @@ namespace N_m3u8DL_RE.Parser.Extractor
|
||||||
this.PreProcessContent();
|
this.PreProcessContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task FetchPlayListAsync(List<StreamSpec> lists)
|
/// <summary>
|
||||||
|
/// 从Master链接中刷新各个流的URL
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lists"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private async Task RefreshUrlFromMaster(List<StreamSpec> lists)
|
||||||
{
|
{
|
||||||
//首次加载不需要刷新URL
|
//重新加载master m3u8, 刷新选中流的URL
|
||||||
if (!FirstFetchFlag && MasterM3u8Flag)
|
await LoadM3u8FromUrlAsync(ParserConfig.Url);
|
||||||
|
var newStreams = await ParseMasterListAsync();
|
||||||
|
newStreams = newStreams.DistinctBy(p => p.Url).ToList();
|
||||||
|
foreach (var l in lists)
|
||||||
{
|
{
|
||||||
//重新加载master m3u8, 刷新选中流的URL
|
var match = newStreams.Where(n => n.ToShortString() == l.ToShortString());
|
||||||
await LoadM3u8FromUrlAsync(ParserConfig.Url);
|
if (match.Any())
|
||||||
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());
|
Logger.DebugMarkUp($"{l.Url} => {match.First().Url}");
|
||||||
if (match.Any())
|
l.Url = match.First().Url;
|
||||||
{
|
|
||||||
Logger.DebugMarkUp($"{l.Url} => {match.First().Url}");
|
|
||||||
l.Url = match.First().Url;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task FetchPlayListAsync(List<StreamSpec> lists)
|
||||||
|
{
|
||||||
for (int i = 0; i < lists.Count; i++)
|
for (int i = 0; i < lists.Count; i++)
|
||||||
{
|
{
|
||||||
//重新加载m3u8
|
try
|
||||||
await LoadM3u8FromUrlAsync(lists[i].Url!);
|
{
|
||||||
|
//直接重新加载m3u8
|
||||||
|
await LoadM3u8FromUrlAsync(lists[i].Url!);
|
||||||
|
}
|
||||||
|
catch (HttpRequestException) when (MasterM3u8Flag == true)
|
||||||
|
{
|
||||||
|
Logger.WarnMarkUp("Can not load m3u8. Try refreshing url from master url...");
|
||||||
|
//当前URL无法加载 尝试从Master链接中刷新URL
|
||||||
|
await RefreshUrlFromMaster(lists);
|
||||||
|
await LoadM3u8FromUrlAsync(lists[i].Url!);
|
||||||
|
}
|
||||||
|
|
||||||
var newPlaylist = await ParseListAsync();
|
var newPlaylist = await ParseListAsync();
|
||||||
if (lists[i].Playlist?.MediaInit != null)
|
if (lists[i].Playlist?.MediaInit != null)
|
||||||
|
@ -570,7 +579,6 @@ namespace N_m3u8DL_RE.Parser.Extractor
|
||||||
|
|
||||||
public async Task RefreshPlayListAsync(List<StreamSpec> streamSpecs)
|
public async Task RefreshPlayListAsync(List<StreamSpec> streamSpecs)
|
||||||
{
|
{
|
||||||
FirstFetchFlag = false;
|
|
||||||
await FetchPlayListAsync(streamSpecs);
|
await FetchPlayListAsync(streamSpecs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
{
|
{
|
||||||
internal partial class CommandInvoker
|
internal partial class CommandInvoker
|
||||||
{
|
{
|
||||||
public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20221220";
|
public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20230111";
|
||||||
|
|
||||||
[GeneratedRegex("((best|worst)\\d*|all)")]
|
[GeneratedRegex("((best|worst)\\d*|all)")]
|
||||||
private static partial Regex ForStrRegex();
|
private static partial Regex ForStrRegex();
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace N_m3u8DL_RE.DownloadManager
|
||||||
task.StartTask();
|
task.StartTask();
|
||||||
|
|
||||||
var name = streamSpec.ToShortString();
|
var name = streamSpec.ToShortString();
|
||||||
var dirName = $"{DownloaderConfig.MyOptions.SaveName ?? NowDateTime.ToString("yyyy-MM-dd_HH-mm-ss")}_{task.Id}_{streamSpec.GroupId}_{streamSpec.Codecs}_{streamSpec.Bandwidth}_{streamSpec.Language}";
|
var dirName = $"{DownloaderConfig.MyOptions.SaveName ?? NowDateTime.ToString("yyyy-MM-dd_HH-mm-ss")}_{task.Id}_{OtherUtil.GetValidFileName(streamSpec.GroupId ?? "", "-")}_{streamSpec.Codecs}_{streamSpec.Bandwidth}_{streamSpec.Language}";
|
||||||
var saveDir = DownloaderConfig.MyOptions.SaveDir ?? Environment.CurrentDirectory;
|
var saveDir = DownloaderConfig.MyOptions.SaveDir ?? Environment.CurrentDirectory;
|
||||||
var saveName = DownloaderConfig.MyOptions.SaveName != null ? $"{DownloaderConfig.MyOptions.SaveName}.{streamSpec.Language}".TrimEnd('.') : dirName;
|
var saveName = DownloaderConfig.MyOptions.SaveName != null ? $"{DownloaderConfig.MyOptions.SaveName}.{streamSpec.Language}".TrimEnd('.') : dirName;
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ namespace N_m3u8DL_RE.DownloadManager
|
||||||
if (segments.Count() == 1) speedContainer.SingleSegment = true;
|
if (segments.Count() == 1) speedContainer.SingleSegment = true;
|
||||||
|
|
||||||
var type = streamSpec.MediaType ?? Common.Enum.MediaType.VIDEO;
|
var type = streamSpec.MediaType ?? Common.Enum.MediaType.VIDEO;
|
||||||
var dirName = $"{DownloaderConfig.MyOptions.SaveName ?? NowDateTime.ToString("yyyy-MM-dd_HH-mm-ss")}_{task.Id}_{streamSpec.GroupId}_{streamSpec.Codecs}_{streamSpec.Bandwidth}_{streamSpec.Language}";
|
var dirName = $"{DownloaderConfig.MyOptions.SaveName ?? NowDateTime.ToString("yyyy-MM-dd_HH-mm-ss")}_{task.Id}_{OtherUtil.GetValidFileName(streamSpec.GroupId ?? "", "-")}_{streamSpec.Codecs}_{streamSpec.Bandwidth}_{streamSpec.Language}";
|
||||||
var tmpDir = Path.Combine(DownloaderConfig.MyOptions.TmpDir ?? Environment.CurrentDirectory, dirName);
|
var tmpDir = Path.Combine(DownloaderConfig.MyOptions.TmpDir ?? Environment.CurrentDirectory, dirName);
|
||||||
var saveDir = DownloaderConfig.MyOptions.SaveDir ?? Environment.CurrentDirectory;
|
var saveDir = DownloaderConfig.MyOptions.SaveDir ?? Environment.CurrentDirectory;
|
||||||
var saveName = DownloaderConfig.MyOptions.SaveName != null ? $"{DownloaderConfig.MyOptions.SaveName}.{streamSpec.Language}".TrimEnd('.') : dirName;
|
var saveName = DownloaderConfig.MyOptions.SaveName != null ? $"{DownloaderConfig.MyOptions.SaveName}.{streamSpec.Language}".TrimEnd('.') : dirName;
|
||||||
|
|
|
@ -181,7 +181,7 @@ namespace N_m3u8DL_RE.DownloadManager
|
||||||
|
|
||||||
var name = streamSpec.ToShortString();
|
var name = streamSpec.ToShortString();
|
||||||
var type = streamSpec.MediaType ?? Common.Enum.MediaType.VIDEO;
|
var type = streamSpec.MediaType ?? Common.Enum.MediaType.VIDEO;
|
||||||
var dirName = $"{DownloaderConfig.MyOptions.SaveName ?? NowDateTime.ToString("yyyy-MM-dd_HH-mm-ss")}_{task.Id}_{streamSpec.GroupId}_{streamSpec.Codecs}_{streamSpec.Bandwidth}_{streamSpec.Language}";
|
var dirName = $"{DownloaderConfig.MyOptions.SaveName ?? NowDateTime.ToString("yyyy-MM-dd_HH-mm-ss")}_{task.Id}_{OtherUtil.GetValidFileName(streamSpec.GroupId ?? "", "-")}_{streamSpec.Codecs}_{streamSpec.Bandwidth}_{streamSpec.Language}";
|
||||||
var tmpDir = Path.Combine(DownloaderConfig.MyOptions.TmpDir ?? Environment.CurrentDirectory, dirName);
|
var tmpDir = Path.Combine(DownloaderConfig.MyOptions.TmpDir ?? Environment.CurrentDirectory, dirName);
|
||||||
var saveDir = DownloaderConfig.MyOptions.SaveDir ?? Environment.CurrentDirectory;
|
var saveDir = DownloaderConfig.MyOptions.SaveDir ?? Environment.CurrentDirectory;
|
||||||
var saveName = DownloaderConfig.MyOptions.SaveName != null ? DownloaderConfig.MyOptions.SaveName : dirName;
|
var saveName = DownloaderConfig.MyOptions.SaveName != null ? DownloaderConfig.MyOptions.SaveName : dirName;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<LangVersion>preview</LangVersion>
|
<LangVersion>preview</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<Version>0.1.5.2</Version>
|
<Version>0.1.5.3</Version>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue