mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-26 05:02:36 +01:00
Merge branch 'main' of https://github.com/SubtitleEdit/subtitleedit
This commit is contained in:
commit
b0217b3380
@ -425,7 +425,7 @@ namespace Test.Logic
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestFirstWithin()
|
public void TestFirstWithin()
|
||||||
{
|
{
|
||||||
var shotChangesFrames = new List<int>() { 1000, 10000, 20000 };
|
var shotChangesFrames = new List<int>() { 50, 1000, 3000, 5000, 10000, 11000, 14000, 15000, 16000, 20000, 22000 };
|
||||||
|
|
||||||
int? First(int start, int end)
|
int? First(int start, int end)
|
||||||
{
|
{
|
||||||
@ -455,6 +455,47 @@ namespace Test.Logic
|
|||||||
Assert.AreEqual(First(20001, 20001), shotChangesFrames.FirstWithin(20001, 20001));
|
Assert.AreEqual(First(20001, 20001), shotChangesFrames.FirstWithin(20001, 20001));
|
||||||
Assert.AreEqual(First(30000, 30000), shotChangesFrames.FirstWithin(30000, 30000));
|
Assert.AreEqual(First(30000, 30000), shotChangesFrames.FirstWithin(30000, 30000));
|
||||||
Assert.AreEqual(First(30000, 40000), shotChangesFrames.FirstWithin(30000, 40000));
|
Assert.AreEqual(First(30000, 40000), shotChangesFrames.FirstWithin(30000, 40000));
|
||||||
|
Assert.AreEqual(First(25000, 5000), shotChangesFrames.FirstWithin(25000, 5000));
|
||||||
|
Assert.AreEqual(First(50, 60), shotChangesFrames.FirstWithin(50, 60));
|
||||||
|
Assert.AreEqual(First(50, 1100), shotChangesFrames.FirstWithin(50, 1100));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TestLastWithin()
|
||||||
|
{
|
||||||
|
var shotChangesFrames = new List<int>() { 50, 1000, 3000, 5000, 10000, 11000, 14000, 15000, 16000, 20000, 22000 };
|
||||||
|
|
||||||
|
int? Last(int start, int end)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return shotChangesFrames.Last(x => x >= start && x <= end);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.AreEqual(Last(-100, 100000), shotChangesFrames.LastWithin(-100, 100000));
|
||||||
|
Assert.AreEqual(Last(0, 100), shotChangesFrames.LastWithin(0, 100));
|
||||||
|
Assert.AreEqual(Last(0, 1000), shotChangesFrames.LastWithin(0, 1000));
|
||||||
|
Assert.AreEqual(Last(1000, 1000), shotChangesFrames.LastWithin(1000, 1000));
|
||||||
|
Assert.AreEqual(Last(1000, 1100), shotChangesFrames.LastWithin(1000, 1100));
|
||||||
|
Assert.AreEqual(Last(1100, 900), shotChangesFrames.LastWithin(1100, 900));
|
||||||
|
Assert.AreEqual(Last(900, 15000), shotChangesFrames.LastWithin(900, 15000));
|
||||||
|
Assert.AreEqual(Last(900, 30000), shotChangesFrames.LastWithin(900, 30000));
|
||||||
|
Assert.AreEqual(Last(19999, 19999), shotChangesFrames.LastWithin(19999, 19999));
|
||||||
|
Assert.AreEqual(Last(19999, 20000), shotChangesFrames.LastWithin(19999, 20000));
|
||||||
|
Assert.AreEqual(Last(20000, 20000), shotChangesFrames.LastWithin(20000, 20000));
|
||||||
|
Assert.AreEqual(Last(20000, 20001), shotChangesFrames.LastWithin(20000, 20001));
|
||||||
|
Assert.AreEqual(Last(19999, 20001), shotChangesFrames.LastWithin(19999, 20001));
|
||||||
|
Assert.AreEqual(Last(20001, 20001), shotChangesFrames.LastWithin(20001, 20001));
|
||||||
|
Assert.AreEqual(Last(30000, 30000), shotChangesFrames.LastWithin(30000, 30000));
|
||||||
|
Assert.AreEqual(Last(30000, 40000), shotChangesFrames.LastWithin(30000, 40000));
|
||||||
|
Assert.AreEqual(Last(25000, 5000), shotChangesFrames.LastWithin(25000, 5000));
|
||||||
|
Assert.AreEqual(Last(50, 60), shotChangesFrames.LastWithin(50, 60));
|
||||||
|
Assert.AreEqual(Last(50, 1100), shotChangesFrames.LastWithin(50, 1100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ namespace Nikse.SubtitleEdit.Core.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// First within (int)
|
// First / last within (int)
|
||||||
|
|
||||||
public static int? FirstWithin(this List<int> orderedList, int start, int end)
|
public static int? FirstWithin(this List<int> orderedList, int start, int end)
|
||||||
{
|
{
|
||||||
@ -177,5 +177,28 @@ namespace Nikse.SubtitleEdit.Core.Common
|
|||||||
|
|
||||||
return orderedList[startIndex];
|
return orderedList[startIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int? LastWithin(this List<int> orderedList, int start, int end)
|
||||||
|
{
|
||||||
|
int startIndex = orderedList.BinarySearch(start);
|
||||||
|
int endIndex = orderedList.BinarySearch(end);
|
||||||
|
|
||||||
|
if (startIndex < 0)
|
||||||
|
{
|
||||||
|
startIndex = ~startIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endIndex < 0)
|
||||||
|
{
|
||||||
|
endIndex = ~endIndex - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startIndex > endIndex || startIndex >= orderedList.Count || orderedList[startIndex] > end || endIndex >= orderedList.Count)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return orderedList[endIndex];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2927,6 +2927,7 @@ $HorzAlign = Center
|
|||||||
public bool AlignTimeCodes { get; set; }
|
public bool AlignTimeCodes { get; set; }
|
||||||
public bool ExtractExactTimeCodes { get; set; }
|
public bool ExtractExactTimeCodes { get; set; }
|
||||||
public bool SnapToShotChanges { get; set; }
|
public bool SnapToShotChanges { get; set; }
|
||||||
|
public int OverlapThreshold { get; set; }
|
||||||
public BeautifyTimeCodesProfile Profile { get; set; }
|
public BeautifyTimeCodesProfile Profile { get; set; }
|
||||||
|
|
||||||
public BeautifyTimeCodesSettings()
|
public BeautifyTimeCodesSettings()
|
||||||
@ -2934,6 +2935,7 @@ $HorzAlign = Center
|
|||||||
AlignTimeCodes = true;
|
AlignTimeCodes = true;
|
||||||
ExtractExactTimeCodes = false;
|
ExtractExactTimeCodes = false;
|
||||||
SnapToShotChanges = true;
|
SnapToShotChanges = true;
|
||||||
|
OverlapThreshold = 1000;
|
||||||
Profile = new BeautifyTimeCodesProfile();
|
Profile = new BeautifyTimeCodesProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8757,6 +8759,12 @@ $HorzAlign = Center
|
|||||||
settings.BeautifyTimeCodes.SnapToShotChanges = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
|
settings.BeautifyTimeCodes.SnapToShotChanges = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subNode = node.SelectSingleNode("OverlapThreshold");
|
||||||
|
if (subNode != null)
|
||||||
|
{
|
||||||
|
settings.BeautifyTimeCodes.OverlapThreshold = Convert.ToInt32(subNode.InnerText, CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
var profileNode = node.SelectSingleNode("Profile");
|
var profileNode = node.SelectSingleNode("Profile");
|
||||||
if (profileNode != null)
|
if (profileNode != null)
|
||||||
{
|
{
|
||||||
@ -12327,6 +12335,7 @@ $HorzAlign = Center
|
|||||||
textWriter.WriteElementString("AlignTimeCodes", settings.BeautifyTimeCodes.AlignTimeCodes.ToString(CultureInfo.InvariantCulture));
|
textWriter.WriteElementString("AlignTimeCodes", settings.BeautifyTimeCodes.AlignTimeCodes.ToString(CultureInfo.InvariantCulture));
|
||||||
textWriter.WriteElementString("ExtractExactTimeCodes", settings.BeautifyTimeCodes.ExtractExactTimeCodes.ToString(CultureInfo.InvariantCulture));
|
textWriter.WriteElementString("ExtractExactTimeCodes", settings.BeautifyTimeCodes.ExtractExactTimeCodes.ToString(CultureInfo.InvariantCulture));
|
||||||
textWriter.WriteElementString("SnapToShotChanges", settings.BeautifyTimeCodes.SnapToShotChanges.ToString(CultureInfo.InvariantCulture));
|
textWriter.WriteElementString("SnapToShotChanges", settings.BeautifyTimeCodes.SnapToShotChanges.ToString(CultureInfo.InvariantCulture));
|
||||||
|
textWriter.WriteElementString("OverlapThreshold", settings.BeautifyTimeCodes.OverlapThreshold.ToString(CultureInfo.InvariantCulture));
|
||||||
textWriter.WriteStartElement("Profile", string.Empty);
|
textWriter.WriteStartElement("Profile", string.Empty);
|
||||||
textWriter.WriteElementString("Gap", settings.BeautifyTimeCodes.Profile.Gap.ToString(CultureInfo.InvariantCulture));
|
textWriter.WriteElementString("Gap", settings.BeautifyTimeCodes.Profile.Gap.ToString(CultureInfo.InvariantCulture));
|
||||||
textWriter.WriteElementString("InCuesGap", settings.BeautifyTimeCodes.Profile.InCuesGap.ToString(CultureInfo.InvariantCulture));
|
textWriter.WriteElementString("InCuesGap", settings.BeautifyTimeCodes.Profile.InCuesGap.ToString(CultureInfo.InvariantCulture));
|
||||||
|
@ -108,6 +108,25 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
|||||||
}
|
}
|
||||||
|
|
||||||
var distance = rightParagraph.StartTime.TotalMilliseconds - leftParagraph.EndTime.TotalMilliseconds;
|
var distance = rightParagraph.StartTime.TotalMilliseconds - leftParagraph.EndTime.TotalMilliseconds;
|
||||||
|
|
||||||
|
// Check if there is an overlap
|
||||||
|
if (distance < 0)
|
||||||
|
{
|
||||||
|
// If an overlap threshold is set, don't connect if threshold exceeded
|
||||||
|
if (Configuration.Settings.BeautifyTimeCodes.OverlapThreshold > 0 && Math.Abs(distance) >= Configuration.Settings.BeautifyTimeCodes.OverlapThreshold)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We are continuing, but there is still an overlap, so fix that first
|
||||||
|
leftParagraph.EndTime.TotalMilliseconds = rightParagraph.StartTime.TotalMilliseconds - 1;
|
||||||
|
|
||||||
|
// Re-calculate distance
|
||||||
|
distance = rightParagraph.StartTime.TotalMilliseconds - leftParagraph.EndTime.TotalMilliseconds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var subtitlesAreConnected = distance < Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesTreatConnected;
|
var subtitlesAreConnected = distance < Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesTreatConnected;
|
||||||
|
|
||||||
if (subtitlesAreConnected)
|
if (subtitlesAreConnected)
|
||||||
@ -126,14 +145,14 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
|||||||
var leftInCueFrame = MillisecondsToFrames(leftParagraph.StartTime.TotalMilliseconds);
|
var leftInCueFrame = MillisecondsToFrames(leftParagraph.StartTime.TotalMilliseconds);
|
||||||
var rightOutCueFrame = MillisecondsToFrames(rightParagraph.EndTime.TotalMilliseconds);
|
var rightOutCueFrame = MillisecondsToFrames(rightParagraph.EndTime.TotalMilliseconds);
|
||||||
|
|
||||||
// Check result
|
// Define align function for reusing
|
||||||
if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToRedZone && bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToRedZone)
|
void AlignCuesAroundClosestShotChange(int leftShotChangeFrame, int rightShotChangeFrame)
|
||||||
{
|
{
|
||||||
var fixInfoForLeft = GetFixedConnectedSubtitlesCueFrames(leftParagraph, rightParagraph, bestLeftOutCueFrameInfo.cueFrame);
|
var fixInfoForLeft = GetFixedConnectedSubtitlesCueFrames(leftParagraph, rightParagraph, leftShotChangeFrame);
|
||||||
var fixInfoForRight = GetFixedConnectedSubtitlesCueFrames(leftParagraph, rightParagraph, bestRightInCueFrameInfo.cueFrame);
|
var fixInfoForRight = GetFixedConnectedSubtitlesCueFrames(leftParagraph, rightParagraph, rightShotChangeFrame);
|
||||||
|
|
||||||
// Both are in red zones! We will use the closest shot change to align the cues around
|
// Calculate which shot change is closer
|
||||||
if (Math.Abs(newLeftOutCueFrame - bestLeftOutCueFrameInfo.cueFrame) <= Math.Abs(newRightInCueFrame - bestRightInCueFrameInfo.cueFrame))
|
if (Math.Abs(newLeftOutCueFrame - leftShotChangeFrame) <= Math.Abs(newRightInCueFrame - rightShotChangeFrame))
|
||||||
{
|
{
|
||||||
// Align around the left shot change
|
// Align around the left shot change
|
||||||
// Except, when the left subtitle now becomes invalid (negative duration) and the right subtitle won't, we will use the right shot change anyway
|
// Except, when the left subtitle now becomes invalid (negative duration) and the right subtitle won't, we will use the right shot change anyway
|
||||||
@ -168,6 +187,13 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check result
|
||||||
|
if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToRedZone && bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToRedZone)
|
||||||
|
{
|
||||||
|
// Both are in red zones! We will use the closest shot change to align the cues around
|
||||||
|
AlignCuesAroundClosestShotChange(bestLeftOutCueFrameInfo.cueFrame, bestRightInCueFrameInfo.cueFrame);
|
||||||
|
}
|
||||||
else if ((bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone || bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone) &&
|
else if ((bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone || bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone) &&
|
||||||
(bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone || bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone))
|
(bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone || bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone))
|
||||||
{
|
{
|
||||||
@ -273,7 +299,24 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
|||||||
}
|
}
|
||||||
else if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone)
|
else if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToLeftGreenZone)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("The left out cue cannot be snapped to the left side of a green zone while the right in cue is unaffected at the same time.");
|
// The left out cue wants to go backward, while the right in cue requires no action... The "Treat as connected" setting is probably really high.
|
||||||
|
// We'll use this function in case there are any shot changes closer to the right in cue.
|
||||||
|
var lastShotChangeInBetween = GetLastShotChangeFrameInBetween(bestLeftOutCueFrameInfo.cueFrame, bestRightInCueFrameInfo.cueFrame);
|
||||||
|
if (lastShotChangeInBetween != null)
|
||||||
|
{
|
||||||
|
// Derive left out cue shot change
|
||||||
|
var leftOutCueShotChange = bestLeftOutCueFrameInfo.cueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesLeftGreenZone;
|
||||||
|
|
||||||
|
// We will use the closest shot change to align the cues around
|
||||||
|
AlignCuesAroundClosestShotChange(leftOutCueShotChange, lastShotChangeInBetween.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There are no shot changes at all between the two cues! That likely means they are overlapping.
|
||||||
|
// Since the left out cue requires a change, we'll accommodate that: put the right in cue on the edge of the green zone, and push the previous subtitle backward.
|
||||||
|
newRightInCueFrame = bestLeftOutCueFrameInfo.cueFrame;
|
||||||
|
newLeftOutCueFrame = newRightInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone)
|
else if (bestLeftOutCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone)
|
||||||
{
|
{
|
||||||
@ -289,7 +332,24 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
|||||||
}
|
}
|
||||||
else if (bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone)
|
else if (bestRightInCueFrameInfo.result == FindBestCueResult.SnappedToRightGreenZone)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("The right in cue cannot be snapped to the right side of a green zone while the left out cue is unaffected at the same time.");
|
// The right in cue wants to go forward, while the left out cue requires no action... The "Treat as connected" setting is probably really high.
|
||||||
|
// We'll use this function in case there are any shot changes closer to the left out cue.
|
||||||
|
var firstShotChangeInBetween = GetFirstShotChangeFrameInBetween(bestLeftOutCueFrameInfo.cueFrame, bestRightInCueFrameInfo.cueFrame);
|
||||||
|
if (firstShotChangeInBetween != null)
|
||||||
|
{
|
||||||
|
// Derive right in cue shot change
|
||||||
|
var rightInCueShotChange = bestRightInCueFrameInfo.cueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.ConnectedSubtitlesRightGreenZone;
|
||||||
|
|
||||||
|
// We will use the closest shot change to align the cues around
|
||||||
|
AlignCuesAroundClosestShotChange(firstShotChangeInBetween.Value, rightInCueShotChange);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There are no shot changes at all between the two cues! That likely means they are overlapping.
|
||||||
|
// Since the right in cue requires a change, we'll accommodate that: put the left out cue on the edge of the green zone, and push the next subtitle forward.
|
||||||
|
newLeftOutCueFrame = bestRightInCueFrameInfo.cueFrame;
|
||||||
|
newRightInCueFrame = newLeftOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.Gap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -422,6 +482,23 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var distance = rightParagraph.StartTime.TotalMilliseconds - leftParagraph.EndTime.TotalMilliseconds;
|
||||||
|
|
||||||
|
// Check if there is an overlap
|
||||||
|
if (distance < 0)
|
||||||
|
{
|
||||||
|
// If an overlap threshold is set, don't chain if threshold exceeded
|
||||||
|
if (Configuration.Settings.BeautifyTimeCodes.OverlapThreshold > 0 && Math.Abs(distance) >= Configuration.Settings.BeautifyTimeCodes.OverlapThreshold)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We are continuing, but there is still an overlap, so fix that first
|
||||||
|
leftParagraph.EndTime.TotalMilliseconds = rightParagraph.StartTime.TotalMilliseconds - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var newLeftOutCueFrame = MillisecondsToFrames(leftParagraph.EndTime.TotalMilliseconds);
|
var newLeftOutCueFrame = MillisecondsToFrames(leftParagraph.EndTime.TotalMilliseconds);
|
||||||
var newRightInCueFrame = MillisecondsToFrames(rightParagraph.StartTime.TotalMilliseconds);
|
var newRightInCueFrame = MillisecondsToFrames(rightParagraph.StartTime.TotalMilliseconds);
|
||||||
|
|
||||||
@ -716,8 +793,19 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
|||||||
var previousParagraph = _subtitle.Paragraphs.ElementAtOrDefault(index - 1);
|
var previousParagraph = _subtitle.Paragraphs.ElementAtOrDefault(index - 1);
|
||||||
if (previousParagraph != null)
|
if (previousParagraph != null)
|
||||||
{
|
{
|
||||||
var previousOutCueFrame = MillisecondsToFrames(previousParagraph.EndTime.TotalMilliseconds);
|
var distance = previousParagraph.StartTime.TotalMilliseconds - paragraph.EndTime.TotalMilliseconds;
|
||||||
newCueFrame = Math.Max(bestCueFrame, previousOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.Gap);
|
|
||||||
|
// If an overlap threshold is set, don't fix if threshold exceeded
|
||||||
|
if (distance < 0 && Configuration.Settings.BeautifyTimeCodes.OverlapThreshold > 0 && Math.Abs(distance) >= Configuration.Settings.BeautifyTimeCodes.OverlapThreshold)
|
||||||
|
{
|
||||||
|
newCueFrame = bestCueFrame;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Else, limit to adjacent subtitle
|
||||||
|
var previousOutCueFrame = MillisecondsToFrames(previousParagraph.EndTime.TotalMilliseconds);
|
||||||
|
newCueFrame = Math.Max(bestCueFrame, previousOutCueFrame + Configuration.Settings.BeautifyTimeCodes.Profile.Gap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -729,8 +817,19 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
|||||||
var nextParagraph = _subtitle.Paragraphs.ElementAtOrDefault(index + 1);
|
var nextParagraph = _subtitle.Paragraphs.ElementAtOrDefault(index + 1);
|
||||||
if (nextParagraph != null)
|
if (nextParagraph != null)
|
||||||
{
|
{
|
||||||
var nextInCueFrame = MillisecondsToFrames(nextParagraph.StartTime.TotalMilliseconds);
|
var distance = paragraph.StartTime.TotalMilliseconds - nextParagraph.EndTime.TotalMilliseconds;
|
||||||
newCueFrame = Math.Min(bestCueFrame, nextInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap);
|
|
||||||
|
// If an overlap threshold is set, don't fix if threshold exceeded
|
||||||
|
if (distance < 0 && Configuration.Settings.BeautifyTimeCodes.OverlapThreshold > 0 && Math.Abs(distance) >= Configuration.Settings.BeautifyTimeCodes.OverlapThreshold)
|
||||||
|
{
|
||||||
|
newCueFrame = bestCueFrame;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Else, limit to adjacent subtitle
|
||||||
|
var nextInCueFrame = MillisecondsToFrames(nextParagraph.StartTime.TotalMilliseconds);
|
||||||
|
newCueFrame = Math.Min(bestCueFrame, nextInCueFrame - Configuration.Settings.BeautifyTimeCodes.Profile.Gap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -902,6 +1001,16 @@ namespace Nikse.SubtitleEdit.Core.Forms
|
|||||||
return _shotChangesFrames.FirstWithin(leftCueFrame, rightCueFrame);
|
return _shotChangesFrames.FirstWithin(leftCueFrame, rightCueFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int? GetLastShotChangeFrameInBetween(int leftCueFrame, int rightCueFrame)
|
||||||
|
{
|
||||||
|
if (_shotChangesFrames == null || _shotChangesFrames.Count == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _shotChangesFrames.LastWithin(leftCueFrame, rightCueFrame);
|
||||||
|
}
|
||||||
|
|
||||||
private int? GetClosestShotChangeFrame(int cueFrame)
|
private int? GetClosestShotChangeFrame(int cueFrame)
|
||||||
{
|
{
|
||||||
if (_shotChangesFrames == null || _shotChangesFrames.Count == 0)
|
if (_shotChangesFrames == null || _shotChangesFrames.Count == 0)
|
||||||
|
@ -1068,6 +1068,7 @@ Command line: {1} {2}
|
|||||||
<XRequiresALocalWebServer>"{0}" 需要在本地运行的网页服务器!</XRequiresALocalWebServer>
|
<XRequiresALocalWebServer>"{0}" 需要在本地运行的网页服务器!</XRequiresALocalWebServer>
|
||||||
<XRequiresAnApiKey>"{0}"需要一个API密钥。</XRequiresAnApiKey>
|
<XRequiresAnApiKey>"{0}"需要一个API密钥。</XRequiresAnApiKey>
|
||||||
<ReadMore>了解更多?</ReadMore>
|
<ReadMore>了解更多?</ReadMore>
|
||||||
|
<Formality>正式程度</Formality>
|
||||||
</GoogleTranslate>
|
</GoogleTranslate>
|
||||||
<GoogleOrMicrosoftTranslate>
|
<GoogleOrMicrosoftTranslate>
|
||||||
<Title>谷歌 与 微软 翻译</Title>
|
<Title>谷歌 与 微软 翻译</Title>
|
||||||
|
Loading…
Reference in New Issue
Block a user