自动计算stpp字幕时间轴

This commit is contained in:
nilaoda 2022-09-19 15:07:25 +08:00
parent 02efb814e9
commit 4ba8f48835
5 changed files with 55 additions and 15 deletions

View File

@ -29,6 +29,8 @@ namespace N_m3u8DL_RE.Common.Entity
public string? VideoRange { get; set; }
//补充信息-特征
public string? Characteristics { get; set; }
//发布时间仅MPD需要
public DateTime? PublishTime { get; set; }
//外部轨道GroupId (后续寻找对应轨道信息)
public string? AudioId { get; set; }

View File

@ -24,9 +24,9 @@ namespace N_m3u8DL_RE.Common.Entity
/// </summary>
/// <param name="textBytes"></param>
/// <returns></returns>
public static WebVttSub Parse(byte[] textBytes)
public static WebVttSub Parse(byte[] textBytes, long BaseTimestamp = 0L)
{
return Parse(Encoding.UTF8.GetString(textBytes));
return Parse(Encoding.UTF8.GetString(textBytes), BaseTimestamp);
}
/// <summary>
@ -35,9 +35,9 @@ namespace N_m3u8DL_RE.Common.Entity
/// <param name="textBytes"></param>
/// <param name="encoding"></param>
/// <returns></returns>
public static WebVttSub Parse(byte[] textBytes, Encoding encoding)
public static WebVttSub Parse(byte[] textBytes, Encoding encoding, long BaseTimestamp = 0L)
{
return Parse(encoding.GetString(textBytes));
return Parse(encoding.GetString(textBytes), BaseTimestamp);
}
/// <summary>
@ -45,7 +45,7 @@ namespace N_m3u8DL_RE.Common.Entity
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public static WebVttSub Parse(string text)
public static WebVttSub Parse(string text, long BaseTimestamp = 0L)
{
if (!text.Trim().StartsWith("WEBVTT"))
throw new Exception("Bad vtt!");
@ -98,6 +98,22 @@ namespace N_m3u8DL_RE.Common.Entity
}
}
if (BaseTimestamp != 0)
{
foreach (var item in webSub.Cues)
{
if (item.StartTime.TotalMilliseconds - BaseTimestamp >= 0)
{
item.StartTime = TimeSpan.FromMilliseconds(item.StartTime.TotalMilliseconds - BaseTimestamp);
item.EndTime = TimeSpan.FromMilliseconds(item.EndTime.TotalMilliseconds - BaseTimestamp);
}
else
{
break;
}
}
}
return webSub;
}

View File

@ -190,6 +190,12 @@ namespace N_m3u8DL_RE.Parser.Extractor
streamSpec.Channels = audioChannelConfiguration.Attribute("value")?.Value;
}
//发布时间
if (!string.IsNullOrEmpty(publishTime))
{
streamSpec.PublishTime = DateTime.Parse(publishTime);
}
//第一种形式 SegmentBase
var segmentBaseElement = representation.Elements().Where(e => e.Name.LocalName == "SegmentBase").FirstOrDefault();

View File

@ -118,7 +118,7 @@ namespace Mp4SubtitleParser
return MultiElementsFixRegex().Matches(xml).Select(m => m.Value).ToList();
}
public static WebVttSub ExtractFromMp4s(IEnumerable<string> items, long segTimeMs)
public static WebVttSub ExtractFromMp4s(IEnumerable<string> items, long segTimeMs, long baseTimestamp = 0L)
{
//read ttmls
List<string> xmls = new List<string>();
@ -156,10 +156,10 @@ namespace Mp4SubtitleParser
segIndex++;
}
return ExtractSub(xmls);
return ExtractSub(xmls, baseTimestamp);
}
public static WebVttSub ExtractFromTTMLs(IEnumerable<string> items, long segTimeMs)
public static WebVttSub ExtractFromTTMLs(IEnumerable<string> items, long segTimeMs, long baseTimestamp = 0L)
{
//read ttmls
List<string> xmls = new List<string>();
@ -178,10 +178,10 @@ namespace Mp4SubtitleParser
segIndex++;
}
return ExtractSub(xmls);
return ExtractSub(xmls, baseTimestamp);
}
private static WebVttSub ExtractSub(List<string> xmls)
private static WebVttSub ExtractSub(List<string> xmls, long baseTimestamp)
{
//parsing
var xmlDoc = new XmlDocument();
@ -306,7 +306,7 @@ namespace Mp4SubtitleParser
vtt.AppendLine();
}
return WebVttSub.Parse(vtt.ToString());
return WebVttSub.Parse(vtt.ToString(), baseTimestamp);
}
}
}

