/// <summary> /// 解析m3u8 并保存成自己的 /// </summary> private void AnalysisM3U8() { //判断是否 多码率适配流 并重新请求 IsMutiple(); //如果需要自己重新加密的 那么需要生成对应的key if (outFileConfig.saveAsEncrpy) { GenerateAESKey(); } Logger.LogDebug("分解出所有的ts文件" + M3U8Response); //分解出所有的ts文件 SpliteM3U8(M3U8Response); //检测视频 AES 加密 if (M3U8Response.IndexOf("#EXT-X-KEY") != -1) { //.*METHOD=([^,]+) #EXT-X-KEY:METHOD=AES-128, var method = ReGeXHelper.GetRes(M3U8Response, @".*METHOD=([^,]+)"); aesConf.method = method != null ? method.Groups[1].Value : ""; //.*URI="([^"]+) URI="key.key" var uri = ReGeXHelper.GetRes(M3U8Response, @".*URI=""([^""]+)"); aesConf.uri = uri != null ? uri.Groups[1].Value : ""; //.*IV=([^,]+) var iv = ReGeXHelper.GetRes(M3U8Response, @".*IV=([^,]+)"); aesConf.iv = iv != null ? iv.Groups[1].Value : ""; aesConf.uri = ApplyURL(aesConf.uri, M3U8Url); Logger.LogDebug("解密" + aesConf.uri); GetAES(); } else { DownloadTS(); } Logger.LogDebug("保存新的m3u8"); OutSaveEnd(); }
/// <summary> /// 最后写入属于自己的M3U8 /// </summary> private void OutSaveEnd() { string m3u8 = M3U8Response; //判断是否请求成功 利用//#EXTM3U 每个 M3U 文件必须将该标签放置在第一行 var m3u8Top = ReGeXHelper.GetRes(m3u8, @"#EXTM3U"); if (m3u8Top == null) { Logger.LogError("请求失败(最后写入属于自己的M3U8):" + M3U8Response); IsComplete = false; return; } Logger.LogDebug($"m3u8Top::{m3u8Top}"); //版本 var version = ReGeXHelper.GetRes(m3u8, @"#EXT-X-VERSION:(.*)"); outFileConfig.version = version != null ? version.Groups[1].Value : "0"; Logger.LogDebug($"version::{outFileConfig.version}"); if (outFileConfig.Times.Count == 0) { Logger.LogDebug("请求完成后,并没有下载到ts文件,自动退出"); IsComplete = false; return; } //#EXT-X-TARGETDURATION 最大时间 int var targetduration = ReGeXHelper.GetRes(m3u8, @"#EXT-X-TARGETDURATION:(.*)"); outFileConfig.targetduration = targetduration != null ? targetduration.Groups[1].Value : (((int)Math.Ceiling(outFileConfig.Times.Max(m => Convert.ToDouble(m)))).ToString()); Logger.LogDebug($"targetduration::{outFileConfig.targetduration}"); //#EXT-X-MEDIA-SEQUENCE var sequence = ReGeXHelper.GetRes(m3u8, @"#EXT-X-SEQUENCE:(.*)"); outFileConfig.sequence = sequence != null ? sequence.Groups[1].Value : "0"; Logger.LogDebug($"sequence::{outFileConfig.sequence}"); outFileConfig.Template = outFileConfig.Template.Replace("{VERSION}", outFileConfig.version); outFileConfig.Template = outFileConfig.Template.Replace("{TARGETDURATION}", outFileConfig.targetduration); outFileConfig.Template = outFileConfig.Template.Replace("{SEQUENCE}", outFileConfig.sequence); //是否加密的处理 OutSaveAESEncrypt(); Logger.LogDebug($"开始content"); string allContent = ""; var paths = outFileConfig.PathTime.ToArray(); var times = outFileConfig.Times.ToArray(); Logger.LogDebug($"开始sort::{paths.Length},{times.Length}"); Array.Sort(paths, times); Logger.LogDebug($"sortj结束::{paths.Length}"); for (int i = 0; i < paths.Length; i++) { var time = times[i]; var path = paths[i]; string content = $"#EXTINF:{time},\n" + $"{path}.ts\n"; allContent += content; Logger.LogDebug($"content::{content}"); } //{CONTENT} outFileConfig.Template = outFileConfig.Template.Replace("{CONTENT}", allContent); Logger.LogDebug($"Template::{outFileConfig.Template}"); using (FileStream file = new FileStream($"{GetM3U8Path()}", FileMode.Create, FileAccess.ReadWrite)) { byte[] bytes = Encoding.UTF8.GetBytes(outFileConfig.Template); file.Write(bytes, 0, bytes.Length); } }