N_m3u8DL-RE/src/N_m3u8DL-RE.Parser/Processor/HLS/DefaultHLSContentProcessor.cs
2024-11-10 18:44:58 +08:00

101 lines
3.9 KiB
C#

using N_m3u8DL_RE.Common.Enum;
using N_m3u8DL_RE.Parser.Config;
using N_m3u8DL_RE.Parser.Constants;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace N_m3u8DL_RE.Parser.Processor.HLS;
public partial class DefaultHLSContentProcessor : ContentProcessor
{
[GeneratedRegex("#EXT-X-DISCONTINUITY\\s+#EXT-X-MAP:URI=\\\"(.*?)\\\",BYTERANGE=\\\"(.*?)\\\"")]
private static partial Regex YkDVRegex();
[GeneratedRegex("#EXT-X-MAP:URI=\\\".*?BUMPER/[\\s\\S]+?#EXT-X-DISCONTINUITY")]
private static partial Regex DNSPRegex();
[GeneratedRegex("#EXTINF:.*?,\\s+.*BUMPER.*\\s+?#EXT-X-DISCONTINUITY")]
private static partial Regex DNSPSubRegex();
[GeneratedRegex("(#EXTINF.*)(\\s+)(#EXT-X-KEY.*)")]
private static partial Regex OrderFixRegex();
[GeneratedRegex("#EXT-X-MAP.*\\.apple\\.com/")]
private static partial Regex ATVRegex();
[GeneratedRegex("(#EXT-X-KEY:[\\s\\S]*?)(#EXT-X-DISCONTINUITY|#EXT-X-ENDLIST)")]
private static partial Regex ATVRegex2();
public override bool CanProcess(ExtractorType extractorType, string rawText, ParserConfig parserConfig) => extractorType == ExtractorType.HLS;
public override string Process(string m3u8Content, ParserConfig parserConfig)
{
// 处理content以\r作为换行符的情况
if (m3u8Content.Contains("\r") && !m3u8Content.Contains("\n"))
{
m3u8Content = m3u8Content.Replace("\r", Environment.NewLine);
}
var m3u8Url = parserConfig.Url;
// YSP回放
if (m3u8Url.Contains("tlivecloud-playback-cdn.ysp.cctv.cn") && m3u8Url.Contains("endtime="))
{
m3u8Content += Environment.NewLine + HLSTags.ext_x_endlist;
}
// IMOOC
if (m3u8Url.Contains("imooc.com/"))
{
// M3u8Content = DecodeImooc.DecodeM3u8(M3u8Content);
}
// 针对YK #EXT-X-VERSION:7杜比视界片源修正
if (m3u8Content.Contains("#EXT-X-DISCONTINUITY") && m3u8Content.Contains("#EXT-X-MAP") && m3u8Content.Contains("ott.cibntv.net") && m3u8Content.Contains("ccode="))
{
Regex ykmap = YkDVRegex();
foreach (Match m in ykmap.Matches(m3u8Content))
{
m3u8Content = m3u8Content.Replace(m.Value, $"#EXTINF:0.000000,\n#EXT-X-BYTERANGE:{m.Groups[2].Value}\n{m.Groups[1].Value}");
}
}
// 针对Disney+修正
if (m3u8Content.Contains("#EXT-X-DISCONTINUITY") && m3u8Content.Contains("#EXT-X-MAP") && m3u8Url.Contains("media.dssott.com/"))
{
Regex ykmap = DNSPRegex();
if (ykmap.IsMatch(m3u8Content))
{
m3u8Content = m3u8Content.Replace(ykmap.Match(m3u8Content).Value, "#XXX");
}
}
// 针对Disney+字幕修正
if (m3u8Content.Contains("#EXT-X-DISCONTINUITY") && m3u8Content.Contains("seg_00000.vtt") && m3u8Url.Contains("media.dssott.com/"))
{
Regex ykmap = DNSPSubRegex();
if (ykmap.IsMatch(m3u8Content))
{
m3u8Content = m3u8Content.Replace(ykmap.Match(m3u8Content).Value, "#XXX");
}
}
// 针对AppleTv修正
if (m3u8Content.Contains("#EXT-X-DISCONTINUITY") && m3u8Content.Contains("#EXT-X-MAP") && (m3u8Url.Contains(".apple.com/") || ATVRegex().IsMatch(m3u8Content)))
{
// 只取加密部分即可
Regex ykmap = ATVRegex2();
if (ykmap.IsMatch(m3u8Content))
{
m3u8Content = "#EXTM3U\r\n" + ykmap.Match(m3u8Content).Groups[1].Value + "\r\n#EXT-X-ENDLIST";
}
}
// 修复#EXT-X-KEY与#EXTINF出现次序异常问题
var regex = OrderFixRegex();
if (regex.IsMatch(m3u8Content))
{
m3u8Content = regex.Replace(m3u8Content, "$3$2$1");
}
return m3u8Content;
}
}