支持`MSS`直播

This commit is contained in:
nilaoda 2022-11-28 02:10:40 +08:00
parent 4db9ad35a7
commit 703bd162b4
2 changed files with 55 additions and 9 deletions

View File

@ -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<StreamSpec> streamSpecs)
public async Task RefreshPlayListAsync(List<StreamSpec> 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);
}
}
}

View File

@ -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;
}
}
}