Skip to content

Commit

Permalink
支持从音频修正VTT字幕时间轴
Browse files Browse the repository at this point in the history
  • Loading branch information
nilaoda committed Apr 12, 2023
1 parent f873cbc commit 3b7d320
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/N_m3u8DL-RE.Common/JsonContext/JsonContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace N_m3u8DL_RE.Common
[JsonSerializable(typeof(IOrderedEnumerable<StreamSpec>))]
[JsonSerializable(typeof(IEnumerable<MediaSegment>))]
[JsonSerializable(typeof(List<StreamSpec>))]
[JsonSerializable(typeof(List<MediaSegment>))]
[JsonSerializable(typeof(Dictionary<string, string>))]
internal partial class JsonContext : JsonSerializerContext { }
}
1 change: 1 addition & 0 deletions src/N_m3u8DL-RE.Common/Resource/ResString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public class ResString
public static string cmd_liveRecordLimit { get => GetText("cmd_liveRecordLimit"); }
public static string cmd_taskStartAt { get => GetText("cmd_taskStartAt"); }
public static string cmd_liveWaitTime { get => GetText("cmd_liveWaitTime"); }
public static string cmd_liveFixVttByAudio { get => GetText("cmd_liveFixVttByAudio"); }
public static string cmd_liveRealTimeMerge { get => GetText("cmd_liveRealTimeMerge"); }
public static string cmd_livePerformAsVod { get => GetText("cmd_livePerformAsVod"); }
public static string cmd_muxAfterDone { get => GetText("cmd_muxAfterDone"); }
Expand Down
6 changes: 6 additions & 0 deletions src/N_m3u8DL-RE.Common/Resource/StaticText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@ internal class StaticText
zhTW: "mkvmerge可執行程序全路徑, 例如 C:\\Tools\\mkvmerge.exe",
enUS: "Full path to the mkvmerge binary, like C:\\Tools\\mkvmerge.exe"
),
["cmd_liveFixVttByAudio"] = new TextContainer
(
zhCN: "通过读取音频文件的起始时间修正VTT字幕",
zhTW: "透過讀取音訊檔案的起始時間修正VTT字幕",
enUS: "Correct VTT sub by reading the start time of the audio file"
),
["cmd_header"] = new TextContainer
(
zhCN: "为HTTP请求设置特定的请求头, 例如:\r\n-H \"Cookie: mycookie\" -H \"User-Agent: iOS\"",
Expand Down
4 changes: 3 additions & 1 deletion src/N_m3u8DL-RE/CommandLine/CommandInvoker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ internal partial class CommandInvoker
private readonly static Option<bool> LivePipeMux = new(new string[] { "--live-pipe-mux" }, description: ResString.cmd_livePipeMux, getDefaultValue: () => false);
private readonly static Option<TimeSpan?> LiveRecordLimit = new(new string[] { "--live-record-limit" }, description: ResString.cmd_liveRecordLimit, parseArgument: ParseLiveLimit) { ArgumentHelpName = "HH:mm:ss" };
private readonly static Option<int?> LiveWaitTime = new(new string[] { "--live-wait-time" }, description: ResString.cmd_liveWaitTime) { ArgumentHelpName = "SEC" };
private readonly static Option<bool> LiveFixVttByAudio = new(new string[] { "--live-fix-vtt-by-audio" }, description: ResString.cmd_liveFixVttByAudio, getDefaultValue: () => false);


//复杂命令行如下
Expand Down Expand Up @@ -418,6 +419,7 @@ protected override MyOption GetBoundValue(BindingContext bindingContext)
TaskStartAt = bindingContext.ParseResult.GetValueForOption(TaskStartAt),
LivePerformAsVod = bindingContext.ParseResult.GetValueForOption(LivePerformAsVod),
LivePipeMux = bindingContext.ParseResult.GetValueForOption(LivePipeMux),
LiveFixVttByAudio = bindingContext.ParseResult.GetValueForOption(LiveFixVttByAudio),
UseSystemProxy = bindingContext.ParseResult.GetValueForOption(UseSystemProxy),
CustomProxy = bindingContext.ParseResult.GetValueForOption(CustomProxy),
LiveWaitTime = bindingContext.ParseResult.GetValueForOption(LiveWaitTime),
Expand Down Expand Up @@ -487,7 +489,7 @@ public static async Task<int> InvokeArgs(string[] args, Func<MyOption, Task> act
LogLevel, UILanguage, UrlProcessorArgs, Keys, KeyTextFile, DecryptionBinaryPath, UseShakaPackager, MP4RealTimeDecryption,
MuxAfterDone,
CustomHLSMethod, CustomHLSKey, CustomHLSIv, UseSystemProxy, CustomProxy, TaskStartAt,
LivePerformAsVod, LiveRealTimeMerge, LiveKeepSegments, LivePipeMux, LiveRecordLimit, LiveWaitTime,
LivePerformAsVod, LiveRealTimeMerge, LiveKeepSegments, LivePipeMux, LiveFixVttByAudio, LiveRecordLimit, LiveWaitTime,
MuxImports, VideoFilter, AudioFilter, SubtitleFilter, DropVideoFilter, DropAudioFilter, DropSubtitleFilter, MoreHelp
};

Expand Down
4 changes: 4 additions & 0 deletions src/N_m3u8DL-RE/CommandLine/MyOption.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,5 +226,9 @@ internal class MyOption
/// See: <see cref="CommandInvoker.LivePipeMux"/>.
/// </summary>
public bool LivePipeMux { get; set; }
/// <summary>
/// See: <see cref="CommandInvoker.LiveFixVttByAudio"/>.
/// </summary>
public bool LiveFixVttByAudio { get; set; }
}
}
24 changes: 23 additions & 1 deletion src/N_m3u8DL-RE/DownloadManager/SimpleLiveRecordManager2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ internal class SimpleLiveRecordManager2
ConcurrentDictionary<int, long> DateTimeDic = new(); //上次下载的dateTime
CancellationTokenSource CancellationTokenSource = new(); //取消Wait

