支持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 noStreamsToDownload { get => GetText("noStreamsToDownload"); }
|
||||
public static string newVersionFound { get => GetText("newVersionFound"); }
|
||||
public static string processImageSub { get => GetText("processImageSub"); }
|
||||
|
||||
private static string GetText(string key)
|
||||
{
|
||||
|
|
|
@ -10,6 +10,12 @@ namespace N_m3u8DL_RE.Common.Resource
|
|||
{
|
||||
public static Dictionary<string, TextContainer> LANG_DIC = new()
|
||||
{
|
||||
["processImageSub"] = new TextContainer
|
||||
(
|
||||
zhCN: "正在处理图形字幕",
|
||||
zhTW: "正在處理圖形字幕",
|
||||
enUS: "Processing Image Sub"
|
||||
),
|
||||
["newVersionFound"] = new TextContainer
|
||||
(
|
||||
zhCN: "检测到新版本,请尽快升级!",
|
||||
|
|
|
@ -34,6 +34,8 @@ namespace Mp4SubtitleParser
|
|||
private static partial Regex LabelFixRegex();
|
||||
[GeneratedRegex("\\<tt[\\s\\S]*?\\<\\/tt\\>")]
|
||||
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)
|
||||
{
|
||||
|
@ -229,18 +231,33 @@ namespace Mp4SubtitleParser
|
|||
if (_div == null)
|
||||
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
|
||||
foreach (XmlElement _p in _div!.SelectNodes("ns:p", nsMgr)!)
|
||||
{
|
||||
var _begin = _p.GetAttribute("begin");
|
||||
var _end = _p.GetAttribute("end");
|
||||
var _region = _p.GetAttribute("region");
|
||||
var _bgImg = _p.GetAttribute("smpte:backgroundImage");
|
||||
var sub = new SubEntity
|
||||
{
|
||||
Begin = _begin,
|
||||
End = _end,
|
||||
Region = _region
|
||||
};
|
||||
|
||||
if (string.IsNullOrEmpty(_bgImg))
|
||||
{
|
||||
var _spans = _p.ChildNodes;
|
||||
//Collect <span>
|
||||
foreach (XmlNode _node in _spans)
|
||||
|
@ -261,6 +278,19 @@ namespace Mp4SubtitleParser
|
|||
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
|
||||
var index = finalSubs.FindLastIndex(s => s.End == _begin && s.Region == _region && s.ContentStrings.SequenceEqual(sub.ContentStrings));
|
||||
//Skip empty lines
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace N_m3u8DL_RE.CommandLine
|
|||
{
|
||||
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)")]
|
||||
private static partial Regex ForStrRegex();
|
||||
|
|
|
@ -410,6 +410,22 @@ namespace N_m3u8DL_RE.DownloadManager
|
|||
//写出字幕
|
||||
var firstKey = FileDic.Keys.First();
|
||||
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);
|
||||
FileDic.Clear();
|
||||
var index = 0;
|
||||
|
@ -444,6 +460,22 @@ namespace N_m3u8DL_RE.DownloadManager
|
|||
//写出字幕
|
||||
var firstKey = FileDic.Keys.First();
|
||||
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);
|
||||
FileDic.Clear();
|
||||
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 = "http://ht.grelighting.cn/m3u8/OEtYNVNjMFF5N1g2VzNkZ2lwbWEvd1ZtTGJ0dlZXOEk=.m3u8"; //特殊的图片伪装
|
||||
//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 = "";
|
||||
|
||||
if (!string.IsNullOrEmpty(option.Input))
|
||||
|
|
Loading…
Reference in New Issue