From 703bd162b4f1405e790f050d7c8500bd78e40bab Mon Sep 17 00:00:00 2001 From: nilaoda Date: Mon, 28 Nov 2022 02:10:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81`MSS`=E7=9B=B4=E6=92=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extractor/MSSExtractor.cs | 39 ++++++++++++++++++- .../SimpleLiveRecordManager2.cs | 25 ++++++++---- 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/N_m3u8DL-RE.Parser/Extractor/MSSExtractor.cs b/src/N_m3u8DL-RE.Parser/Extractor/MSSExtractor.cs index fb157dc..2b9c040 100644 --- a/src/N_m3u8DL-RE.Parser/Extractor/MSSExtractor.cs +++ b/src/N_m3u8DL-RE.Parser/Extractor/MSSExtractor.cs @@ -62,6 +62,7 @@ namespace N_m3u8DL_RE.Parser.Extractor //选中第一个SmoothStreamingMedia节点 var ssmElement = xmlDocument.Elements().First(e => e.Name.LocalName == "SmoothStreamingMedia"); + bool isLive = Convert.ToBoolean(ssmElement.Attribute("IsLive")?.Value ?? "FALSE"); var timeScaleStr = ssmElement.Attribute("TimeScale")?.Value ?? "10000000"; var durationStr = ssmElement.Attribute("Duration")?.Value; var isLiveStr = ssmElement.Attribute("IsLive")?.Value; @@ -124,6 +125,7 @@ namespace N_m3u8DL_RE.Parser.Extractor streamSpec.OriginalUrl = ParserConfig.OriginalUrl; streamSpec.PeriodId = indexStr; streamSpec.Playlist = new Playlist(); + streamSpec.Playlist.IsLive = isLive; streamSpec.Playlist.MediaParts.Add(new MediaPart()); streamSpec.GroupId = name ?? indexStr; streamSpec.Bandwidth = bitrate; @@ -212,6 +214,10 @@ namespace N_m3u8DL_RE.Parser.Extractor ProtectionData = protectionData, ProtectionSystemID = protectionSystemId, }; + if (streamSpec.MSSData.Duration == 0) + { + streamSpec.MSSData.Duration = streamSpec.MSSData.Timesacle; + } var processor = new MSSMoovProcessor(streamSpec); var header = processor.GenHeader(); //trackId可能不正确 streamSpec.Playlist!.MediaInit!.Url = $"base64://{Convert.ToBase64String(header)}"; @@ -353,9 +359,38 @@ namespace N_m3u8DL_RE.Parser.Extractor } } - public Task RefreshPlayListAsync(List streamSpecs) + public async Task RefreshPlayListAsync(List streamSpecs) { - throw new NotImplementedException(); + if (streamSpecs.Count == 0) return; + + var (rawText, url) = ("", ParserConfig.Url); + try + { + (rawText, url) = await HTTPUtil.GetWebSourceAndNewUrlAsync(ParserConfig.Url, ParserConfig.Headers); + } + catch (HttpRequestException) when (ParserConfig.Url != ParserConfig.OriginalUrl) + { + //当URL无法访问时,再请求原始URL + (rawText, url) = await HTTPUtil.GetWebSourceAndNewUrlAsync(ParserConfig.OriginalUrl, ParserConfig.Headers); + } + + ParserConfig.Url = url; + SetInitUrl(); + + var newStreams = await ExtractStreamsAsync(rawText); + foreach (var streamSpec in streamSpecs) + { + //有的网站每次请求MPD返回的码率不一致,导致ToShortString()无法匹配 无法更新playlist + //故增加通过init url来匹配 (如果有的话) + var match = newStreams.Where(n => n.ToShortString() == streamSpec.ToShortString()); + if (!match.Any()) + match = newStreams.Where(n => n.Playlist?.MediaInit?.Url == streamSpec.Playlist?.MediaInit?.Url); + + if (match.Any()) + streamSpec.Playlist!.MediaParts = match.First().Playlist!.MediaParts; //不更新init + } + //这里才调用URL预处理器,节省开销 + await ProcessUrlAsync(streamSpecs); } } } diff --git a/src/N_m3u8DL-RE/DownloadManager/SimpleLiveRecordManager2.cs b/src/N_m3u8DL-RE/DownloadManager/SimpleLiveRecordManager2.cs index 3a5d0fd..9d02a10 100644 --- a/src/N_m3u8DL-RE/DownloadManager/SimpleLiveRecordManager2.cs +++ b/src/N_m3u8DL-RE/DownloadManager/SimpleLiveRecordManager2.cs @@ -9,6 +9,7 @@ using N_m3u8DL_RE.Config; using N_m3u8DL_RE.Downloader; using N_m3u8DL_RE.Entity; using N_m3u8DL_RE.Parser; +using N_m3u8DL_RE.Parser.Mp4; using N_m3u8DL_RE.Util; using Spectre.Console; using Spectre.Console.Rendering; @@ -271,7 +272,7 @@ namespace N_m3u8DL_RE.DownloadManager } //下载第一个分片 - if (!readInfo) + if (!readInfo || StreamExtractor.ExtractorType == ExtractorType.MSS) { var seg = segments.First(); segments = segments.Skip(1); @@ -288,6 +289,13 @@ namespace N_m3u8DL_RE.DownloadManager task.Increment(1); if (result != null && result.Success) { + //修复MSS init + if (StreamExtractor.ExtractorType == ExtractorType.MSS) + { + var processor = new MSSMoovProcessor(streamSpec); + var header = processor.GenHeader(File.ReadAllBytes(result.ActualFilePath)); + await File.WriteAllBytesAsync(FileDic[streamSpec.Playlist!.MediaInit!]!.ActualFilePath, header); + } //读取init信息 if (string.IsNullOrEmpty(currentKID)) { @@ -307,12 +315,15 @@ namespace N_m3u8DL_RE.DownloadManager result.ActualFilePath = dec; } } - //ffmpeg读取信息 - Logger.WarnMarkUp(ResString.readingInfo); - mediaInfos = await MediainfoUtil.ReadInfoAsync(DownloaderConfig.MyOptions.FFmpegBinaryPath!, result!.ActualFilePath); - mediaInfos.ForEach(info => Logger.InfoMarkUp(info.ToStringMarkUp())); - ChangeSpecInfo(streamSpec, mediaInfos, ref useAACFilter); - readInfo = true; + if (!readInfo) + { + //ffmpeg读取信息 + Logger.WarnMarkUp(ResString.readingInfo); + mediaInfos = await MediainfoUtil.ReadInfoAsync(DownloaderConfig.MyOptions.FFmpegBinaryPath!, result!.ActualFilePath); + mediaInfos.ForEach(info => Logger.InfoMarkUp(info.ToStringMarkUp())); + ChangeSpecInfo(streamSpec, mediaInfos, ref useAACFilter); + readInfo = true; + } } }