支持TTML+PNG图形字幕
This commit is contained in:
parent
438b2dea7b
commit
b0c25c7f25
|
@ -103,6 +103,7 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
public static string writeJson { get => GetText("writeJson"); }
|
public static string writeJson { get => GetText("writeJson"); }
|
||||||
public static string noStreamsToDownload { get => GetText("noStreamsToDownload"); }
|
public static string noStreamsToDownload { get => GetText("noStreamsToDownload"); }
|
||||||
public static string newVersionFound { get => GetText("newVersionFound"); }
|
public static string newVersionFound { get => GetText("newVersionFound"); }
|
||||||
|
public static string processImageSub { get => GetText("processImageSub"); }
|
||||||
|
|
||||||
private static string GetText(string key)
|
private static string GetText(string key)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,12 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
{
|
{
|
||||||
public static Dictionary<string, TextContainer> LANG_DIC = new()
|
public static Dictionary<string, TextContainer> LANG_DIC = new()
|
||||||
{
|
{
|
||||||
|
["processImageSub"] = new TextContainer
|
||||||
|
(
|
||||||
|
zhCN: "正在处理图形字幕",
|
||||||
|
zhTW: "正在處理圖形字幕",
|
||||||
|
enUS: "Processing Image Sub"
|
||||||
|
),
|
||||||
["newVersionFound"] = new TextContainer
|
["newVersionFound"] = new TextContainer
|
||||||
(
|
(
|
||||||
zhCN: "检测到新版本,请尽快升级!",
|
zhCN: "检测到新版本,请尽快升级!",
|
||||||
|
|
|
@ -34,6 +34,8 @@ namespace Mp4SubtitleParser
|
||||||
private static partial Regex LabelFixRegex();
|
private static partial Regex LabelFixRegex();
|
||||||
[GeneratedRegex("\\<tt[\\s\\S]*?\\<\\/tt\\>")]
|
[GeneratedRegex("\\<tt[\\s\\S]*?\\<\\/tt\\>")]
|
||||||
private static partial Regex MultiElementsFixRegex();
|
private static partial Regex MultiElementsFixRegex();
|
||||||
|
[GeneratedRegex("\\<smpte:image.*xml:id=\\\"(.*?)\\\".*\\>([\\s\\S]*?)<\\/smpte:image>")]
|
||||||
|
private static partial Regex ImageRegex();
|
||||||
|
|
||||||
public static bool CheckInit(byte[] data)
|
public static bool CheckInit(byte[] data)
|
||||||
{
|
{
|
||||||
|
@ -229,18 +231,33 @@ namespace Mp4SubtitleParser
|
||||||
if (_div == null)
|
if (_div == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
//PNG Subs
|
||||||
|
var imageDic = new Dictionary<string, string>(); //id, Base64
|
||||||
|
if (ImageRegex().IsMatch(xmlDoc.InnerXml))
|
||||||
|
{
|
||||||
|
foreach (Match img in ImageRegex().Matches(xmlDoc.InnerXml))
|
||||||
|
{
|
||||||
|
imageDic.Add(img.Groups[1].Value, img.Groups[2].Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Parse <p> label
|
//Parse <p> label
|
||||||
foreach (XmlElement _p in _div!.SelectNodes("ns:p", nsMgr)!)
|
foreach (XmlElement _p in _div!.SelectNodes("ns:p", nsMgr)!)
|
||||||
{
|
{
|
||||||
var _begin = _p.GetAttribute("begin");
|
var _begin = _p.GetAttribute("begin");
|
||||||
var _end = _p.GetAttribute("end");
|
var _end = _p.GetAttribute("end");
|
||||||
var _region = _p.GetAttribute("region");
|
var _region = _p.GetAttribute("region");
|
||||||
|
var _bgImg = _p.GetAttribute("smpte:backgroundImage");
|
||||||
var sub = new SubEntity
|
var sub = new SubEntity
|
||||||
{
|
{
|
||||||
Begin = _begin,
|
Begin = _begin,
|
||||||
End = _end,
|
End = _end,
|
||||||
Region = _region
|
Region = _region
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(_bgImg))
|
||||||
|
{
|
||||||
var _spans = _p.ChildNodes;
|
var _spans = _p.ChildNodes;
|
||||||
//Collect <span>
|
//Collect <span>
|
||||||
foreach (XmlNode _node in _spans)
|
foreach (XmlNode _node in _spans)
|
||||||
|
@ -261,6 +278,19 @@ namespace Mp4SubtitleParser
|
||||||
sub.ContentStrings.Add(_span.OuterXml);
|
sub.ContentStrings.Add(_span.OuterXml);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var id = _bgImg.Replace("#", "");
|
||||||
|
if (imageDic.ContainsKey(id))
|
||||||
|
{
|
||||||
|
var _span = new XmlDocument().CreateElement("span");
|
||||||
|
_span.InnerText = $"Base64::{imageDic[id]}";
|
||||||
|
sub.Contents.Add(_span);
|
||||||
|
sub.ContentStrings.Add(_span.OuterXml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Check if one <p> has been splitted
|
//Check if one <p> has been splitted
|
||||||
var index = finalSubs.FindLastIndex(s => s.End == _begin && s.Region == _region && s.ContentStrings.SequenceEqual(sub.ContentStrings));
|
var index = finalSubs.FindLastIndex(s => s.End == _begin && s.Region == _region && s.ContentStrings.SequenceEqual(sub.ContentStrings));
|
||||||
//Skip empty lines
|
//Skip empty lines
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
{
|
{
|
||||||
internal partial class CommandInvoker
|
internal partial class CommandInvoker
|
||||||
{
|
{
|
||||||
public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20221113";
|
public const string VERSION_INFO = "N_m3u8DL-RE (Beta version) 20221114";
|
||||||
|
|
||||||
[GeneratedRegex("((best|worst)\\d*|all)")]
|
[GeneratedRegex("((best|worst)\\d*|all)")]
|
||||||
private static partial Regex ForStrRegex();
|
private static partial Regex ForStrRegex();
|
||||||
|
|
|
@ -410,6 +410,22 @@ namespace N_m3u8DL_RE.DownloadManager
|
||||||
//写出字幕
|
//写出字幕
|
||||||
var firstKey = FileDic.Keys.First();
|
var firstKey = FileDic.Keys.First();
|
||||||
var files = FileDic.Values.Select(v => v!.ActualFilePath).OrderBy(s => s).ToArray();
|
var files = FileDic.Values.Select(v => v!.ActualFilePath).OrderBy(s => s).ToArray();
|
||||||
|
|
||||||
|
//处理图形字幕
|
||||||
|
if (finalVtt.Cues.All(v => v.Payload.StartsWith("Base64::")))
|
||||||
|
{
|
||||||
|
Logger.WarnMarkUp(ResString.processImageSub);
|
||||||
|
var _pad = "0".PadLeft(finalVtt.Cues.Count().ToString().Length, '0');
|
||||||
|
var _i = 0;
|
||||||
|
foreach (var img in finalVtt.Cues)
|
||||||
|
{
|
||||||
|
var base64 = img.Payload[8..];
|
||||||
|
var name = _i++.ToString(_pad) + ".png";
|
||||||
|
await File.WriteAllBytesAsync(Path.Combine(tmpDir, name), Convert.FromBase64String(base64));
|
||||||
|
img.Payload = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var item in files) File.Delete(item);
|
foreach (var item in files) File.Delete(item);
|
||||||
FileDic.Clear();
|
FileDic.Clear();
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
@ -444,6 +460,22 @@ namespace N_m3u8DL_RE.DownloadManager
|
||||||
//写出字幕
|
//写出字幕
|
||||||
var firstKey = FileDic.Keys.First();
|
var firstKey = FileDic.Keys.First();
|
||||||
var files = FileDic.Values.Select(v => v!.ActualFilePath).OrderBy(s => s).ToArray();
|
var files = FileDic.Values.Select(v => v!.ActualFilePath).OrderBy(s => s).ToArray();
|
||||||
|
|
||||||
|
//处理图形字幕
|
||||||
|
if (finalVtt.Cues.All(v => v.Payload.StartsWith("Base64::")))
|
||||||
|
{
|
||||||
|
Logger.WarnMarkUp(ResString.processImageSub);
|
||||||
|
var _pad = "0".PadLeft(finalVtt.Cues.Count().ToString().Length, '0');
|
||||||
|
var _i = 0;
|
||||||
|
foreach (var img in finalVtt.Cues)
|
||||||
|
{
|
||||||
|
var base64 = img.Payload[8..];
|
||||||
|
var name = _i++.ToString(_pad) + ".png";
|
||||||
|
await File.WriteAllBytesAsync(Path.Combine(tmpDir, name), Convert.FromBase64String(base64));
|
||||||
|
img.Payload = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var item in files) File.Delete(item);
|
foreach (var item in files) File.Delete(item);
|
||||||
FileDic.Clear();
|
FileDic.Clear();
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
|
|
@ -193,6 +193,7 @@ namespace N_m3u8DL_RE
|
||||||
//url = "https://a38avoddashs3ww-a.akamaihd.net/ondemand/iad_2/8e91/f2f2/ec5a/430f-bd7a-0779f4a0189d/685cda75-609c-41c1-86bb-688f4cdb5521_corrected.mpd";
|
//url = "https://a38avoddashs3ww-a.akamaihd.net/ondemand/iad_2/8e91/f2f2/ec5a/430f-bd7a-0779f4a0189d/685cda75-609c-41c1-86bb-688f4cdb5521_corrected.mpd";
|
||||||
//url = "http://ht.grelighting.cn/m3u8/OEtYNVNjMFF5N1g2VzNkZ2lwbWEvd1ZtTGJ0dlZXOEk=.m3u8"; //特殊的图片伪装
|
//url = "http://ht.grelighting.cn/m3u8/OEtYNVNjMFF5N1g2VzNkZ2lwbWEvd1ZtTGJ0dlZXOEk=.m3u8"; //特殊的图片伪装
|
||||||
//url = "https://ali6.a.yximgs.com/udata/music/music_295e59bdb3084def8158873ad6f5c8250.jpg"; //PNG图片伪装
|
//url = "https://ali6.a.yximgs.com/udata/music/music_295e59bdb3084def8158873ad6f5c8250.jpg"; //PNG图片伪装
|
||||||
|
//url = "https://vod.cds.nowonline.com.br/Content/dsc/VOD/movie/df/83/4dd69316-2022-45c0-a4f7-c35cad87df83/manifest.mpd"; //TTML+PNG
|
||||||
//url = "";
|
//url = "";
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(option.Input))
|
if (!string.IsNullOrEmpty(option.Input))
|
||||||
|
|
Loading…
Reference in New Issue