View File

@ -35,6 +35,7 @@ namespace N_m3u8DL_RE.DownloadManager
StreamExtractor StreamExtractor;
List<StreamSpec> SelectedSteams;
DateTime NowDateTime;
DateTime? PublishDateTime;
bool STOP_FLAG = false;
int WAIT_SEC = 0; //刷新间隔
ConcurrentDictionary<int, int> RecordingDurDic = new(); //已录制时长
@ -46,6 +47,7 @@ namespace N_m3u8DL_RE.DownloadManager
this.DownloaderConfig = downloaderConfig;
Downloader = new SimpleDownloader(DownloaderConfig);
NowDateTime = DateTime.Now;
PublishDateTime = selectedSteams.FirstOrDefault()?.PublishTime;
StreamExtractor = streamExtractor;
SelectedSteams = selectedSteams;
}
@ -115,6 +117,7 @@ namespace N_m3u8DL_RE.DownloadManager
private async Task<bool> RecordStreamAsync(StreamSpec streamSpec, ProgressTask task, SpeedContainer speedContainer, ISourceBlock<List<MediaSegment>> source)
{
var baseTimestamp = PublishDateTime == null ? 0L : (long)(PublishDateTime.Value.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds;
//mp4decrypt
var mp4decrypt = DownloaderConfig.MyOptions.DecryptionBinaryPath!;
var mp4InitFile = "";
@ -321,6 +324,7 @@ namespace N_m3u8DL_RE.DownloadManager
if (firstSub)
{
currentVtt = MP4VttUtil.ExtractSub(mp4s, timescale);
firstSub = false;
}
else
{
@ -337,11 +341,17 @@ namespace N_m3u8DL_RE.DownloadManager
var mp4s = FileDic.Values.Select(v => v!.ActualFilePath).Where(p => p.EndsWith(".ttml")).OrderBy(s => s).ToArray();
if (firstSub)
{
currentVtt = MP4TtmlUtil.ExtractFromTTMLs(mp4s, 0);
if (baseTimestamp != 0)
{
var total = segments.Sum(s => s.Duration);
baseTimestamp -= (long)TimeSpan.FromSeconds(total).TotalMilliseconds;
}
currentVtt = MP4TtmlUtil.ExtractFromTTMLs(mp4s, 0, baseTimestamp);
firstSub = false;
}
else
{
var finalVtt = MP4TtmlUtil.ExtractFromTTMLs(mp4s, 0);
var finalVtt = MP4TtmlUtil.ExtractFromTTMLs(mp4s, 0, baseTimestamp);
currentVtt.AddCuesFromOne(finalVtt);
}
}
@ -358,11 +368,17 @@ namespace N_m3u8DL_RE.DownloadManager
var mp4s = FileDic.Values.Select(v => v!.ActualFilePath).Where(p => p.EndsWith(".m4s")).OrderBy(s => s).ToArray();
if (firstSub)
{
currentVtt = MP4TtmlUtil.ExtractFromMp4s(mp4s, 0);
if (baseTimestamp != 0)
{
var total = segments.Sum(s => s.Duration);
baseTimestamp -= (long)TimeSpan.FromSeconds(total).TotalMilliseconds;
}
currentVtt = MP4TtmlUtil.ExtractFromMp4s(mp4s, 0, baseTimestamp);
firstSub = false;
}
else
{
var finalVtt = MP4TtmlUtil.ExtractFromMp4s(mp4s, 0);
var finalVtt = MP4TtmlUtil.ExtractFromMp4s(mp4s, 0, baseTimestamp);
currentVtt.AddCuesFromOne(finalVtt);
}
}