diff --git a/LanguageBaseEnglish.xml b/LanguageBaseEnglish.xml
index 2351dddf9..c2cd1b1b7 100644
--- a/LanguageBaseEnglish.xml
+++ b/LanguageBaseEnglish.xml
@@ -192,6 +192,7 @@ Read more info (web)?
Transcribing audio to text - file {0} of {1}...
{0} files saved to video source folder
Use post-processing (line merge, fix casing, punctuation, and more)
+ Auto adjust timings
Batch mode
Keep partial transcription
Translate to English
diff --git a/src/libse/AudioToText/AudioToTextPostProcessor.cs b/src/libse/AudioToText/AudioToTextPostProcessor.cs
index 118328f04..8bd7b6370 100644
--- a/src/libse/AudioToText/AudioToTextPostProcessor.cs
+++ b/src/libse/AudioToText/AudioToTextPostProcessor.cs
@@ -40,7 +40,7 @@ namespace Nikse.SubtitleEdit.Core.AudioToText
}
}
- public Subtitle Generate(Engine engine, List resultTexts, bool usePostProcessing, bool addPeriods, bool mergeLines, bool fixCasing, bool fixShortDuration, bool splitLines)
+ public Subtitle Generate(Engine engine, List resultTexts, bool usePostProcessing, bool addPeriods, bool mergeLines, bool fixCasing, bool fixShortDuration, bool splitLines, bool autoAdjustTimings, WavePeakData wavePeaks)
{
_resultTexts = resultTexts;
var subtitle = new Subtitle();
@@ -57,6 +57,12 @@ namespace Nikse.SubtitleEdit.Core.AudioToText
}
}
+ if (autoAdjustTimings && wavePeaks != null)
+ {
+ subtitle = WhisperTimingFixer.ShortenLongTexts(subtitle);
+ subtitle = WhisperTimingFixer.ShortenViaWavePeaks(subtitle, wavePeaks);
+ }
+
return Generate(subtitle, usePostProcessing, addPeriods, mergeLines, fixCasing, fixShortDuration, splitLines);
}
diff --git a/src/libse/AudioToText/WhisperTimingFixer.cs b/src/libse/AudioToText/WhisperTimingFixer.cs
new file mode 100644
index 000000000..3339dfe6c
--- /dev/null
+++ b/src/libse/AudioToText/WhisperTimingFixer.cs
@@ -0,0 +1,202 @@
+using Nikse.SubtitleEdit.Core.Common;
+using System;
+
+namespace Nikse.SubtitleEdit.Core.AudioToText
+{
+ public static class WhisperTimingFixer
+ {
+ private static int SecondsToSampleIndex(double seconds, int sampleRate)
+ {
+ return (int)Math.Round(seconds * sampleRate, MidpointRounding.AwayFromZero);
+ }
+
+ private static double FindPercentage(double startSeconds, double endSeconds, WavePeakData wavePeaks)
+ {
+ var min = Math.Max(0, SecondsToSampleIndex(startSeconds, wavePeaks.SampleRate));
+ var max = Math.Min(wavePeaks.Peaks.Count, SecondsToSampleIndex(endSeconds, wavePeaks.SampleRate));
+
+ var minPeak = int.MaxValue;
+ var maxPeak = int.MinValue;
+ var count = 0;
+ for (var i = min; i < max; i++)
+ {
+ var v = wavePeaks.Peaks[i].Abs;
+ count++;
+ if (v < minPeak)
+ {
+ minPeak = v;
+ }
+ if (v > maxPeak)
+ {
+ maxPeak = v;
+ }
+ }
+
+ if (count == 0)
+ {
+ return -1;
+ }
+
+ var pctMin = minPeak * 100.0 / wavePeaks.HighestPeak;
+ var pctMax = maxPeak * 100.0 / wavePeaks.HighestPeak;
+ return (pctMin + pctMax) / 2.0;
+ }
+
+ public static Subtitle ShortenViaWavePeaks(Subtitle subtitle, WavePeakData wavePeaks)
+ {
+ var s = new Subtitle(subtitle);
+ const double percentageMax = 7.0;
+
+ for (var index = 0; index < s.Paragraphs.Count; index++)
+ {
+ var p = s.Paragraphs[index];
+ var prevEndSecs = -1.0;
+ if (index > 0)
+ {
+ prevEndSecs = s.Paragraphs[index].EndTime.TotalSeconds;
+ }
+
+ // Find nearest silence
+ var startPos = p.StartTime.TotalSeconds;
+ var pctHere = FindPercentage(startPos - 0.05, startPos + 0.05, wavePeaks);
+ if (Math.Abs(pctHere - 1) < 0.01)
+ {
+ return s;
+ }
+
+ if (pctHere > percentageMax)
+ {
+ var startPosBack = startPos;
+ var startPosForward = startPos;
+ for (var ms = 50; ms < 255; ms += 50)
+ {
+ var pct = FindPercentage(startPosBack - 0.05, startPosBack + 0.05, wavePeaks);
+ if (Math.Abs(pct - 1) < 0.01)
+ {
+ return s;
+ }
+
+ if (pct < percentageMax + 1 && p.Duration.TotalSeconds < 5)
+ {
+ startPosBack -= 0.025;
+ var pct2 = FindPercentage(startPosBack - 0.05, startPosBack + 0.05, wavePeaks);
+ if (pct2 < pct && pct2 >= 0)
+ {
+ var x = startPosBack + 0.05;
+ if (x < 0)
+ {
+ x = 0;
+ }
+
+ if (x > prevEndSecs)
+ {
+ p.StartTime.TotalMilliseconds = x * 1000.0;
+ }
+ }
+ else
+ {
+ var x = startPosBack + 0.025 + 0.05;
+ if (x < 0)
+ {
+ x = 0;
+ }
+
+ if (x > prevEndSecs)
+ {
+ p.StartTime.TotalMilliseconds = x * 1000.0;
+ }
+ }
+
+ break;
+ }
+
+ startPosBack -= 0.05;
+
+
+
+ var pctF = FindPercentage(startPosForward - 0.05, startPosForward + 0.05, wavePeaks);
+ if (Math.Abs(pctHere - 1) < 0.01)
+ {
+ return s;
+ }
+
+ if (pctF < percentageMax)
+ {
+ startPosForward -= 0.025;
+ var pct2 = FindPercentage(startPosForward - 0.05, startPosForward + 0.05, wavePeaks);
+ if (pct2 < pctF && pct2 >= 0)
+ {
+ p.StartTime.TotalSeconds = startPosForward + 0.05;
+ }
+ else
+ {
+ p.StartTime.TotalSeconds = startPosForward + 0.025 + 0.05;
+ }
+
+ break;
+ }
+
+ startPosForward += 0.05;
+ }
+ }
+
+ // find next non-silence
+ startPos = p.StartTime.TotalSeconds;
+ pctHere = FindPercentage(startPos - 0.05, startPos + 0.05, wavePeaks);
+ if (pctHere < percentageMax)
+ {
+ var startPosForward = p.StartTime.TotalSeconds;
+ while (pctHere < percentageMax && startPos < p.EndTime.TotalSeconds - 1)
+ {
+ pctHere = FindPercentage(startPosForward - 0.05, startPosForward + 0.05, wavePeaks);
+ if (Math.Abs(pctHere - 1) < 0.01)
+ {
+ return s;
+ }
+
+ p.StartTime.TotalSeconds = startPosForward;
+ if (pctHere >= percentageMax)
+ {
+ startPosForward -= 0.025;
+ var pct2 = FindPercentage(startPosForward - 0.05, startPosForward + 0.05, wavePeaks);
+ if (pct2 < pctHere && pct2 >= 0)
+ {
+ p.StartTime.TotalSeconds -= 0.025;
+
+ pctHere = pct2;
+ startPosForward -= 0.025;
+ pct2 = FindPercentage(startPosForward - 0.05, startPosForward + 0.05, wavePeaks);
+ if (pct2 < pctHere && pct2 >= 0)
+ {
+ p.StartTime.TotalSeconds -= 0.025;
+ }
+ }
+
+ break;
+ }
+
+ startPosForward += 0.05;
+ }
+ }
+ }
+
+ return s;
+ }
+
+ public static Subtitle ShortenLongTexts(Subtitle subtitle)
+ {
+ var s = new Subtitle(subtitle);
+
+ for (var i = 0; i < subtitle.Paragraphs.Count; i++)
+ {
+ var p = subtitle.Paragraphs[i];
+ if (p.Duration.TotalSeconds > 5)
+ {
+ p.StartTime.TotalMilliseconds = p.EndTime.TotalMilliseconds - 5000;
+ }
+ }
+
+ return s;
+ }
+ }
+}
diff --git a/src/libse/Common/Settings.cs b/src/libse/Common/Settings.cs
index fbf60d617..55fd6ab8b 100644
--- a/src/libse/Common/Settings.cs
+++ b/src/libse/Common/Settings.cs
@@ -417,6 +417,7 @@ namespace Nikse.SubtitleEdit.Core.Common
public string WhisperLanguageCode { get; set; }
public string WhisperLocation { get; set; }
public string WhisperExtraSettings { get; set; }
+ public bool WhisperAutoAdjustTimings { get; set; }
public int AudioToTextLineMaxChars { get; set; }
public int AudioToTextLineMaxCharsJp { get; set; }
public int AudioToTextLineMaxCharsCn { get; set; }
@@ -621,6 +622,7 @@ namespace Nikse.SubtitleEdit.Core.Common
WhisperDeleteTempFiles = true;
WhisperExtraSettings = "";
WhisperLanguageCode = "en";
+ WhisperAutoAdjustTimings = true;
AudioToTextLineMaxChars = 86;
AudioToTextLineMaxCharsJp = 32;
AudioToTextLineMaxCharsCn = 36;
@@ -6177,6 +6179,12 @@ $HorzAlign = Center
settings.Tools.WhisperLanguageCode = subNode.InnerText;
}
+ subNode = node.SelectSingleNode("WhisperAutoAdjustTimings");
+ if (subNode != null)
+ {
+ settings.Tools.WhisperAutoAdjustTimings = Convert.ToBoolean(subNode.InnerText, CultureInfo.InvariantCulture);
+ }
+
subNode = node.SelectSingleNode("AudioToTextLineMaxChars");
if (subNode != null)
{
@@ -10429,6 +10437,7 @@ $HorzAlign = Center
textWriter.WriteElementString("WhisperLocation", settings.Tools.WhisperLocation);
textWriter.WriteElementString("WhisperExtraSettings", settings.Tools.WhisperExtraSettings);
textWriter.WriteElementString("WhisperLanguageCode", settings.Tools.WhisperLanguageCode);
+ textWriter.WriteElementString("WhisperAutoAdjustTimings", settings.Tools.WhisperAutoAdjustTimings.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("AudioToTextLineMaxChars", settings.Tools.AudioToTextLineMaxChars.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("AudioToTextLineMaxCharsJp", settings.Tools.AudioToTextLineMaxCharsJp.ToString(CultureInfo.InvariantCulture));
textWriter.WriteElementString("AudioToTextLineMaxCharsCn", settings.Tools.AudioToTextLineMaxCharsCn.ToString(CultureInfo.InvariantCulture));
diff --git a/src/libse/SubtitleFormats/SubtitleFormat.cs b/src/libse/SubtitleFormats/SubtitleFormat.cs
index be07e0cea..f1ad6d3a3 100644
--- a/src/libse/SubtitleFormats/SubtitleFormat.cs
+++ b/src/libse/SubtitleFormats/SubtitleFormat.cs
@@ -236,6 +236,7 @@ namespace Nikse.SubtitleEdit.Core.SubtitleFormats
new VocapiaSplit(),
new WebVTT(),
new WebVTTFileWithLineNumber(),
+ new WhisperRaw(),
new Xif(),
new Xmp(),
new YouTubeAnnotations(),
diff --git a/src/libse/SubtitleFormats/WhisperRaw.cs b/src/libse/SubtitleFormats/WhisperRaw.cs
new file mode 100644
index 000000000..4cd466d04
--- /dev/null
+++ b/src/libse/SubtitleFormats/WhisperRaw.cs
@@ -0,0 +1,76 @@
+using Nikse.SubtitleEdit.Core.Common;
+using Nikse.SubtitleEdit.Core.Enums;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Nikse.SubtitleEdit.Core.SubtitleFormats
+{
+ public class WhisperRaw : SubtitleFormat
+ {
+ private readonly Regex _timeRegexShort = new Regex(@"^\[\d\d:\d\d[\.,]\d\d\d --> \d\d:\d\d[\.,]\d\d\d\]", RegexOptions.Compiled);
+ private readonly Regex _timeRegexLong = new Regex(@"^\[\d\d:\d\d:\d\d[\.,]\d\d\d --> \d\d:\d\d:\d\d[\.,]\d\d\d]", RegexOptions.Compiled);
+ public override string Extension => ".txt";
+ public override string Name => "Whisper Raw";
+
+ public override string ToText(Subtitle subtitle, string title)
+ {
+ var sb = new StringBuilder();
+ const string writeFormat = "[{0} --> {1}] {2}";
+ foreach (var p in subtitle.Paragraphs)
+ {
+ sb.AppendLine(string.Format(writeFormat, EncodeEndTimeCode(p.StartTime), EncodeEndTimeCode(p.EndTime), HtmlUtil.RemoveHtmlTags(p.Text.Replace(Environment.NewLine, " "), true)));
+ sb.AppendLine();
+ }
+
+ return sb.ToString();
+ }
+
+ private static string EncodeEndTimeCode(TimeCode time)
+ {
+ return $"{time.ToDisplayString()}";
+ }
+
+ public override void LoadSubtitle(Subtitle subtitle, List lines, string fileName)
+ {
+ subtitle.Paragraphs.Clear();
+ _errorCount = 0;
+ foreach (var line in lines)
+ {
+ var trimmedLine = line.Trim();
+ if (trimmedLine.StartsWith('['))
+ {
+ if (_timeRegexShort.IsMatch(trimmedLine))
+ {
+ var start = trimmedLine.Substring(1, 10);
+ var end = trimmedLine.Substring(14, 10);
+ var text = trimmedLine.Remove(0, 25).Trim();
+ if (!string.IsNullOrEmpty(text))
+ {
+ subtitle.Paragraphs.Add(new Paragraph(text, GetMs(start), GetMs(end)));
+ }
+ }
+ else if (_timeRegexLong.IsMatch(trimmedLine))
+ {
+ var start = trimmedLine.Substring(1, 12);
+ var end = trimmedLine.Substring(18, 12);
+ var text = trimmedLine.Remove(0, 31).Trim();
+ if (!string.IsNullOrEmpty(text))
+ {
+ subtitle.Paragraphs.Add(new Paragraph(text, GetMs(start), GetMs(end)));
+ }
+ }
+ }
+ }
+
+ subtitle.Sort(SubtitleSortCriteria.StartTime);
+ subtitle.Renumber();
+ }
+
+ private static double GetMs(string timeCode)
+ {
+ return TimeCode.ParseToMilliseconds(timeCode);
+ }
+ }
+}
diff --git a/src/ui/Controls/AudioVisualizer.cs b/src/ui/Controls/AudioVisualizer.cs
index 52b9549f9..2bb3a1b2f 100644
--- a/src/ui/Controls/AudioVisualizer.cs
+++ b/src/ui/Controls/AudioVisualizer.cs
@@ -1158,13 +1158,13 @@ namespace Nikse.SubtitleEdit.Controls
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int SecondsToXPosition(double seconds)
{
- return (int)Math.Round(seconds * _wavePeaks.SampleRate * _zoomFactor);
+ return (int)Math.Round(seconds * _wavePeaks.SampleRate * _zoomFactor, MidpointRounding.AwayFromZero);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int SecondsToSampleIndex(double seconds)
{
- return (int)Math.Round(seconds * _wavePeaks.SampleRate);
+ return (int)Math.Round(seconds * _wavePeaks.SampleRate, MidpointRounding.AwayFromZero);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/ui/Forms/AudioToText/VoskAudioToText.cs b/src/ui/Forms/AudioToText/VoskAudioToText.cs
index 0514d0619..c2e33d5c1 100644
--- a/src/ui/Forms/AudioToText/VoskAudioToText.cs
+++ b/src/ui/Forms/AudioToText/VoskAudioToText.cs
@@ -156,7 +156,7 @@ namespace Nikse.SubtitleEdit.Forms.AudioToText
{
ParagraphMaxChars = Configuration.Settings.General.SubtitleLineMaximumLength * 2,
};
- TranscribedSubtitle = postProcessor.Generate(AudioToTextPostProcessor.Engine.Vosk, transcript, checkBoxUsePostProcessing.Checked, true, true, true, true, false);
+ TranscribedSubtitle = postProcessor.Generate(AudioToTextPostProcessor.Engine.Vosk, transcript, checkBoxUsePostProcessing.Checked, true, true, true, true, false, false, null);
DialogResult = DialogResult.OK;
}
@@ -218,7 +218,7 @@ namespace Nikse.SubtitleEdit.Forms.AudioToText
{
ParagraphMaxChars = Configuration.Settings.General.SubtitleLineMaximumLength * 2,
};
- TranscribedSubtitle = postProcessor.Generate(AudioToTextPostProcessor.Engine.Vosk, transcript, checkBoxUsePostProcessing.Checked, true, true, true, true, false);
+ TranscribedSubtitle = postProcessor.Generate(AudioToTextPostProcessor.Engine.Vosk, transcript, checkBoxUsePostProcessing.Checked, true, true, true, true, false, false, null);
SaveToSourceFolder(videoFileName);
TaskbarList.SetProgressValue(_parentForm.Handle, _batchFileNumber, listViewInputFiles.Items.Count);
diff --git a/src/ui/Forms/AudioToText/VoskAudioToTextSelectedLines.cs b/src/ui/Forms/AudioToText/VoskAudioToTextSelectedLines.cs
index 689653498..2c4e7d5ea 100644
--- a/src/ui/Forms/AudioToText/VoskAudioToTextSelectedLines.cs
+++ b/src/ui/Forms/AudioToText/VoskAudioToTextSelectedLines.cs
@@ -127,7 +127,7 @@ namespace Nikse.SubtitleEdit.Forms.AudioToText
return;
}
- TranscribedSubtitle = postProcessor.Generate(AudioToTextPostProcessor.Engine.Vosk, transcript, checkBoxUsePostProcessing.Checked, false, true, false, false, false);
+ TranscribedSubtitle = postProcessor.Generate(AudioToTextPostProcessor.Engine.Vosk, transcript, checkBoxUsePostProcessing.Checked, false, true, false, false, false, false, null);
progressBar1.Value = (int)Math.Round(_batchFileNumber * 100.0 / _audioClips.Count, MidpointRounding.AwayFromZero);
progressBar1.Refresh();
diff --git a/src/ui/Forms/AudioToText/WhisperAudioToText.Designer.cs b/src/ui/Forms/AudioToText/WhisperAudioToText.Designer.cs
index 12e061ada..7e20acd04 100644
--- a/src/ui/Forms/AudioToText/WhisperAudioToText.Designer.cs
+++ b/src/ui/Forms/AudioToText/WhisperAudioToText.Designer.cs
@@ -62,6 +62,7 @@
this.whisperCppCToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.removeTemporaryFilesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.checkBoxAutoAdjustTimings = new System.Windows.Forms.CheckBox();
this.groupBoxModels.SuspendLayout();
this.groupBoxInputFiles.SuspendLayout();
this.contextMenuStripWhisperAdvanced.SuspendLayout();
@@ -72,10 +73,10 @@
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.buttonCancel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
- this.buttonCancel.Location = new System.Drawing.Point(622, 427);
+ this.buttonCancel.Location = new System.Drawing.Point(622, 457);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
- this.buttonCancel.TabIndex = 10;
+ this.buttonCancel.TabIndex = 8;
this.buttonCancel.Text = "C&ancel";
this.buttonCancel.UseVisualStyleBackColor = true;
this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
@@ -84,10 +85,10 @@
//
this.buttonGenerate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonGenerate.ImeMode = System.Windows.Forms.ImeMode.NoControl;
- this.buttonGenerate.Location = new System.Drawing.Point(373, 427);
+ this.buttonGenerate.Location = new System.Drawing.Point(373, 457);
this.buttonGenerate.Name = "buttonGenerate";
this.buttonGenerate.Size = new System.Drawing.Size(125, 23);
- this.buttonGenerate.TabIndex = 8;
+ this.buttonGenerate.TabIndex = 6;
this.buttonGenerate.Text = "&Generate";
this.buttonGenerate.UseVisualStyleBackColor = true;
this.buttonGenerate.Click += new System.EventHandler(this.ButtonGenerate_Click);
@@ -96,7 +97,7 @@
//
this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
- this.progressBar1.Location = new System.Drawing.Point(12, 427);
+ this.progressBar1.Location = new System.Drawing.Point(12, 457);
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(355, 12);
this.progressBar1.TabIndex = 7;
@@ -106,7 +107,7 @@
//
this.labelProgress.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.labelProgress.AutoSize = true;
- this.labelProgress.Location = new System.Drawing.Point(12, 409);
+ this.labelProgress.Location = new System.Drawing.Point(12, 439);
this.labelProgress.Name = "labelProgress";
this.labelProgress.Size = new System.Drawing.Size(70, 13);
this.labelProgress.TabIndex = 6;
@@ -121,7 +122,7 @@
this.textBoxLog.Multiline = true;
this.textBoxLog.Name = "textBoxLog";
this.textBoxLog.ScrollBars = System.Windows.Forms.ScrollBars.Both;
- this.textBoxLog.Size = new System.Drawing.Size(168, 258);
+ this.textBoxLog.Size = new System.Drawing.Size(168, 288);
this.textBoxLog.TabIndex = 0;
//
// labelInfo
@@ -146,7 +147,7 @@
this.groupBoxModels.Location = new System.Drawing.Point(15, 59);
this.groupBoxModels.Name = "groupBoxModels";
this.groupBoxModels.Size = new System.Drawing.Size(682, 83);
- this.groupBoxModels.TabIndex = 3;
+ this.groupBoxModels.TabIndex = 1;
this.groupBoxModels.TabStop = false;
this.groupBoxModels.Text = "Language and models";
//
@@ -166,7 +167,7 @@
this.comboBoxLanguages.Location = new System.Drawing.Point(6, 44);
this.comboBoxLanguages.Name = "comboBoxLanguages";
this.comboBoxLanguages.Size = new System.Drawing.Size(240, 21);
- this.comboBoxLanguages.TabIndex = 5;
+ this.comboBoxLanguages.TabIndex = 0;
this.comboBoxLanguages.SelectedIndexChanged += new System.EventHandler(this.comboBoxLanguages_SelectedIndexChanged);
//
// buttonDownload
@@ -215,7 +216,7 @@
this.linkLabeWhisperWebSite.Location = new System.Drawing.Point(12, 26);
this.linkLabeWhisperWebSite.Name = "linkLabeWhisperWebSite";
this.linkLabeWhisperWebSite.Size = new System.Drawing.Size(85, 13);
- this.linkLabeWhisperWebSite.TabIndex = 2;
+ this.linkLabeWhisperWebSite.TabIndex = 0;
this.linkLabeWhisperWebSite.TabStop = true;
this.linkLabeWhisperWebSite.Text = "Whisper website";
this.linkLabeWhisperWebSite.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelWhisperWebsite_LinkClicked);
@@ -224,7 +225,7 @@
//
this.labelTime.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.labelTime.AutoSize = true;
- this.labelTime.Location = new System.Drawing.Point(12, 442);
+ this.labelTime.Location = new System.Drawing.Point(12, 472);
this.labelTime.Name = "labelTime";
this.labelTime.Size = new System.Drawing.Size(88, 13);
this.labelTime.TabIndex = 6;
@@ -237,21 +238,22 @@
// checkBoxUsePostProcessing
//
this.checkBoxUsePostProcessing.AutoSize = true;
- this.checkBoxUsePostProcessing.Location = new System.Drawing.Point(15, 177);
+ this.checkBoxUsePostProcessing.Location = new System.Drawing.Point(15, 185);
this.checkBoxUsePostProcessing.Name = "checkBoxUsePostProcessing";
this.checkBoxUsePostProcessing.Size = new System.Drawing.Size(312, 17);
this.checkBoxUsePostProcessing.TabIndex = 4;
this.checkBoxUsePostProcessing.Text = "Use post-processing (line merge, fix casing, and punctuation)";
this.checkBoxUsePostProcessing.UseVisualStyleBackColor = true;
+ this.checkBoxUsePostProcessing.CheckedChanged += new System.EventHandler(this.checkBoxUsePostProcessing_CheckedChanged);
//
// buttonBatchMode
//
this.buttonBatchMode.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonBatchMode.ImeMode = System.Windows.Forms.ImeMode.NoControl;
- this.buttonBatchMode.Location = new System.Drawing.Point(504, 427);
+ this.buttonBatchMode.Location = new System.Drawing.Point(504, 457);
this.buttonBatchMode.Name = "buttonBatchMode";
this.buttonBatchMode.Size = new System.Drawing.Size(112, 23);
- this.buttonBatchMode.TabIndex = 9;
+ this.buttonBatchMode.TabIndex = 7;
this.buttonBatchMode.Text = "Batch mode";
this.buttonBatchMode.UseVisualStyleBackColor = true;
this.buttonBatchMode.Click += new System.EventHandler(this.buttonBatchMode_Click);
@@ -265,9 +267,9 @@
this.groupBoxInputFiles.Controls.Add(this.buttonRemoveFile);
this.groupBoxInputFiles.Controls.Add(this.buttonAddFile);
this.groupBoxInputFiles.Controls.Add(this.listViewInputFiles);
- this.groupBoxInputFiles.Location = new System.Drawing.Point(15, 200);
+ this.groupBoxInputFiles.Location = new System.Drawing.Point(15, 246);
this.groupBoxInputFiles.Name = "groupBoxInputFiles";
- this.groupBoxInputFiles.Size = new System.Drawing.Size(682, 185);
+ this.groupBoxInputFiles.Size = new System.Drawing.Size(682, 169);
this.groupBoxInputFiles.TabIndex = 5;
this.groupBoxInputFiles.TabStop = false;
this.groupBoxInputFiles.Text = "Input files";
@@ -317,7 +319,7 @@
this.listViewInputFiles.HideSelection = false;
this.listViewInputFiles.Location = new System.Drawing.Point(6, 18);
this.listViewInputFiles.Name = "listViewInputFiles";
- this.listViewInputFiles.Size = new System.Drawing.Size(591, 150);
+ this.listViewInputFiles.Size = new System.Drawing.Size(591, 134);
this.listViewInputFiles.TabIndex = 0;
this.listViewInputFiles.UseCompatibleStateImageBehavior = false;
this.listViewInputFiles.View = System.Windows.Forms.View.Details;
@@ -334,7 +336,7 @@
//
this.labelFC.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.labelFC.ForeColor = System.Drawing.Color.Gray;
- this.labelFC.Location = new System.Drawing.Point(247, 442);
+ this.labelFC.Location = new System.Drawing.Point(247, 472);
this.labelFC.Name = "labelFC";
this.labelFC.Size = new System.Drawing.Size(120, 17);
this.labelFC.TabIndex = 19;
@@ -347,7 +349,7 @@
this.checkBoxTranslateToEnglish.Location = new System.Drawing.Point(15, 153);
this.checkBoxTranslateToEnglish.Name = "checkBoxTranslateToEnglish";
this.checkBoxTranslateToEnglish.Size = new System.Drawing.Size(119, 17);
- this.checkBoxTranslateToEnglish.TabIndex = 20;
+ this.checkBoxTranslateToEnglish.TabIndex = 2;
this.checkBoxTranslateToEnglish.Text = "Translate to English";
this.checkBoxTranslateToEnglish.UseVisualStyleBackColor = true;
//
@@ -365,7 +367,7 @@
// labelElapsed
//
this.labelElapsed.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
- this.labelElapsed.Location = new System.Drawing.Point(215, 409);
+ this.labelElapsed.Location = new System.Drawing.Point(215, 439);
this.labelElapsed.Name = "labelElapsed";
this.labelElapsed.Size = new System.Drawing.Size(152, 13);
this.labelElapsed.TabIndex = 22;
@@ -380,7 +382,7 @@
this.toolStripSeparator1,
this.removeTemporaryFilesToolStripMenuItem});
this.contextMenuStripWhisperAdvanced.Name = "contextMenuStripWhisperAdvanced";
- this.contextMenuStripWhisperAdvanced.Size = new System.Drawing.Size(200, 98);
+ this.contextMenuStripWhisperAdvanced.Size = new System.Drawing.Size(200, 76);
//
// whisperPhpOriginalToolStripMenuItem
//
@@ -408,11 +410,22 @@
this.removeTemporaryFilesToolStripMenuItem.Text = "Remove temporary files";
this.removeTemporaryFilesToolStripMenuItem.Click += new System.EventHandler(this.removeTemporaryFilesToolStripMenuItem_Click);
//
+ // checkBoxAutoAdjustTimings
+ //
+ this.checkBoxAutoAdjustTimings.AutoSize = true;
+ this.checkBoxAutoAdjustTimings.Location = new System.Drawing.Point(42, 208);
+ this.checkBoxAutoAdjustTimings.Name = "checkBoxAutoAdjustTimings";
+ this.checkBoxAutoAdjustTimings.Size = new System.Drawing.Size(114, 17);
+ this.checkBoxAutoAdjustTimings.TabIndex = 3;
+ this.checkBoxAutoAdjustTimings.Text = "Auto adjust timings";
+ this.checkBoxAutoAdjustTimings.UseVisualStyleBackColor = true;
+ //
// WhisperAudioToText
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(709, 464);
+ this.ClientSize = new System.Drawing.Size(709, 494);
+ this.Controls.Add(this.checkBoxAutoAdjustTimings);
this.Controls.Add(this.labelElapsed);
this.Controls.Add(this.labelCpp);
this.Controls.Add(this.checkBoxTranslateToEnglish);
@@ -485,5 +498,6 @@
private System.Windows.Forms.ToolStripMenuItem whisperCppCToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
private System.Windows.Forms.ToolStripMenuItem removeTemporaryFilesToolStripMenuItem;
+ private System.Windows.Forms.CheckBox checkBoxAutoAdjustTimings;
}
}
\ No newline at end of file
diff --git a/src/ui/Forms/AudioToText/WhisperAudioToText.cs b/src/ui/Forms/AudioToText/WhisperAudioToText.cs
index d1b39f6b2..b8e4b0e6a 100644
--- a/src/ui/Forms/AudioToText/WhisperAudioToText.cs
+++ b/src/ui/Forms/AudioToText/WhisperAudioToText.cs
@@ -56,6 +56,7 @@ namespace Nikse.SubtitleEdit.Forms.AudioToText
linkLabelOpenModelsFolder.Text = LanguageSettings.Current.AudioToText.OpenModelsFolder;
checkBoxTranslateToEnglish.Text = LanguageSettings.Current.AudioToText.TranslateToEnglish;
checkBoxUsePostProcessing.Text = LanguageSettings.Current.AudioToText.UsePostProcessing;
+ checkBoxAutoAdjustTimings.Text = LanguageSettings.Current.AudioToText.AutoAdjustTimings;
buttonGenerate.Text = LanguageSettings.Current.Watermark.Generate;
buttonCancel.Text = LanguageSettings.Current.General.Cancel;
buttonBatchMode.Text = LanguageSettings.Current.AudioToText.BatchMode;
@@ -69,6 +70,7 @@ namespace Nikse.SubtitleEdit.Forms.AudioToText
columnHeaderFileName.Text = LanguageSettings.Current.JoinSubtitles.FileName;
checkBoxUsePostProcessing.Checked = Configuration.Settings.Tools.VoskPostProcessing;
+ checkBoxAutoAdjustTimings.Checked = Configuration.Settings.Tools.WhisperAutoAdjustTimings;
_filesToDelete = new List();
@@ -193,7 +195,20 @@ namespace Nikse.SubtitleEdit.Forms.AudioToText
{
ParagraphMaxChars = Configuration.Settings.General.SubtitleLineMaximumLength * 2,
};
- TranscribedSubtitle = postProcessor.Generate(AudioToTextPostProcessor.Engine.Whisper, transcript, checkBoxUsePostProcessing.Checked, true, true, true, true, true);
+
+ WavePeakData wavePeaks = null;
+ if (checkBoxAutoAdjustTimings.Checked)
+ {
+ using (var waveFile = new WavePeakGenerator(waveFileName))
+ {
+ var wavePeakFileName = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".wav");
+ waveFile.GeneratePeaks(0, wavePeakFileName);
+ wavePeaks = WavePeakData.FromDisk(wavePeakFileName);
+ _filesToDelete.Add(wavePeakFileName);
+ }
+ }
+
+ TranscribedSubtitle = postProcessor.Generate(AudioToTextPostProcessor.Engine.Whisper, transcript, checkBoxUsePostProcessing.Checked, true, true, true, true, true, checkBoxAutoAdjustTimings.Checked, wavePeaks);
if (transcript == null || transcript.Count == 0)
{
@@ -264,11 +279,23 @@ namespace Nikse.SubtitleEdit.Forms.AudioToText
return;
}
+ WavePeakData wavePeaks = null;
+ if (checkBoxAutoAdjustTimings.Checked)
+ {
+ using (var waveFile = new WavePeakGenerator(waveFileName))
+ {
+ var wavePeakFileName = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".wav");
+ waveFile.GeneratePeaks(0, wavePeakFileName);
+ wavePeaks = WavePeakData.FromDisk(wavePeakFileName);
+ _filesToDelete.Add(wavePeakFileName);
+ }
+ }
+
var postProcessor = new AudioToTextPostProcessor(_languageCode)
{
ParagraphMaxChars = Configuration.Settings.General.SubtitleLineMaximumLength * 2,
};
- TranscribedSubtitle = postProcessor.Generate(AudioToTextPostProcessor.Engine.Whisper, transcript, checkBoxUsePostProcessing.Checked, true, true, true, true, true);
+ TranscribedSubtitle = postProcessor.Generate(AudioToTextPostProcessor.Engine.Whisper, transcript, checkBoxUsePostProcessing.Checked, true, true, true, true, true, checkBoxAutoAdjustTimings.Checked, wavePeaks);
SaveToSourceFolder(videoFileName);
TaskbarList.SetProgressValue(_parentForm.Handle, _batchFileNumber, listViewInputFiles.Items.Count);
@@ -670,7 +697,7 @@ namespace Nikse.SubtitleEdit.Forms.AudioToText
}
translateToEnglish = $"--max-len {maxChars} ";
- translateToEnglish = string.Empty; //TODO: remove line when "--max-len" is working!
+ //translateToEnglish = string.Empty; //TODO: remove line when "--max-len" is working!
}
var outputSrt = string.Empty;
@@ -744,6 +771,7 @@ namespace Nikse.SubtitleEdit.Forms.AudioToText
}
Configuration.Settings.Tools.VoskPostProcessing = checkBoxUsePostProcessing.Checked;
+ Configuration.Settings.Tools.WhisperAutoAdjustTimings = checkBoxAutoAdjustTimings.Checked;
DeleteTemporaryFiles(_filesToDelete);
}
@@ -912,7 +940,7 @@ namespace Nikse.SubtitleEdit.Forms.AudioToText
if (_batchMode)
{
groupBoxInputFiles.Enabled = true;
- Height = checkBoxUsePostProcessing.Bottom + progressBar1.Height + buttonCancel.Height + 450;
+ Height = checkBoxAutoAdjustTimings.Bottom + progressBar1.Height + buttonCancel.Height + 450;
listViewInputFiles.Visible = true;
buttonBatchMode.Text = LanguageSettings.Current.Split.Basic;
MinimumSize = new Size(MinimumSize.Width, Height - 75);
@@ -923,7 +951,7 @@ namespace Nikse.SubtitleEdit.Forms.AudioToText
else
{
groupBoxInputFiles.Enabled = false;
- var h = checkBoxUsePostProcessing.Bottom + progressBar1.Height + buttonCancel.Height + 70;
+ var h = checkBoxAutoAdjustTimings.Bottom + progressBar1.Height + buttonCancel.Height + 70;
MinimumSize = new Size(MinimumSize.Width, h - 10);
Height = h;
Width = _initialWidth;
@@ -1067,5 +1095,10 @@ namespace Nikse.SubtitleEdit.Forms.AudioToText
Configuration.Settings.Tools.WhisperDeleteTempFiles = !Configuration.Settings.Tools.WhisperDeleteTempFiles;
removeTemporaryFilesToolStripMenuItem.Checked = Configuration.Settings.Tools.WhisperDeleteTempFiles;
}
+
+ private void checkBoxUsePostProcessing_CheckedChanged(object sender, EventArgs e)
+ {
+ checkBoxAutoAdjustTimings.Enabled = checkBoxUsePostProcessing.Checked;
+ }
}
}
diff --git a/src/ui/Forms/AudioToText/WhisperAudioToTextSelectedLines.cs b/src/ui/Forms/AudioToText/WhisperAudioToTextSelectedLines.cs
index 7dd42b3f5..0d34ddaa4 100644
--- a/src/ui/Forms/AudioToText/WhisperAudioToTextSelectedLines.cs
+++ b/src/ui/Forms/AudioToText/WhisperAudioToTextSelectedLines.cs
@@ -149,7 +149,7 @@ namespace Nikse.SubtitleEdit.Forms.AudioToText
return;
}
- TranscribedSubtitle = postProcessor.Generate(AudioToTextPostProcessor.Engine.Whisper, transcript, checkBoxUsePostProcessing.Checked, true, true, true, true, false);
+ TranscribedSubtitle = postProcessor.Generate(AudioToTextPostProcessor.Engine.Whisper, transcript, checkBoxUsePostProcessing.Checked, true, true, true, true, false, false, null);
SaveToAudioClip(_batchFileNumber - 1);
TaskbarList.SetProgressValue(_parentForm.Handle, _batchFileNumber, listViewInputFiles.Items.Count);
diff --git a/src/ui/Forms/Main.cs b/src/ui/Forms/Main.cs
index 4169d2ed1..860eac9ee 100644
--- a/src/ui/Forms/Main.cs
+++ b/src/ui/Forms/Main.cs
@@ -18702,94 +18702,219 @@ namespace Nikse.SubtitleEdit.Forms
return;
}
- var silenceLengthInSeconds = 0.08;
- var lowPercent = audioVisualizer.FindLowPercentage(p.StartTime.TotalSeconds - 0.3, p.StartTime.TotalSeconds + 0.1);
- var highPercent = audioVisualizer.FindHighPercentage(p.StartTime.TotalSeconds - 0.3, p.StartTime.TotalSeconds + 0.4);
- var add = 5.0;
- if (highPercent > 40)
- {
- add = 8;
- }
- else if (highPercent < 5)
- {
- add = highPercent - lowPercent - 0.3;
- }
+ _subtitle = WhisperTimingFixer.ShortenViaWavePeaks(_subtitle, audioVisualizer.WavePeaks);
- for (var startVolume = lowPercent + add; startVolume < 14; startVolume += 0.3)
+ SaveSubtitleListviewIndices();
+ SubtitleListview1.Fill(_subtitle, _subtitleOriginal);
+ RestoreSubtitleListviewIndices();
+ RefreshSelectedParagraph();
+ return;
+
+ var pctCheck = 10;
+
+ // Find nearest silence
+ var startPos = p.StartTime.TotalSeconds;
+ var lowPercentx = audioVisualizer.FindLowPercentage(startPos - 0.05, startPos + 0.05);
+ var highPercentx = audioVisualizer.FindHighPercentage(startPos - 0.05, startPos + 0.05);
+ var pctHere = lowPercentx + highPercentx / 2;
+ if (pctHere > pctCheck)
{
- var pos = audioVisualizer.FindDataBelowThresholdBackForStart(startVolume, silenceLengthInSeconds, p.StartTime.TotalSeconds);
- var pos2 = audioVisualizer.FindDataBelowThresholdBackForStart(startVolume + 0.3, silenceLengthInSeconds, p.StartTime.TotalSeconds);
- if (pos >= 0 && pos > p.StartTime.TotalSeconds - 1)
+ var startPosBack = startPos ;
+ var startPosForward = startPosBack;
+ for (var ms = 50; ms < 250; ms += 50)
{
- if (pos2 > pos && pos2 >= 0 && pos2 > p.StartTime.TotalSeconds - 1)
+ var lowPercentBack = audioVisualizer.FindLowPercentage(startPosBack - 0.05, startPosBack + 0.05);
+ var highPercentBack = audioVisualizer.FindHighPercentage(startPosBack - 0.05, startPosBack + 0.05);
+ var pct = lowPercentBack + highPercentBack / 2;
+ if (pct < pctCheck)
{
- pos = pos2;
- }
-
- var newStartTimeMs = pos * TimeCode.BaseUnit;
- var prev = _subtitle.GetParagraphOrDefault(index - 1);
- if (prev != null && prev.EndTime.TotalMilliseconds + MinGapBetweenLines >= newStartTimeMs)
- {
- newStartTimeMs = prev.EndTime.TotalMilliseconds + MinGapBetweenLines;
- if (newStartTimeMs >= p.StartTime.TotalMilliseconds)
+ startPosBack -= 0.025;
+ var lowPercentBack2 = audioVisualizer.FindLowPercentage(startPosBack - 0.05, startPosBack + 0.05);
+ var highPercentBack2 = audioVisualizer.FindHighPercentage(startPosBack - 0.05, startPosBack + 0.05);
+ var pct2 = lowPercentBack2 + highPercentBack2 / 2;
+ if (pct2 < pct)
{
- break; // cannot move start time
+ p.StartTime.TotalSeconds = startPosBack + 0.05;
}
- }
-
- // check for shot changes
- if (audioVisualizer.ShotChanges != null)
- {
- var matchingShotChanges = audioVisualizer.ShotChanges
- .Where(sc => sc > p.StartTime.TotalSeconds - 0.3 && sc < p.StartTime.TotalSeconds + 0.2)
- .OrderBy(sc => Math.Abs(sc - p.StartTime.TotalSeconds));
- if (matchingShotChanges.Any())
+ else
{
- newStartTimeMs = matchingShotChanges.First() * TimeCode.BaseUnit;
+ p.StartTime.TotalSeconds = startPosBack + 0.025 + + 0.05;
}
+
+ break;
}
- if (Math.Abs(p.StartTime.TotalMilliseconds - newStartTimeMs) < 10)
- {
- break; // diff too small
- }
+ startPosBack -= 0.05;
- var newEndTimeMs = p.EndTime.TotalMilliseconds;
- if (newStartTimeMs > p.StartTime.TotalMilliseconds)
+
+
+ var lowPercentForward = audioVisualizer.FindLowPercentage(startPosForward - 0.05, startPosForward + 0.05);
+ var highPercentForward = audioVisualizer.FindHighPercentage(startPosForward - 0.05, startPosForward + 0.05);
+ var pctF = lowPercentForward + highPercentForward / 2;
+ if (pctF < pctCheck)
{
- var temp = new Paragraph(p);
- temp.StartTime.TotalMilliseconds = newStartTimeMs;
- if (temp.Duration.TotalMilliseconds < Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds ||
- Utilities.GetCharactersPerSecond(temp) > Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds)
+ startPosForward -= 0.025;
+ var lowPercentForward2 = audioVisualizer.FindLowPercentage(startPosForward - 0.05, startPosForward + 0.05);
+ var highPercentForward2 = audioVisualizer.FindHighPercentage(startPosForward - 0.05, startPosForward + 0.05);
+ var pct2 = lowPercentForward2 + highPercentForward2 / 2;
+ if (pct2 < pctF)
{
- var next = _subtitle.GetParagraphOrDefault(index + 1);
- if (next == null ||
- next.StartTime.TotalMilliseconds > newStartTimeMs + p.Duration.TotalMilliseconds + MinGapBetweenLines)
- {
- newEndTimeMs = newStartTimeMs + p.Duration.TotalMilliseconds;
- }
+ p.StartTime.TotalSeconds = startPosForward + 0.05;
}
- }
-
- MakeHistoryForUndo(string.Format(LanguageSettings.Current.Main.BeforeX, LanguageSettings.Current.Settings.WaveformGuessStart));
-
- if (IsOriginalEditable)
- {
- var original = Utilities.GetOriginalParagraph(index, p, _subtitleOriginal.Paragraphs);
- if (original != null)
+ else
{
- original.StartTime.TotalMilliseconds = newStartTimeMs;
- original.EndTime.TotalMilliseconds = newEndTimeMs;
+ p.StartTime.TotalSeconds = startPosForward + 0.025 + +0.05;
}
+
+ break;
}
- p.StartTime.TotalMilliseconds = newStartTimeMs;
- p.EndTime.TotalMilliseconds = newEndTimeMs;
- RefreshSelectedParagraph();
- SubtitleListview1.SetStartTimeAndDuration(index, p, _subtitle.GetParagraphOrDefault(index + 1), _subtitle.GetParagraphOrDefault(index - 1));
- break;
+ startPosForward += 0.05;
}
}
+
+
+ startPos = p.StartTime.TotalSeconds;
+ lowPercentx = audioVisualizer.FindLowPercentage(startPos - 0.05, startPos + 0.05);
+ highPercentx = audioVisualizer.FindHighPercentage(startPos - 0.05, startPos + 0.05);
+ pctHere = lowPercentx + highPercentx / 2;
+ if (pctHere < pctCheck)
+ {
+ var startPosForward = p.StartTime.TotalSeconds;
+ while (pctHere < pctCheck && startPos < p.EndTime.TotalSeconds - 1)
+ {
+ var lowPercentForward = audioVisualizer.FindLowPercentage(startPosForward - 0.05, startPosForward + 0.05);
+ var highPercentForward = audioVisualizer.FindHighPercentage(startPosForward - 0.05, startPosForward + 0.05);
+ pctHere = lowPercentForward + highPercentForward / 2;
+
+ p.StartTime.TotalSeconds = startPosForward;
+
+ if (pctHere >= pctCheck)
+ {
+ startPosForward -= 0.025;
+ var lowPercentForward2 = audioVisualizer.FindLowPercentage(startPosForward - 0.05, startPosForward + 0.05);
+ var highPercentForward2 = audioVisualizer.FindHighPercentage(startPosForward - 0.05, startPosForward + 0.05);
+ var pct2 = lowPercentForward2 + highPercentForward2 / 2;
+ if (pct2 < pctHere)
+ {
+ p.StartTime.TotalSeconds -= 0.025;
+
+ pctHere = pct2;
+ startPosForward -= 0.025;
+ lowPercentForward2 = audioVisualizer.FindLowPercentage(startPosForward - 0.05, startPosForward + 0.05);
+ highPercentForward2 = audioVisualizer.FindHighPercentage(startPosForward - 0.05, startPosForward + 0.05);
+ pct2 = lowPercentForward2 + highPercentForward2 / 2;
+ if (pct2 < pctHere)
+ {
+ p.StartTime.TotalSeconds -= 0.025;
+ }
+ }
+
+ break;
+ }
+
+ startPosForward += 0.05;
+ }
+ }
+
+
+ RefreshSelectedParagraph();
+ SubtitleListview1.SetStartTimeAndDuration(index, p, _subtitle.GetParagraphOrDefault(index + 1), _subtitle.GetParagraphOrDefault(index - 1));
+
+ //var p = _subtitle.GetParagraphOrDefault(index);
+ //if (p == null)
+ //{
+ // return;
+ //}
+
+ //var silenceLengthInSeconds = 0.08;
+ //var lowPercent = audioVisualizer.FindLowPercentage(p.StartTime.TotalSeconds - 0.3, p.StartTime.TotalSeconds + 0.1);
+ //var highPercent = audioVisualizer.FindHighPercentage(p.StartTime.TotalSeconds - 0.3, p.StartTime.TotalSeconds + 0.4);
+ //var add = 5.0;
+ //if (highPercent > 40)
+ //{
+ // add = 8;
+ //}
+ //else if (highPercent < 5)
+ //{
+ // add = highPercent - lowPercent - 0.3;
+ //}
+
+ //for (var startVolume = lowPercent + add; startVolume < 14; startVolume += 0.3)
+ //{
+ // var pos = audioVisualizer.FindDataBelowThresholdBackForStart(startVolume, silenceLengthInSeconds, p.StartTime.TotalSeconds);
+ // var pos2 = audioVisualizer.FindDataBelowThresholdBackForStart(startVolume + 0.3, silenceLengthInSeconds, p.StartTime.TotalSeconds);
+ // if (pos >= 0 && pos > p.StartTime.TotalSeconds - 1)
+ // {
+ // if (pos2 > pos && pos2 >= 0 && pos2 > p.StartTime.TotalSeconds - 1)
+ // {
+ // pos = pos2;
+ // }
+
+ // var newStartTimeMs = pos * TimeCode.BaseUnit;
+ // var prev = _subtitle.GetParagraphOrDefault(index - 1);
+ // if (prev != null && prev.EndTime.TotalMilliseconds + MinGapBetweenLines >= newStartTimeMs)
+ // {
+ // newStartTimeMs = prev.EndTime.TotalMilliseconds + MinGapBetweenLines;
+ // if (newStartTimeMs >= p.StartTime.TotalMilliseconds)
+ // {
+ // break; // cannot move start time
+ // }
+ // }
+
+ // // check for shot changes
+ // if (audioVisualizer.ShotChanges != null)
+ // {
+ // var matchingShotChanges = audioVisualizer.ShotChanges
+ // .Where(sc => sc > p.StartTime.TotalSeconds - 0.3 && sc < p.StartTime.TotalSeconds + 0.2)
+ // .OrderBy(sc => Math.Abs(sc - p.StartTime.TotalSeconds));
+ // if (matchingShotChanges.Any())
+ // {
+ // newStartTimeMs = matchingShotChanges.First() * TimeCode.BaseUnit;
+ // }
+ // }
+
+ // if (Math.Abs(p.StartTime.TotalMilliseconds - newStartTimeMs) < 10)
+ // {
+ // break; // diff too small
+ // }
+
+ // var newEndTimeMs = p.EndTime.TotalMilliseconds;
+ // if (newStartTimeMs > p.StartTime.TotalMilliseconds)
+ // {
+ // var temp = new Paragraph(p);
+ // temp.StartTime.TotalMilliseconds = newStartTimeMs;
+ // if (temp.Duration.TotalMilliseconds < Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds ||
+ // Utilities.GetCharactersPerSecond(temp) > Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds)
+ // {
+ // var next = _subtitle.GetParagraphOrDefault(index + 1);
+ // if (next == null ||
+ // next.StartTime.TotalMilliseconds > newStartTimeMs + p.Duration.TotalMilliseconds + MinGapBetweenLines)
+ // {
+ // newEndTimeMs = newStartTimeMs + p.Duration.TotalMilliseconds;
+ // }
+ // }
+ // }
+
+ // MakeHistoryForUndo(string.Format(LanguageSettings.Current.Main.BeforeX, LanguageSettings.Current.Settings.WaveformGuessStart));
+
+ // if (IsOriginalEditable)
+ // {
+ // var original = Utilities.GetOriginalParagraph(index, p, _subtitleOriginal.Paragraphs);
+ // if (original != null)
+ // {
+ // original.StartTime.TotalMilliseconds = newStartTimeMs;
+ // original.EndTime.TotalMilliseconds = newEndTimeMs;
+ // }
+ // }
+
+ // p.StartTime.TotalMilliseconds = newStartTimeMs;
+ // p.EndTime.TotalMilliseconds = newEndTimeMs;
+ // RefreshSelectedParagraph();
+ // SubtitleListview1.SetStartTimeAndDuration(index, p, _subtitle.GetParagraphOrDefault(index + 1), _subtitle.GetParagraphOrDefault(index - 1));
+ // break;
+ // }
+ //}
}
private void GoToBookmark()
diff --git a/src/ui/Logic/Language.cs b/src/ui/Logic/Language.cs
index 18d25a28e..c6088aa4d 100644
--- a/src/ui/Logic/Language.cs
+++ b/src/ui/Logic/Language.cs
@@ -337,6 +337,7 @@ namespace Nikse.SubtitleEdit.Logic
Transcribing = "Transcribing audio to text...",
TranscribingXOfY = "Transcribing audio to text - file {0} of {1}...",
UsePostProcessing = "Use post-processing (line merge, fix casing, punctuation, and more)",
+ AutoAdjustTimings = "Auto adjust timings",
BatchMode = "Batch mode",
XFilesSavedToVideoSourceFolder = "{0} files saved to video source folder",
KeepPartialTranscription = "Keep partial transcription",
diff --git a/src/ui/Logic/LanguageDeserializer.cs b/src/ui/Logic/LanguageDeserializer.cs
index 32fd8028d..66de5fe30 100644
--- a/src/ui/Logic/LanguageDeserializer.cs
+++ b/src/ui/Logic/LanguageDeserializer.cs
@@ -517,6 +517,9 @@ namespace Nikse.SubtitleEdit.Logic
case "AudioToText/UsePostProcessing":
language.AudioToText.UsePostProcessing = reader.Value;
break;
+ case "AudioToText/AutoAdjustTimings":
+ language.AudioToText.AutoAdjustTimings = reader.Value;
+ break;
case "AudioToText/BatchMode":
language.AudioToText.BatchMode = reader.Value;
break;
diff --git a/src/ui/Logic/LanguageStructure.cs b/src/ui/Logic/LanguageStructure.cs
index 305a7ccef..854c049af 100644
--- a/src/ui/Logic/LanguageStructure.cs
+++ b/src/ui/Logic/LanguageStructure.cs
@@ -196,6 +196,7 @@ namespace Nikse.SubtitleEdit.Logic
public string TranscribingXOfY { get; set; }
public string XFilesSavedToVideoSourceFolder { get; set; }
public string UsePostProcessing { get; set; }
+ public string AutoAdjustTimings { get; set; }
public string BatchMode { get; set; }
public string KeepPartialTranscription { get; set; }
public string TranslateToEnglish { get; set; }