`MSS`修正`TrackId`后应重新解密
This commit is contained in:
parent
386c2bb46a
commit
0b19fd0f3a
|
@ -288,9 +288,9 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
),
|
),
|
||||||
["cmd_customHLSMethod"] = new TextContainer
|
["cmd_customHLSMethod"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "指定HLS加密方式 (AES_128|AES_128_ECB|CENC|CHACHA20|NONE|SAMPLE_AES|SAMPLE_AES_CTR|UNKNOWN)",
|
zhCN: "指定HLS加密方式 (AES_128|AES_128_ECB|CENC|PLAYREADY|CHACHA20|NONE|SAMPLE_AES|SAMPLE_AES_CTR|UNKNOWN)",
|
||||||
zhTW: "指定HLS加密方式 (AES_128|AES_128_ECB|CENC|CHACHA20|NONE|SAMPLE_AES|SAMPLE_AES_CTR|UNKNOWN)",
|
zhTW: "指定HLS加密方式 (AES_128|AES_128_ECB|CENC|PLAYREADY|CHACHA20|NONE|SAMPLE_AES|SAMPLE_AES_CTR|UNKNOWN)",
|
||||||
enUS: "Set HLS encryption method (AES_128|AES_128_ECB|CENC|CHACHA20|NONE|SAMPLE_AES|SAMPLE_AES_CTR|UNKNOWN)"
|
enUS: "Set HLS encryption method (AES_128|AES_128_ECB|CENC|PLAYREADY|CHACHA20|NONE|SAMPLE_AES|SAMPLE_AES_CTR|UNKNOWN)"
|
||||||
),
|
),
|
||||||
["cmd_customHLSKey"] = new TextContainer
|
["cmd_customHLSKey"] = new TextContainer
|
||||||
(
|
(
|
||||||
|
|
|
@ -164,6 +164,11 @@ namespace N_m3u8DL_RE.Parser.Extractor
|
||||||
var _duration = Convert.ToInt64(_durationStr);
|
var _duration = Convert.ToInt64(_durationStr);
|
||||||
var timescale = Convert.ToInt32(timeScaleStr);
|
var timescale = Convert.ToInt32(timeScaleStr);
|
||||||
var _repeatCount = Convert.ToInt64(_repeatCountStr);
|
var _repeatCount = Convert.ToInt64(_repeatCountStr);
|
||||||
|
if (_repeatCount > 0)
|
||||||
|
{
|
||||||
|
// This value is one-based. (A value of 2 means two fragments in the contiguous series).
|
||||||
|
_repeatCount -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
varDic[MSSTags.StartTime] = currentTime;
|
varDic[MSSTags.StartTime] = currentTime;
|
||||||
var oriUrl = ParserUtil.CombineURL(this.BaseUrl, urlPattern!);
|
var oriUrl = ParserUtil.CombineURL(this.BaseUrl, urlPattern!);
|
||||||
|
@ -215,10 +220,6 @@ namespace N_m3u8DL_RE.Parser.Extractor
|
||||||
ProtectionData = protectionData,
|
ProtectionData = protectionData,
|
||||||
ProtectionSystemID = protectionSystemId,
|
ProtectionSystemID = protectionSystemId,
|
||||||
};
|
};
|
||||||
if (streamSpec.MSSData.Duration == 0)
|
|
||||||
{
|
|
||||||
streamSpec.MSSData.Duration = streamSpec.MSSData.Timesacle;
|
|
||||||
}
|
|
||||||
var processor = new MSSMoovProcessor(streamSpec);
|
var processor = new MSSMoovProcessor(streamSpec);
|
||||||
var header = processor.GenHeader(); //trackId可能不正确
|
var header = processor.GenHeader(); //trackId可能不正确
|
||||||
streamSpec.Playlist!.MediaInit!.Url = $"base64://{Convert.ToBase64String(header)}";
|
streamSpec.Playlist!.MediaInit!.Url = $"base64://{Convert.ToBase64String(header)}";
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace N_m3u8DL_RE.Parser.Mp4
|
||||||
private string ProtectionSystemId;
|
private string ProtectionSystemId;
|
||||||
private string ProtectionData;
|
private string ProtectionData;
|
||||||
private string ProtecitonKID;
|
private string ProtecitonKID;
|
||||||
|
private string ProtecitonKID_PR;
|
||||||
private byte[] UnityMatrix
|
private byte[] UnityMatrix
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -165,6 +166,8 @@ namespace N_m3u8DL_RE.Parser.Mp4
|
||||||
var bytes = HexUtil.HexToBytes(ProtectionData.Replace("00", ""));
|
var bytes = HexUtil.HexToBytes(ProtectionData.Replace("00", ""));
|
||||||
var text = Encoding.ASCII.GetString(bytes);
|
var text = Encoding.ASCII.GetString(bytes);
|
||||||
var kidBytes = Convert.FromBase64String(KIDRegex().Match(text).Groups[1].Value);
|
var kidBytes = Convert.FromBase64String(KIDRegex().Match(text).Groups[1].Value);
|
||||||
|
//save kid for playready
|
||||||
|
this.ProtecitonKID_PR = HexUtil.BytesToHex(kidBytes);
|
||||||
//fix byte order
|
//fix byte order
|
||||||
var reverse1 = new byte[4] { kidBytes[3], kidBytes[2], kidBytes[1], kidBytes[0] };
|
var reverse1 = new byte[4] { kidBytes[3], kidBytes[2], kidBytes[1], kidBytes[0] };
|
||||||
var reverse2 = new byte[4] { kidBytes[5], kidBytes[4], kidBytes[7], kidBytes[6] };
|
var reverse2 = new byte[4] { kidBytes[5], kidBytes[4], kidBytes[7], kidBytes[6] };
|
||||||
|
@ -244,7 +247,7 @@ namespace N_m3u8DL_RE.Parser.Mp4
|
||||||
writer.Write("iso6"); //major brand
|
writer.Write("iso6"); //major brand
|
||||||
writer.WriteUInt(1); //minor version
|
writer.WriteUInt(1); //minor version
|
||||||
writer.Write("isom"); //compatible brand
|
writer.Write("isom"); //compatible brand
|
||||||
writer.Write("iso6"); //compatible brand
|
writer.Write("iso5"); //compatible brand
|
||||||
writer.Write("msdh"); //compatible brand
|
writer.Write("msdh"); //compatible brand
|
||||||
|
|
||||||
return Box("ftyp", stream.ToArray());
|
return Box("ftyp", stream.ToArray());
|
||||||
|
@ -525,9 +528,9 @@ namespace N_m3u8DL_RE.Parser.Mp4
|
||||||
else if (FourCC == "HVC1" || FourCC == "HEV1")
|
else if (FourCC == "HVC1" || FourCC == "HEV1")
|
||||||
{
|
{
|
||||||
var arr = CodecPrivateData.Split(new[] { StartCode }, StringSplitOptions.RemoveEmptyEntries);
|
var arr = CodecPrivateData.Split(new[] { StartCode }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
var vps = HexUtil.HexToBytes(arr.Where(x => (HexUtil.HexToBytes(x[0..2])[0] & 0x3F) == 0x20).First());
|
var vps = HexUtil.HexToBytes(arr.Where(x => (HexUtil.HexToBytes(x[0..2])[0] >> 1) == 0x20).First());
|
||||||
var sps = HexUtil.HexToBytes(arr.Where(x => (HexUtil.HexToBytes(x[0..2])[0] & 0x3F) == 0x21).First());
|
var sps = HexUtil.HexToBytes(arr.Where(x => (HexUtil.HexToBytes(x[0..2])[0] >> 1) == 0x21).First());
|
||||||
var pps = HexUtil.HexToBytes(arr.Where(x => (HexUtil.HexToBytes(x[0..2])[0] & 0x3F) == 0x22).First());
|
var pps = HexUtil.HexToBytes(arr.Where(x => (HexUtil.HexToBytes(x[0..2])[0] >> 1) == 0x22).First());
|
||||||
//make hvcC
|
//make hvcC
|
||||||
var hvcC = GetHvcC(sps, pps, vps);
|
var hvcC = GetHvcC(sps, pps, vps);
|
||||||
writer.Write(hvcC);
|
writer.Write(hvcC);
|
||||||
|
@ -730,6 +733,35 @@ namespace N_m3u8DL_RE.Parser.Mp4
|
||||||
return FullBox("trex", 0, 0, stream.ToArray()); //Track Extends Box
|
return FullBox("trex", 0, 0, stream.ToArray()); //Track Extends Box
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private byte[] GenPsshBoxForPlayReady()
|
||||||
|
{
|
||||||
|
using var _stream = new MemoryStream();
|
||||||
|
using var _writer = new BinaryWriter2(_stream);
|
||||||
|
var sysIdData = HexUtil.HexToBytes(ProtectionSystemId.Replace("-", ""));
|
||||||
|
var psshData = HexUtil.HexToBytes(ProtectionData);
|
||||||
|
|
||||||
|
_writer.Write(sysIdData); // SystemID 16 bytes
|
||||||
|
_writer.WriteUInt(psshData.Length); //Size of Data 4 bytes
|
||||||
|
_writer.Write(psshData); //Data
|
||||||
|
var psshBox = FullBox("pssh", 0, 0, _stream.ToArray());
|
||||||
|
return psshBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] GenPsshBoxForWideVine()
|
||||||
|
{
|
||||||
|
using var _stream = new MemoryStream();
|
||||||
|
using var _writer = new BinaryWriter2(_stream);
|
||||||
|
var sysIdData = HexUtil.HexToBytes("edef8ba9-79d6-4ace-a3c8-27dcd51d21ed".Replace("-", ""));
|
||||||
|
//var kid = HexUtil.HexToBytes(ProtecitonKID);
|
||||||
|
|
||||||
|
_writer.Write(sysIdData); // SystemID 16 bytes
|
||||||
|
var psshData = HexUtil.HexToBytes($"08011210{ProtecitonKID}1A046E647265220400000000");
|
||||||
|
_writer.WriteUInt(psshData.Length); //Size of Data 4 bytes
|
||||||
|
_writer.Write(psshData); //Data
|
||||||
|
var psshBox = FullBox("pssh", 0, 0, _stream.ToArray());
|
||||||
|
return psshBox;
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] GenHeader(byte[] firstSegment)
|
public byte[] GenHeader(byte[] firstSegment)
|
||||||
{
|
{
|
||||||
new MP4Parser()
|
new MP4Parser()
|
||||||
|
@ -801,12 +833,12 @@ namespace N_m3u8DL_RE.Parser.Mp4
|
||||||
var mvexBox = Box("mvex", mvexPayload); //Movie Extends Box
|
var mvexBox = Box("mvex", mvexPayload); //Movie Extends Box
|
||||||
moovPayload = moovPayload.Concat(mvexBox).ToArray();
|
moovPayload = moovPayload.Concat(mvexBox).ToArray();
|
||||||
|
|
||||||
/*if (IsProtection) //gen pssh
|
if (IsProtection)
|
||||||
{
|
{
|
||||||
var pssh = HexUtil.HexToBytes(ProtectionData);
|
var psshBox1 = GenPsshBoxForPlayReady();
|
||||||
var psshBox = FullBox("pssh", 1, 0, pssh);
|
var psshBox2 = GenPsshBoxForWideVine();
|
||||||
moovPayload = moovPayload.Concat(psshBox).ToArray();
|
moovPayload = moovPayload.Concat(psshBox1).Concat(psshBox2).ToArray();
|
||||||
}*/
|
}
|
||||||
|
|
||||||
var moovBox = Box("moov", moovPayload); //Movie Box
|
var moovBox = Box("moov", moovPayload); //Movie Box
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ namespace N_m3u8DL_RE.DownloadManager
|
||||||
//从文件读取KEY
|
//从文件读取KEY
|
||||||
await SearchKeyAsync(currentKID);
|
await SearchKeyAsync(currentKID);
|
||||||
//实时解密
|
//实时解密
|
||||||
if (DownloaderConfig.MyOptions.MP4RealTimeDecryption && !string.IsNullOrEmpty(currentKID))
|
if (DownloaderConfig.MyOptions.MP4RealTimeDecryption && !string.IsNullOrEmpty(currentKID) && StreamExtractor.ExtractorType != ExtractorType.MSS)
|
||||||
{
|
{
|
||||||
var enc = result.ActualFilePath;
|
var enc = result.ActualFilePath;
|
||||||
var dec = Path.Combine(Path.GetDirectoryName(enc)!, Path.GetFileNameWithoutExtension(enc) + "_dec" + Path.GetExtension(enc));
|
var dec = Path.Combine(Path.GetDirectoryName(enc)!, Path.GetFileNameWithoutExtension(enc) + "_dec" + Path.GetExtension(enc));
|
||||||
|
@ -226,6 +226,17 @@ namespace N_m3u8DL_RE.DownloadManager
|
||||||
var processor = new MSSMoovProcessor(streamSpec);
|
var processor = new MSSMoovProcessor(streamSpec);
|
||||||
var header = processor.GenHeader(File.ReadAllBytes(result.ActualFilePath));
|
var header = processor.GenHeader(File.ReadAllBytes(result.ActualFilePath));
|
||||||
await File.WriteAllBytesAsync(FileDic[streamSpec.Playlist!.MediaInit!]!.ActualFilePath, header);
|
await File.WriteAllBytesAsync(FileDic[streamSpec.Playlist!.MediaInit!]!.ActualFilePath, header);
|
||||||
|
if (DownloaderConfig.MyOptions.MP4RealTimeDecryption && !string.IsNullOrEmpty(currentKID))
|
||||||
|
{
|
||||||
|
//需要重新解密init
|
||||||
|
var enc = FileDic[streamSpec.Playlist!.MediaInit!]!.ActualFilePath;
|
||||||
|
var dec = Path.Combine(Path.GetDirectoryName(enc)!, Path.GetFileNameWithoutExtension(enc) + "_dec" + Path.GetExtension(enc));
|
||||||
|
var dResult = await MP4DecryptUtil.DecryptAsync(DownloaderConfig.MyOptions.UseShakaPackager, mp4decrypt, DownloaderConfig.MyOptions.Keys, enc, dec, currentKID);
|
||||||
|
if (dResult)
|
||||||
|
{
|
||||||
|
FileDic[streamSpec.Playlist!.MediaInit!]!.ActualFilePath = dec;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//读取init信息
|
//读取init信息
|
||||||
if (string.IsNullOrEmpty(currentKID))
|
if (string.IsNullOrEmpty(currentKID))
|
||||||
|
|
|
@ -241,7 +241,7 @@ namespace N_m3u8DL_RE.DownloadManager
|
||||||
//从文件读取KEY
|
//从文件读取KEY
|
||||||
await SearchKeyAsync(currentKID);
|
await SearchKeyAsync(currentKID);
|
||||||
//实时解密
|
//实时解密
|
||||||
if (DownloaderConfig.MyOptions.MP4RealTimeDecryption && !string.IsNullOrEmpty(currentKID))
|
if (DownloaderConfig.MyOptions.MP4RealTimeDecryption && !string.IsNullOrEmpty(currentKID) && StreamExtractor.ExtractorType != ExtractorType.MSS)
|
||||||
{
|
{
|
||||||
var enc = result.ActualFilePath;
|
var enc = result.ActualFilePath;
|
||||||
var dec = Path.Combine(Path.GetDirectoryName(enc)!, Path.GetFileNameWithoutExtension(enc) + "_dec" + Path.GetExtension(enc));
|
var dec = Path.Combine(Path.GetDirectoryName(enc)!, Path.GetFileNameWithoutExtension(enc) + "_dec" + Path.GetExtension(enc));
|
||||||
|
@ -296,6 +296,17 @@ namespace N_m3u8DL_RE.DownloadManager
|
||||||
var processor = new MSSMoovProcessor(streamSpec);
|
var processor = new MSSMoovProcessor(streamSpec);
|
||||||
var header = processor.GenHeader(File.ReadAllBytes(result.ActualFilePath));
|
var header = processor.GenHeader(File.ReadAllBytes(result.ActualFilePath));
|
||||||
await File.WriteAllBytesAsync(FileDic[streamSpec.Playlist!.MediaInit!]!.ActualFilePath, header);
|
await File.WriteAllBytesAsync(FileDic[streamSpec.Playlist!.MediaInit!]!.ActualFilePath, header);
|
||||||
|
if (DownloaderConfig.MyOptions.MP4RealTimeDecryption && !string.IsNullOrEmpty(currentKID))
|
||||||
|
{
|
||||||
|
//需要重新解密init
|
||||||
|
var enc = FileDic[streamSpec.Playlist!.MediaInit!]!.ActualFilePath;
|
||||||
|
var dec = Path.Combine(Path.GetDirectoryName(enc)!, Path.GetFileNameWithoutExtension(enc) + "_dec" + Path.GetExtension(enc));
|
||||||
|
var dResult = await MP4DecryptUtil.DecryptAsync(DownloaderConfig.MyOptions.UseShakaPackager, mp4decrypt, DownloaderConfig.MyOptions.Keys, enc, dec, currentKID);
|
||||||
|
if (dResult)
|
||||||
|
{
|
||||||
|
FileDic[streamSpec.Playlist!.MediaInit!]!.ActualFilePath = dec;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//读取init信息
|
//读取init信息
|
||||||
if (string.IsNullOrEmpty(currentKID))
|
if (string.IsNullOrEmpty(currentKID))
|
||||||
|
|
Loading…
Reference in New Issue