private readonly object lockObj = new object();
TimeSpan? audioStart = null;

public SimpleLiveRecordManager2(DownloaderConfig downloaderConfig, List<StreamSpec> selectedSteams, StreamExtractor streamExtractor)
{
this.DownloaderConfig = downloaderConfig;
Expand Down Expand Up @@ -248,6 +251,10 @@ private async Task<bool> RecordStreamAsync(StreamSpec streamSpec, ProgressTask t
Logger.WarnMarkUp(ResString.readingInfo);
mediaInfos = await MediainfoUtil.ReadInfoAsync(DownloaderConfig.MyOptions.FFmpegBinaryPath!, result.ActualFilePath);
mediaInfos.ForEach(info => Logger.InfoMarkUp(info.ToStringMarkUp()));
lock (lockObj)
{
if (audioStart == null) audioStart = mediaInfos.FirstOrDefault(x => x.Type == "Audio")?.StartTime;
}
ChangeSpecInfo(streamSpec, mediaInfos, ref useAACFilter);
readInfo = true;
}
Expand Down Expand Up @@ -324,6 +331,10 @@ private async Task<bool> RecordStreamAsync(StreamSpec streamSpec, ProgressTask t
Logger.WarnMarkUp(ResString.readingInfo);
mediaInfos = await MediainfoUtil.ReadInfoAsync(DownloaderConfig.MyOptions.FFmpegBinaryPath!, result!.ActualFilePath);
mediaInfos.ForEach(info => Logger.InfoMarkUp(info.ToStringMarkUp()));
lock (lockObj)
{
if (audioStart == null) audioStart = mediaInfos.FirstOrDefault(x => x.Type == "Audio")?.StartTime;
}
ChangeSpecInfo(streamSpec, mediaInfos, ref useAACFilter);
readInfo = true;
}
Expand Down Expand Up @@ -367,7 +378,13 @@ await Parallel.ForEachAsync(segments, options, async (seg, _) =>
foreach (var seg in keys)
{
var vttContent = File.ReadAllText(FileDic[seg]!.ActualFilePath);
var vtt = WebVttSub.Parse(vttContent);
var waitCount = 0;
while (DownloaderConfig.MyOptions.LiveFixVttByAudio && audioStart == null && waitCount++ < 5)
{
await Task.Delay(1000);
}
var subOffset = audioStart != null ? (long)audioStart.Value.TotalMilliseconds : 0L;
var vtt = WebVttSub.Parse(vttContent, subOffset);
//手动计算MPEGTS
if (currentVtt.MpegtsTimestamp == 0 && vtt.MpegtsTimestamp == 0)
{
Expand Down Expand Up @@ -773,6 +790,11 @@ public async Task<bool> StartRecordAsync()
if (WAIT_SEC <= 0) WAIT_SEC = 1;
Logger.WarnMarkUp($"set refresh interval to {WAIT_SEC} seconds");
}
//如果没有选中音频 取消通过音频修复vtt时间轴
if (!SelectedSteams.Any(x => x.MediaType == MediaType.AUDIO))
{
DownloaderConfig.MyOptions.LiveFixVttByAudio = false;
}

/*//写出master
if (DownloaderConfig.MyOptions.LiveWriteHLS)
Expand Down
1 change: 1 addition & 0 deletions src/N_m3u8DL-RE/Entity/Mediainfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ internal class Mediainfo
public string? Resolution { get; set; }
public string? Fps { get; set; }
public string? Type { get; set; }
public TimeSpan? StartTime { get; set; }
public bool DolbyVison { get; set; }
public bool HDR { get; set; }

Expand Down
2 changes: 1 addition & 1 deletion src/N_m3u8DL-RE/N_m3u8DL-RE.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>
<Version>0.1.5.3</Version>
<Version>0.1.5.4</Version>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>

Expand Down
9 changes: 9 additions & 0 deletions src/N_m3u8DL-RE/Util/MediainfoUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ internal partial class MediainfoUtil
private static partial Regex FpsRegex();
[GeneratedRegex("DOVI configuration record.*profile: (\\d).*compatibility id: (\\d)")]
private static partial Regex DoViRegex();
[GeneratedRegex("Duration.*?start: (\\d+\\.?\\d{0,3})")]
private static partial Regex StartRegex();

public static async Task<List<Mediainfo>> ReadInfoAsync(string binary, string file)
{
Expand Down Expand Up @@ -73,6 +75,13 @@ public static async Task<List<Mediainfo>> ReadInfoAsync(string binary, string fi
)
info.DolbyVison = true;

if (StartRegex().IsMatch(output))
{
var f = StartRegex().Match(output).Groups[1].Value;
if (double.TryParse(f, out var d))
info.StartTime = TimeSpan.FromSeconds(d);
}

result.Add(info);
}

Expand Down

0 comments on commit 3b7d320

Please sign in to comment.