mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-22 11:12:36 +01:00
Testing tts
This commit is contained in:
parent
a4db942d37
commit
3ab1074e71
@ -19027,7 +19027,7 @@ namespace Nikse.SubtitleEdit.Forms
|
|||||||
}
|
}
|
||||||
else if (e.Modifiers == (Keys.Alt | Keys.Shift | Keys.Control) && e.KeyCode == Keys.T)
|
else if (e.Modifiers == (Keys.Alt | Keys.Shift | Keys.Control) && e.KeyCode == Keys.T)
|
||||||
{
|
{
|
||||||
using (var form = new TextToSpeech(_subtitle, _videoFileName))
|
using (var form = new TextToSpeech(_subtitle, _videoFileName, _videoInfo))
|
||||||
{
|
{
|
||||||
if (form.ShowDialog(this) != DialogResult.OK)
|
if (form.ShowDialog(this) != DialogResult.OK)
|
||||||
{
|
{
|
||||||
|
177
src/ui/Forms/TextToSpeech.Designer.cs
generated
177
src/ui/Forms/TextToSpeech.Designer.cs
generated
@ -29,9 +29,15 @@
|
|||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
this.buttonOK = new System.Windows.Forms.Button();
|
this.buttonOK = new System.Windows.Forms.Button();
|
||||||
this.labelDescription = new System.Windows.Forms.Label();
|
this.labelProgress = new System.Windows.Forms.Label();
|
||||||
this.button1 = new System.Windows.Forms.Button();
|
this.buttonGenerateTTS = new System.Windows.Forms.Button();
|
||||||
this.textBox1 = new Nikse.SubtitleEdit.Controls.NikseTextBox();
|
this.progressBar1 = new System.Windows.Forms.ProgressBar();
|
||||||
|
this.labelEngine = new System.Windows.Forms.Label();
|
||||||
|
this.groupBoxMsSettings = new System.Windows.Forms.GroupBox();
|
||||||
|
this.labelMsVoice = new System.Windows.Forms.Label();
|
||||||
|
this.nikseComboBoxVoice = new Nikse.SubtitleEdit.Controls.NikseComboBox();
|
||||||
|
this.nikseComboBoxEngine = new Nikse.SubtitleEdit.Controls.NikseComboBox();
|
||||||
|
this.groupBoxMsSettings.SuspendLayout();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// buttonOK
|
// buttonOK
|
||||||
@ -46,50 +52,144 @@
|
|||||||
this.buttonOK.UseVisualStyleBackColor = true;
|
this.buttonOK.UseVisualStyleBackColor = true;
|
||||||
this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
|
this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
|
||||||
//
|
//
|
||||||
// labelDescription
|
// labelProgress
|
||||||
//
|
//
|
||||||
this.labelDescription.AutoSize = true;
|
this.labelProgress.AutoSize = true;
|
||||||
this.labelDescription.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
this.labelProgress.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.labelDescription.Location = new System.Drawing.Point(9, 33);
|
this.labelProgress.Location = new System.Drawing.Point(12, 384);
|
||||||
this.labelDescription.Name = "labelDescription";
|
this.labelProgress.Name = "labelProgress";
|
||||||
this.labelDescription.Size = new System.Drawing.Size(76, 13);
|
this.labelProgress.Size = new System.Drawing.Size(70, 13);
|
||||||
this.labelDescription.TabIndex = 9;
|
this.labelProgress.TabIndex = 9;
|
||||||
this.labelDescription.Text = "Name of voice";
|
this.labelProgress.Text = "labelProgress";
|
||||||
//
|
//
|
||||||
// button1
|
// buttonGenerateTTS
|
||||||
//
|
//
|
||||||
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
this.buttonGenerateTTS.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.button1.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
this.buttonGenerateTTS.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.button1.Location = new System.Drawing.Point(12, 75);
|
this.buttonGenerateTTS.Location = new System.Drawing.Point(571, 374);
|
||||||
this.button1.Name = "button1";
|
this.buttonGenerateTTS.Name = "buttonGenerateTTS";
|
||||||
this.button1.Size = new System.Drawing.Size(75, 23);
|
this.buttonGenerateTTS.Size = new System.Drawing.Size(228, 23);
|
||||||
this.button1.TabIndex = 11;
|
this.buttonGenerateTTS.TabIndex = 11;
|
||||||
this.button1.Text = "Go";
|
this.buttonGenerateTTS.Text = "Generate speech from text";
|
||||||
this.button1.UseVisualStyleBackColor = true;
|
this.buttonGenerateTTS.UseVisualStyleBackColor = true;
|
||||||
this.button1.Click += new System.EventHandler(this.button1_Click);
|
this.buttonGenerateTTS.Click += new System.EventHandler(this.ButtonGenerateTtsClick);
|
||||||
//
|
//
|
||||||
// textBox1
|
// progressBar1
|
||||||
//
|
//
|
||||||
this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.textBox1.FocusedColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(120)))), ((int)(((byte)(215)))));
|
this.progressBar1.Location = new System.Drawing.Point(12, 407);
|
||||||
this.textBox1.Location = new System.Drawing.Point(12, 49);
|
this.progressBar1.Name = "progressBar1";
|
||||||
this.textBox1.Name = "textBox1";
|
this.progressBar1.Size = new System.Drawing.Size(706, 23);
|
||||||
this.textBox1.Size = new System.Drawing.Size(229, 20);
|
this.progressBar1.TabIndex = 12;
|
||||||
this.textBox1.TabIndex = 10;
|
//
|
||||||
this.textBox1.Text = "Hello, how are you?";
|
// labelEngine
|
||||||
|
//
|
||||||
|
this.labelEngine.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.labelEngine.AutoSize = true;
|
||||||
|
this.labelEngine.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
|
this.labelEngine.Location = new System.Drawing.Point(405, 12);
|
||||||
|
this.labelEngine.Name = "labelEngine";
|
||||||
|
this.labelEngine.Size = new System.Drawing.Size(40, 13);
|
||||||
|
this.labelEngine.TabIndex = 14;
|
||||||
|
this.labelEngine.Text = "Engine";
|
||||||
|
//
|
||||||
|
// groupBoxMsSettings
|
||||||
|
//
|
||||||
|
this.groupBoxMsSettings.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.groupBoxMsSettings.Controls.Add(this.labelMsVoice);
|
||||||
|
this.groupBoxMsSettings.Controls.Add(this.nikseComboBoxVoice);
|
||||||
|
this.groupBoxMsSettings.Location = new System.Drawing.Point(408, 57);
|
||||||
|
this.groupBoxMsSettings.Name = "groupBoxMsSettings";
|
||||||
|
this.groupBoxMsSettings.Size = new System.Drawing.Size(391, 311);
|
||||||
|
this.groupBoxMsSettings.TabIndex = 15;
|
||||||
|
this.groupBoxMsSettings.TabStop = false;
|
||||||
|
this.groupBoxMsSettings.Text = "Settings";
|
||||||
|
//
|
||||||
|
// labelMsVoice
|
||||||
|
//
|
||||||
|
this.labelMsVoice.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.labelMsVoice.AutoSize = true;
|
||||||
|
this.labelMsVoice.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
|
this.labelMsVoice.Location = new System.Drawing.Point(14, 25);
|
||||||
|
this.labelMsVoice.Name = "labelMsVoice";
|
||||||
|
this.labelMsVoice.Size = new System.Drawing.Size(34, 13);
|
||||||
|
this.labelMsVoice.TabIndex = 16;
|
||||||
|
this.labelMsVoice.Text = "Voice";
|
||||||
|
//
|
||||||
|
// nikseComboBoxVoice
|
||||||
|
//
|
||||||
|
this.nikseComboBoxVoice.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.nikseComboBoxVoice.BackColor = System.Drawing.SystemColors.Window;
|
||||||
|
this.nikseComboBoxVoice.BackColorDisabled = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
|
||||||
|
this.nikseComboBoxVoice.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(171)))), ((int)(((byte)(173)))), ((int)(((byte)(179)))));
|
||||||
|
this.nikseComboBoxVoice.BorderColorDisabled = System.Drawing.Color.FromArgb(((int)(((byte)(120)))), ((int)(((byte)(120)))), ((int)(((byte)(120)))));
|
||||||
|
this.nikseComboBoxVoice.ButtonForeColor = System.Drawing.SystemColors.ControlText;
|
||||||
|
this.nikseComboBoxVoice.ButtonForeColorDown = System.Drawing.Color.Orange;
|
||||||
|
this.nikseComboBoxVoice.ButtonForeColorOver = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(120)))), ((int)(((byte)(215)))));
|
||||||
|
this.nikseComboBoxVoice.DropDownHeight = 400;
|
||||||
|
this.nikseComboBoxVoice.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||||
|
this.nikseComboBoxVoice.DropDownWidth = 195;
|
||||||
|
this.nikseComboBoxVoice.FormattingEnabled = false;
|
||||||
|
this.nikseComboBoxVoice.Location = new System.Drawing.Point(17, 41);
|
||||||
|
this.nikseComboBoxVoice.MaxLength = 32767;
|
||||||
|
this.nikseComboBoxVoice.Name = "nikseComboBoxVoice";
|
||||||
|
this.nikseComboBoxVoice.SelectedIndex = -1;
|
||||||
|
this.nikseComboBoxVoice.SelectedItem = null;
|
||||||
|
this.nikseComboBoxVoice.SelectedText = "";
|
||||||
|
this.nikseComboBoxVoice.Size = new System.Drawing.Size(351, 23);
|
||||||
|
this.nikseComboBoxVoice.TabIndex = 15;
|
||||||
|
this.nikseComboBoxVoice.UsePopupWindow = false;
|
||||||
|
//
|
||||||
|
// nikseComboBoxEngine
|
||||||
|
//
|
||||||
|
this.nikseComboBoxEngine.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.nikseComboBoxEngine.BackColor = System.Drawing.SystemColors.Window;
|
||||||
|
this.nikseComboBoxEngine.BackColorDisabled = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
|
||||||
|
this.nikseComboBoxEngine.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(171)))), ((int)(((byte)(173)))), ((int)(((byte)(179)))));
|
||||||
|
this.nikseComboBoxEngine.BorderColorDisabled = System.Drawing.Color.FromArgb(((int)(((byte)(120)))), ((int)(((byte)(120)))), ((int)(((byte)(120)))));
|
||||||
|
this.nikseComboBoxEngine.ButtonForeColor = System.Drawing.SystemColors.ControlText;
|
||||||
|
this.nikseComboBoxEngine.ButtonForeColorDown = System.Drawing.Color.Orange;
|
||||||
|
this.nikseComboBoxEngine.ButtonForeColorOver = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(120)))), ((int)(((byte)(215)))));
|
||||||
|
this.nikseComboBoxEngine.DropDownHeight = 400;
|
||||||
|
this.nikseComboBoxEngine.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDown;
|
||||||
|
this.nikseComboBoxEngine.DropDownWidth = 195;
|
||||||
|
this.nikseComboBoxEngine.FormattingEnabled = false;
|
||||||
|
this.nikseComboBoxEngine.Location = new System.Drawing.Point(408, 28);
|
||||||
|
this.nikseComboBoxEngine.MaxLength = 32767;
|
||||||
|
this.nikseComboBoxEngine.Name = "nikseComboBoxEngine";
|
||||||
|
this.nikseComboBoxEngine.SelectedIndex = -1;
|
||||||
|
this.nikseComboBoxEngine.SelectedItem = null;
|
||||||
|
this.nikseComboBoxEngine.SelectedText = "";
|
||||||
|
this.nikseComboBoxEngine.Size = new System.Drawing.Size(391, 23);
|
||||||
|
this.nikseComboBoxEngine.TabIndex = 13;
|
||||||
|
this.nikseComboBoxEngine.TabStop = false;
|
||||||
|
this.nikseComboBoxEngine.Text = "nikseComboBox1";
|
||||||
|
this.nikseComboBoxEngine.UsePopupWindow = false;
|
||||||
|
this.nikseComboBoxEngine.SelectedIndexChanged += new System.EventHandler(this.nikseComboBoxEngine_SelectedIndexChanged);
|
||||||
//
|
//
|
||||||
// TextToSpeech
|
// TextToSpeech
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(811, 442);
|
this.ClientSize = new System.Drawing.Size(811, 442);
|
||||||
this.Controls.Add(this.button1);
|
this.Controls.Add(this.groupBoxMsSettings);
|
||||||
this.Controls.Add(this.textBox1);
|
this.Controls.Add(this.labelEngine);
|
||||||
this.Controls.Add(this.labelDescription);
|
this.Controls.Add(this.nikseComboBoxEngine);
|
||||||
|
this.Controls.Add(this.progressBar1);
|
||||||
|
this.Controls.Add(this.buttonGenerateTTS);
|
||||||
|
this.Controls.Add(this.labelProgress);
|
||||||
this.Controls.Add(this.buttonOK);
|
this.Controls.Add(this.buttonOK);
|
||||||
|
this.KeyPreview = true;
|
||||||
|
this.MinimumSize = new System.Drawing.Size(827, 481);
|
||||||
this.Name = "TextToSpeech";
|
this.Name = "TextToSpeech";
|
||||||
this.Text = "TextToSpeach";
|
this.ShowIcon = false;
|
||||||
|
this.ShowInTaskbar = false;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
this.Text = "Text to speach";
|
||||||
|
this.groupBoxMsSettings.ResumeLayout(false);
|
||||||
|
this.groupBoxMsSettings.PerformLayout();
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
this.PerformLayout();
|
this.PerformLayout();
|
||||||
|
|
||||||
@ -97,8 +197,13 @@
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
private System.Windows.Forms.Button buttonOK;
|
private System.Windows.Forms.Button buttonOK;
|
||||||
private Controls.NikseTextBox textBox1;
|
private System.Windows.Forms.Label labelProgress;
|
||||||
private System.Windows.Forms.Label labelDescription;
|
private System.Windows.Forms.Button buttonGenerateTTS;
|
||||||
private System.Windows.Forms.Button button1;
|
private System.Windows.Forms.ProgressBar progressBar1;
|
||||||
|
private Controls.NikseComboBox nikseComboBoxEngine;
|
||||||
|
private System.Windows.Forms.Label labelEngine;
|
||||||
|
private System.Windows.Forms.GroupBox groupBoxMsSettings;
|
||||||
|
private System.Windows.Forms.Label labelMsVoice;
|
||||||
|
private Controls.NikseComboBox nikseComboBoxVoice;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,10 @@
|
|||||||
using Nikse.SubtitleEdit.Logic;
|
using Nikse.SubtitleEdit.Core.Common;
|
||||||
|
using Nikse.SubtitleEdit.Logic;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Speech.Synthesis;
|
using System.Speech.Synthesis;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
@ -7,33 +12,322 @@ namespace Nikse.SubtitleEdit.Forms
|
|||||||
{
|
{
|
||||||
public partial class TextToSpeech : Form
|
public partial class TextToSpeech : Form
|
||||||
{
|
{
|
||||||
public TextToSpeech(Core.Common.Subtitle subtitle, string videoFileName)
|
private readonly Subtitle _subtitle;
|
||||||
|
private readonly string _videoFileName;
|
||||||
|
private readonly VideoInfo _videoInfo;
|
||||||
|
private string _waveFolder;
|
||||||
|
|
||||||
|
public TextToSpeech(Subtitle subtitle, string videoFileName, VideoInfo videoInfo)
|
||||||
{
|
{
|
||||||
UiUtil.PreInitialize(this);
|
UiUtil.PreInitialize(this);
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
UiUtil.FixFonts(this);
|
UiUtil.FixFonts(this);
|
||||||
|
|
||||||
|
_subtitle = subtitle;
|
||||||
|
_videoFileName = videoFileName;
|
||||||
|
_videoInfo = videoInfo;
|
||||||
|
|
||||||
buttonOK.Text = LanguageSettings.Current.General.Ok;
|
buttonOK.Text = LanguageSettings.Current.General.Ok;
|
||||||
UiUtil.FixLargeFonts(this, buttonOK);
|
UiUtil.FixLargeFonts(this, buttonOK);
|
||||||
|
|
||||||
|
progressBar1.Visible = false;
|
||||||
|
labelProgress.Text = string.Empty;
|
||||||
|
|
||||||
|
nikseComboBoxEngine.DropDownStyle = ComboBoxStyle.DropDownList;
|
||||||
|
nikseComboBoxEngine.Items.Clear();
|
||||||
|
nikseComboBoxEngine.Items.Add("Microsoft SpeechSynthesizer (fast/robotic)");
|
||||||
|
nikseComboBoxEngine.Items.Add("Tortoise TTS (very slow/very good)");
|
||||||
|
nikseComboBoxEngine.Items.Add("Mimic3");
|
||||||
|
nikseComboBoxEngine.SelectedIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void button1_Click(object sender, EventArgs e)
|
private void ButtonGenerateTtsClick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var text = textBox1.Text;
|
_waveFolder = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||||
|
Directory.CreateDirectory(_waveFolder);
|
||||||
|
|
||||||
using (SpeechSynthesizer synth = new SpeechSynthesizer())
|
if (nikseComboBoxEngine.SelectedIndex == 0)
|
||||||
{
|
{
|
||||||
synth.SetOutputToWaveFile(@"C:\data\Sample.wav");
|
GenerateParagraphAudioMs();
|
||||||
synth.SelectVoiceByHints(VoiceGender.Male, VoiceAge.Adult);
|
|
||||||
var builder = new PromptBuilder();
|
|
||||||
builder.AppendText(text);
|
|
||||||
synth.Speak(builder);
|
|
||||||
}
|
}
|
||||||
|
else if (nikseComboBoxEngine.SelectedIndex == 1)
|
||||||
|
{
|
||||||
|
GenerateParagraphAudioTortoiseTts();
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileNames = FixParagraphAudioSpeed();
|
||||||
|
|
||||||
|
// rename result file
|
||||||
|
var tempAudioFile = MergeAudioParagraphs(fileNames);
|
||||||
|
var resultAudioFileName = Path.Combine(Path.GetDirectoryName(tempAudioFile), Path.GetFileNameWithoutExtension(_videoFileName) + ".wav");
|
||||||
|
File.Move(tempAudioFile, resultAudioFileName);
|
||||||
|
|
||||||
|
Cleanup(_waveFolder, resultAudioFileName);
|
||||||
|
|
||||||
|
UiUtil.OpenFolder(_waveFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Cleanup(string waveFolder, string resultAudioFile)
|
||||||
|
{
|
||||||
|
foreach (var fileName in Directory.GetFiles(waveFolder, "*.wav"))
|
||||||
|
{
|
||||||
|
if (!fileName.Equals(resultAudioFile, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
File.Delete(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<string> FixParagraphAudioSpeed()
|
||||||
|
{
|
||||||
|
var fileNames = new List<string>(_subtitle.Paragraphs.Count);
|
||||||
|
|
||||||
|
labelProgress.Text = "Adjusting speed...";
|
||||||
|
labelProgress.Refresh();
|
||||||
|
Application.DoEvents();
|
||||||
|
|
||||||
|
progressBar1.Value = 0;
|
||||||
|
progressBar1.Maximum = _subtitle.Paragraphs.Count;
|
||||||
|
progressBar1.Visible = true;
|
||||||
|
for (var index = 0; index < _subtitle.Paragraphs.Count; index++)
|
||||||
|
{
|
||||||
|
progressBar1.Value = index + 1;
|
||||||
|
labelProgress.Text = $"Adjusting speed: {index + 1} / {_subtitle.Paragraphs.Count}...";
|
||||||
|
var p = _subtitle.Paragraphs[index];
|
||||||
|
var next = _subtitle.GetParagraphOrDefault(index + 1);
|
||||||
|
var pFileName = Path.Combine(_waveFolder, index + ".wav");
|
||||||
|
|
||||||
|
var addDuration = 0d;
|
||||||
|
if (next != null && p.EndTime.TotalMilliseconds < next.StartTime.TotalMilliseconds)
|
||||||
|
{
|
||||||
|
var diff = next.StartTime.TotalMilliseconds - p.EndTime.TotalMilliseconds;
|
||||||
|
addDuration = Math.Max(1000, diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputFileName1 = Path.Combine(_waveFolder, index + "_u.wav");
|
||||||
|
var trimProcess = VideoPreviewGenerator.TrimSilenceStartAndEnd(pFileName, outputFileName1);
|
||||||
|
trimProcess.Start();
|
||||||
|
trimProcess.WaitForExit();
|
||||||
|
|
||||||
|
var waveInfo = UiUtil.GetVideoInfo(outputFileName1);
|
||||||
|
if (waveInfo.TotalMilliseconds <= p.DurationTotalMilliseconds + addDuration)
|
||||||
|
{
|
||||||
|
fileNames.Add(outputFileName1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var factor = waveInfo.TotalMilliseconds / (p.DurationTotalMilliseconds + addDuration);
|
||||||
|
var outputFileName2 = Path.Combine(_waveFolder, index + "_t.wav");
|
||||||
|
fileNames.Add(outputFileName2);
|
||||||
|
var mergeProcess = VideoPreviewGenerator.ChangeSpeed(outputFileName1, outputFileName2, (float)factor);
|
||||||
|
mergeProcess.Start();
|
||||||
|
mergeProcess.WaitForExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string MergeAudioParagraphs(List<string> fileNames)
|
||||||
|
{
|
||||||
|
labelProgress.Text = "Merging audio track...";
|
||||||
|
labelProgress.Refresh();
|
||||||
|
Application.DoEvents();
|
||||||
|
var silenceFileName = Path.Combine(_waveFolder, "silence.wav");
|
||||||
|
var silenceProcess = VideoPreviewGenerator.GenerateEmptyAudio(silenceFileName, (float)_videoInfo.TotalSeconds);
|
||||||
|
silenceProcess.Start();
|
||||||
|
silenceProcess.WaitForExit();
|
||||||
|
|
||||||
|
progressBar1.Value = 0;
|
||||||
|
progressBar1.Maximum = _subtitle.Paragraphs.Count;
|
||||||
|
progressBar1.Visible = true;
|
||||||
|
var inputFileName = silenceFileName;
|
||||||
|
var outputFileName = string.Empty;
|
||||||
|
for (var index = 0; index < fileNames.Count; index++)
|
||||||
|
{
|
||||||
|
progressBar1.Value = index + 1;
|
||||||
|
labelProgress.Text = $"Merging audio track: {index + 1} / {_subtitle.Paragraphs.Count}...";
|
||||||
|
var p = _subtitle.Paragraphs[index];
|
||||||
|
var pFileName = fileNames[index];
|
||||||
|
outputFileName = Path.Combine(_waveFolder, $"silence{index}.wav");
|
||||||
|
var mergeProcess = VideoPreviewGenerator.MergeAudioTracks(inputFileName, pFileName, outputFileName, (float)p.StartTime.TotalSeconds);
|
||||||
|
inputFileName = outputFileName;
|
||||||
|
mergeProcess.Start();
|
||||||
|
mergeProcess.WaitForExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
progressBar1.Visible = false;
|
||||||
|
labelProgress.Text = string.Empty;
|
||||||
|
|
||||||
|
return outputFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateParagraphAudioMs()
|
||||||
|
{
|
||||||
|
progressBar1.Value = 0;
|
||||||
|
progressBar1.Maximum = _subtitle.Paragraphs.Count;
|
||||||
|
progressBar1.Visible = true;
|
||||||
|
|
||||||
|
using (var synthesizer = new SpeechSynthesizer())
|
||||||
|
{
|
||||||
|
VoiceInfo voiceInfo = null;
|
||||||
|
var vs = synthesizer.GetInstalledVoices().Where(p => p.Enabled).ToList();
|
||||||
|
for (var index = 0; index < vs.Count; index++)
|
||||||
|
{
|
||||||
|
var v = vs[index];
|
||||||
|
if (index == nikseComboBoxVoice.SelectedIndex)
|
||||||
|
{
|
||||||
|
synthesizer.SelectVoice(v.VoiceInfo.Name);
|
||||||
|
voiceInfo = v.VoiceInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var index = 0; index < _subtitle.Paragraphs.Count; index++)
|
||||||
|
{
|
||||||
|
progressBar1.Value = index + 1;
|
||||||
|
labelProgress.Text = $"Generating audio texts: {index + 1} / {_subtitle.Paragraphs.Count}...";
|
||||||
|
var p = _subtitle.Paragraphs[index];
|
||||||
|
synthesizer.SetOutputToWaveFile(Path.Combine(_waveFolder, index + ".wav"));
|
||||||
|
var builder = new PromptBuilder();
|
||||||
|
if (voiceInfo != null)
|
||||||
|
{
|
||||||
|
builder.StartVoice(voiceInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AppendText(p.Text);
|
||||||
|
if (voiceInfo != null)
|
||||||
|
{
|
||||||
|
builder.EndVoice();
|
||||||
|
}
|
||||||
|
|
||||||
|
synthesizer.Speak(builder);
|
||||||
|
|
||||||
|
progressBar1.Refresh();
|
||||||
|
labelProgress.Refresh();
|
||||||
|
Application.DoEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
progressBar1.Visible = false;
|
||||||
|
labelProgress.Text = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool GenerateParagraphAudioTortoiseTts()
|
||||||
|
{
|
||||||
|
var pythonFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
|
||||||
|
"AppData",
|
||||||
|
"Local",
|
||||||
|
"Programs",
|
||||||
|
"Python");
|
||||||
|
|
||||||
|
var pyFileName = "do_tts.py";
|
||||||
|
var voice = nikseComboBoxVoice.Text;
|
||||||
|
var files = Directory.EnumerateFiles(pythonFolder, pyFileName, SearchOption.AllDirectories).ToList();
|
||||||
|
if (files.Count == 0)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"{pyFileName} not found under {pythonFolder}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pythonFolderVersionFolder = files[0].Substring(pythonFolder.Length).Split(new char[] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
var pythonExe = Path.Combine(pythonFolder, pythonFolderVersionFolder[0], "python.exe");
|
||||||
|
if (!File.Exists(pythonExe))
|
||||||
|
{
|
||||||
|
pythonExe = "python.exe";
|
||||||
|
}
|
||||||
|
|
||||||
|
progressBar1.Value = 0;
|
||||||
|
progressBar1.Maximum = _subtitle.Paragraphs.Count;
|
||||||
|
progressBar1.Visible = true;
|
||||||
|
|
||||||
|
|
||||||
|
for (var index = 0; index < _subtitle.Paragraphs.Count; index++)
|
||||||
|
{
|
||||||
|
progressBar1.Value = index + 1;
|
||||||
|
labelProgress.Text = $"Generating audio texts: {index + 1} / {_subtitle.Paragraphs.Count}...";
|
||||||
|
var p = _subtitle.Paragraphs[index];
|
||||||
|
var outputFileName = Path.Combine(_waveFolder, index + ".wav");
|
||||||
|
|
||||||
|
var processTortoiseTts = new Process
|
||||||
|
{
|
||||||
|
StartInfo =
|
||||||
|
{
|
||||||
|
WorkingDirectory = Path.GetDirectoryName(files[0]),
|
||||||
|
FileName = pythonExe,
|
||||||
|
Arguments = $"do_tts.py --output_path \"{_waveFolder}\" --preset ultra_fast --voice {voice} --text \"{p.Text.RemoveChar('"')}\"",
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
processTortoiseTts.Start();
|
||||||
|
processTortoiseTts.WaitForExit();
|
||||||
|
|
||||||
|
var inputFile = Path.Combine(_waveFolder, $"{voice}_0_2.wav");
|
||||||
|
File.Move(inputFile, outputFileName);
|
||||||
|
|
||||||
|
progressBar1.Refresh();
|
||||||
|
labelProgress.Refresh();
|
||||||
|
Application.DoEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
progressBar1.Visible = false;
|
||||||
|
labelProgress.Text = string.Empty;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buttonOK_Click(object sender, EventArgs e)
|
private void buttonOK_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
DialogResult = DialogResult.OK;
|
DialogResult = DialogResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void nikseComboBoxEngine_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
nikseComboBoxVoice.Items.Clear();
|
||||||
|
|
||||||
|
if (nikseComboBoxEngine.SelectedIndex == 0)
|
||||||
|
{
|
||||||
|
using (var synthesizer = new SpeechSynthesizer())
|
||||||
|
{
|
||||||
|
foreach (var v in synthesizer.GetInstalledVoices())
|
||||||
|
{
|
||||||
|
if (v.Enabled)
|
||||||
|
{
|
||||||
|
nikseComboBoxVoice.Items.Add(v.VoiceInfo.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nikseComboBoxEngine.SelectedIndex == 1)
|
||||||
|
{
|
||||||
|
nikseComboBoxVoice.Items.Add("angie");
|
||||||
|
nikseComboBoxVoice.Items.Add("applejack");
|
||||||
|
nikseComboBoxVoice.Items.Add("daniel");
|
||||||
|
nikseComboBoxVoice.Items.Add("deniro");
|
||||||
|
nikseComboBoxVoice.Items.Add("emma");
|
||||||
|
nikseComboBoxVoice.Items.Add("freeman");
|
||||||
|
nikseComboBoxVoice.Items.Add("geralt");
|
||||||
|
nikseComboBoxVoice.Items.Add("halle");
|
||||||
|
nikseComboBoxVoice.Items.Add("jlaw");
|
||||||
|
nikseComboBoxVoice.Items.Add("lj");
|
||||||
|
nikseComboBoxVoice.Items.Add("mol");
|
||||||
|
nikseComboBoxVoice.Items.Add("myself");
|
||||||
|
nikseComboBoxVoice.Items.Add("pat");
|
||||||
|
nikseComboBoxVoice.Items.Add("pat2");
|
||||||
|
nikseComboBoxVoice.Items.Add("rainbow");
|
||||||
|
nikseComboBoxVoice.Items.Add("Update rainbow");
|
||||||
|
nikseComboBoxVoice.Items.Add("snakes");
|
||||||
|
nikseComboBoxVoice.Items.Add("tim_reynolds");
|
||||||
|
nikseComboBoxVoice.Items.Add("tom");
|
||||||
|
nikseComboBoxVoice.Items.Add("weaver");
|
||||||
|
nikseComboBoxVoice.Items.Add("william");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nikseComboBoxVoice.Items.Count > 0)
|
||||||
|
{
|
||||||
|
nikseComboBoxVoice.SelectedIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -75,6 +75,42 @@ namespace Nikse.SubtitleEdit.Logic
|
|||||||
return processMakeVideo;
|
return processMakeVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Process GenerateEmptyAudio(string outputFileName, float seconds, DataReceivedEventHandler dataReceivedHandler = null)
|
||||||
|
{
|
||||||
|
var processMakeVideo = new Process
|
||||||
|
{
|
||||||
|
StartInfo =
|
||||||
|
{
|
||||||
|
FileName = GetFfmpegLocation(),
|
||||||
|
Arguments = $"-f lavfi -i anullsrc -t {seconds.ToString(CultureInfo.InvariantCulture)} \"{outputFileName}\"",
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SetupDataReceiveHandler(dataReceivedHandler, processMakeVideo);
|
||||||
|
|
||||||
|
return processMakeVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Process MergeAudioTracks(string inputFileName1, string inputFileName2, string outputFileName, float startSeconds, DataReceivedEventHandler dataReceivedHandler = null)
|
||||||
|
{
|
||||||
|
var processMakeVideo = new Process
|
||||||
|
{
|
||||||
|
StartInfo =
|
||||||
|
{
|
||||||
|
FileName = GetFfmpegLocation(),
|
||||||
|
Arguments = $"-i \"{inputFileName1}\" -i \"{inputFileName2}\" -filter_complex \"aevalsrc=0:d={startSeconds.ToString(CultureInfo.InvariantCulture)}[s1];[s1][1:a]concat=n=2:v=0:a=1[ac1];[0:a][ac1]amix=2:normalize=false[aout]\" -map [aout] \"{outputFileName}\"",
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SetupDataReceiveHandler(dataReceivedHandler, processMakeVideo);
|
||||||
|
|
||||||
|
return processMakeVideo;
|
||||||
|
}
|
||||||
|
|
||||||
private static void SetupDataReceiveHandler(DataReceivedEventHandler dataReceivedHandler, Process processMakeVideo)
|
private static void SetupDataReceiveHandler(DataReceivedEventHandler dataReceivedHandler, Process processMakeVideo)
|
||||||
{
|
{
|
||||||
if (dataReceivedHandler != null)
|
if (dataReceivedHandler != null)
|
||||||
@ -546,5 +582,45 @@ namespace Nikse.SubtitleEdit.Logic
|
|||||||
SetupDataReceiveHandler(outputHandler, processMakeVideo);
|
SetupDataReceiveHandler(outputHandler, processMakeVideo);
|
||||||
return processMakeVideo;
|
return processMakeVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Process ChangeSpeed(string inputFileName, string outputFileName, float inputSpeed, DataReceivedEventHandler dataReceivedHandler = null)
|
||||||
|
{
|
||||||
|
var speed = Math.Max(0.5f, inputSpeed);
|
||||||
|
speed = Math.Min(100, speed);
|
||||||
|
speed = (float)Math.Round(speed, 3, MidpointRounding.AwayFromZero);
|
||||||
|
|
||||||
|
var processMakeVideo = new Process
|
||||||
|
{
|
||||||
|
StartInfo =
|
||||||
|
{
|
||||||
|
FileName = GetFfmpegLocation(),
|
||||||
|
Arguments = $"-i \"{inputFileName}\" -filter:a \"atempo={speed.ToString(CultureInfo.InvariantCulture)}\" \"{outputFileName}\"",
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SetupDataReceiveHandler(dataReceivedHandler, processMakeVideo);
|
||||||
|
|
||||||
|
return processMakeVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Process TrimSilenceStartAndEnd(string inputFileName, string outputFileName, DataReceivedEventHandler dataReceivedHandler = null)
|
||||||
|
{
|
||||||
|
var processMakeVideo = new Process
|
||||||
|
{
|
||||||
|
StartInfo =
|
||||||
|
{
|
||||||
|
FileName = GetFfmpegLocation(),
|
||||||
|
Arguments = $"-i \"{inputFileName}\" -af silenceremove=start_periods=1:start_silence=0.01,areverse,silenceremove=start_periods=1:start_silence=0.01,areverse \"{outputFileName}\"",
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SetupDataReceiveHandler(dataReceivedHandler, processMakeVideo);
|
||||||
|
|
||||||
|
return processMakeVideo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user