diff --git a/src/ui/Forms/Main.cs b/src/ui/Forms/Main.cs index e579a6fc9..e8b2058f1 100644 --- a/src/ui/Forms/Main.cs +++ b/src/ui/Forms/Main.cs @@ -19027,7 +19027,7 @@ namespace Nikse.SubtitleEdit.Forms } else if (e.Modifiers == (Keys.Alt | Keys.Shift | Keys.Control) && e.KeyCode == Keys.T) { - using (var form = new TextToSpeech(_subtitle, _videoFileName, _videoInfo)) + using (var form = new TextToSpeech(_subtitle, GetCurrentSubtitleFormat(), _videoFileName, _videoInfo)) { if (form.ShowDialog(this) != DialogResult.OK) { diff --git a/src/ui/Forms/TextToSpeech.Designer.cs b/src/ui/Forms/TextToSpeech.Designer.cs index bf414242f..c48b95df7 100644 --- a/src/ui/Forms/TextToSpeech.Designer.cs +++ b/src/ui/Forms/TextToSpeech.Designer.cs @@ -28,6 +28,7 @@ /// private void InitializeComponent() { + this.components = new System.ComponentModel.Container(); this.buttonOK = new System.Windows.Forms.Button(); this.labelProgress = new System.Windows.Forms.Label(); this.buttonGenerateTTS = new System.Windows.Forms.Button(); @@ -35,9 +36,13 @@ this.labelEngine = new System.Windows.Forms.Label(); this.groupBoxMsSettings = new System.Windows.Forms.GroupBox(); this.labelMsVoice = new System.Windows.Forms.Label(); + this.checkBoxAddToVideoFile = new System.Windows.Forms.CheckBox(); + this.listView1 = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.contextMenuStripActors = new System.Windows.Forms.ContextMenuStrip(this.components); this.nikseComboBoxVoice = new Nikse.SubtitleEdit.Controls.NikseComboBox(); this.nikseComboBoxEngine = new Nikse.SubtitleEdit.Controls.NikseComboBox(); - this.checkBoxAddToVideoFile = new System.Windows.Forms.CheckBox(); this.groupBoxMsSettings.SuspendLayout(); this.SuspendLayout(); // @@ -45,7 +50,7 @@ // this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.buttonOK.ImeMode = System.Windows.Forms.ImeMode.NoControl; - this.buttonOK.Location = new System.Drawing.Point(724, 407); + this.buttonOK.Location = new System.Drawing.Point(767, 456); this.buttonOK.Name = "buttonOK"; this.buttonOK.Size = new System.Drawing.Size(75, 23); this.buttonOK.TabIndex = 7; @@ -55,9 +60,10 @@ // // labelProgress // + this.labelProgress.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.labelProgress.AutoSize = true; this.labelProgress.ImeMode = System.Windows.Forms.ImeMode.NoControl; - this.labelProgress.Location = new System.Drawing.Point(12, 384); + this.labelProgress.Location = new System.Drawing.Point(12, 433); this.labelProgress.Name = "labelProgress"; this.labelProgress.Size = new System.Drawing.Size(70, 13); this.labelProgress.TabIndex = 9; @@ -67,7 +73,7 @@ // this.buttonGenerateTTS.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.buttonGenerateTTS.ImeMode = System.Windows.Forms.ImeMode.NoControl; - this.buttonGenerateTTS.Location = new System.Drawing.Point(571, 374); + this.buttonGenerateTTS.Location = new System.Drawing.Point(614, 423); this.buttonGenerateTTS.Name = "buttonGenerateTTS"; this.buttonGenerateTTS.Size = new System.Drawing.Size(228, 23); this.buttonGenerateTTS.TabIndex = 11; @@ -79,9 +85,9 @@ // 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, 407); + this.progressBar1.Location = new System.Drawing.Point(12, 456); this.progressBar1.Name = "progressBar1"; - this.progressBar1.Size = new System.Drawing.Size(706, 23); + this.progressBar1.Size = new System.Drawing.Size(749, 10); this.progressBar1.TabIndex = 12; // // labelEngine @@ -89,7 +95,7 @@ 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.Location = new System.Drawing.Point(448, 12); this.labelEngine.Name = "labelEngine"; this.labelEngine.Size = new System.Drawing.Size(40, 13); this.labelEngine.TabIndex = 14; @@ -101,9 +107,9 @@ | 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.Location = new System.Drawing.Point(451, 57); this.groupBoxMsSettings.Name = "groupBoxMsSettings"; - this.groupBoxMsSettings.Size = new System.Drawing.Size(391, 311); + this.groupBoxMsSettings.Size = new System.Drawing.Size(391, 320); this.groupBoxMsSettings.TabIndex = 15; this.groupBoxMsSettings.TabStop = false; this.groupBoxMsSettings.Text = "Settings"; @@ -119,6 +125,51 @@ this.labelMsVoice.TabIndex = 16; this.labelMsVoice.Text = "Voice"; // + // checkBoxAddToVideoFile + // + this.checkBoxAddToVideoFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.checkBoxAddToVideoFile.AutoSize = true; + this.checkBoxAddToVideoFile.Location = new System.Drawing.Point(614, 397); + this.checkBoxAddToVideoFile.Name = "checkBoxAddToVideoFile"; + this.checkBoxAddToVideoFile.Size = new System.Drawing.Size(176, 17); + this.checkBoxAddToVideoFile.TabIndex = 16; + this.checkBoxAddToVideoFile.Text = "Add audio to video file (new file)"; + this.checkBoxAddToVideoFile.UseVisualStyleBackColor = true; + // + // listView1 + // + this.listView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2}); + this.listView1.ContextMenuStrip = this.contextMenuStripActors; + this.listView1.FullRowSelect = true; + this.listView1.GridLines = true; + this.listView1.HideSelection = false; + this.listView1.Location = new System.Drawing.Point(12, 28); + this.listView1.Name = "listView1"; + this.listView1.Size = new System.Drawing.Size(421, 349); + this.listView1.TabIndex = 17; + this.listView1.UseCompatibleStateImageBehavior = false; + this.listView1.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + this.columnHeader1.Text = "Style"; + this.columnHeader1.Width = 200; + // + // columnHeader2 + // + this.columnHeader2.Text = "Voice"; + this.columnHeader2.Width = 200; + // + // contextMenuStripActors + // + this.contextMenuStripActors.Name = "contextMenuStripActors"; + this.contextMenuStripActors.Size = new System.Drawing.Size(61, 4); + // // nikseComboBoxVoice // this.nikseComboBoxVoice.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); @@ -157,7 +208,7 @@ 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.Location = new System.Drawing.Point(451, 28); this.nikseComboBoxEngine.MaxLength = 32767; this.nikseComboBoxEngine.Name = "nikseComboBoxEngine"; this.nikseComboBoxEngine.SelectedIndex = -1; @@ -170,21 +221,12 @@ this.nikseComboBoxEngine.UsePopupWindow = false; this.nikseComboBoxEngine.SelectedIndexChanged += new System.EventHandler(this.nikseComboBoxEngine_SelectedIndexChanged); // - // checkBoxAddToVideoFile - // - this.checkBoxAddToVideoFile.AutoSize = true; - this.checkBoxAddToVideoFile.Location = new System.Drawing.Point(15, 82); - this.checkBoxAddToVideoFile.Name = "checkBoxAddToVideoFile"; - this.checkBoxAddToVideoFile.Size = new System.Drawing.Size(176, 17); - this.checkBoxAddToVideoFile.TabIndex = 16; - this.checkBoxAddToVideoFile.Text = "Add audio to video file (new file)"; - this.checkBoxAddToVideoFile.UseVisualStyleBackColor = true; - // // TextToSpeech // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(811, 442); + this.ClientSize = new System.Drawing.Size(854, 491); + this.Controls.Add(this.listView1); this.Controls.Add(this.checkBoxAddToVideoFile); this.Controls.Add(this.groupBoxMsSettings); this.Controls.Add(this.labelEngine); @@ -218,5 +260,9 @@ private System.Windows.Forms.Label labelMsVoice; private Controls.NikseComboBox nikseComboBoxVoice; private System.Windows.Forms.CheckBox checkBoxAddToVideoFile; + private System.Windows.Forms.ListView listView1; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ContextMenuStrip contextMenuStripActors; } } \ No newline at end of file diff --git a/src/ui/Forms/TextToSpeech.cs b/src/ui/Forms/TextToSpeech.cs index 98e45d5d6..5f80e85bf 100644 --- a/src/ui/Forms/TextToSpeech.cs +++ b/src/ui/Forms/TextToSpeech.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Speech.Synthesis; using System.Windows.Forms; +using Nikse.SubtitleEdit.Core.SubtitleFormats; namespace Nikse.SubtitleEdit.Forms { @@ -16,8 +17,17 @@ namespace Nikse.SubtitleEdit.Forms private readonly string _videoFileName; private readonly VideoInfo _videoInfo; private string _waveFolder; + private readonly List _actorAndVoices; - public TextToSpeech(Subtitle subtitle, string videoFileName, VideoInfo videoInfo) + public class ActorAndVoice + { + public string Actor { get; set; } + public int UseCount { get; set; } + public string Voice { get; set; } + public int VoiceIndex { get; set; } + } + + public TextToSpeech(Subtitle subtitle, SubtitleFormat subtitleFormat, string videoFileName, VideoInfo videoInfo) { UiUtil.PreInitialize(this); InitializeComponent(); @@ -39,6 +49,81 @@ namespace Nikse.SubtitleEdit.Forms nikseComboBoxEngine.Items.Add("Tortoise TTS (very slow/very good)"); nikseComboBoxEngine.Items.Add("Mimic3"); nikseComboBoxEngine.SelectedIndex = 0; + + _actorAndVoices = new List(); + listView1.Visible = false; + if (subtitleFormat.GetType() == typeof(AdvancedSubStationAlpha)) + { + var actors = _subtitle.Paragraphs + .Where(p => !string.IsNullOrEmpty(p.Actor)) + .Select(p => p.Actor) + .Distinct() + .ToList(); + if (actors.Any()) + { + foreach (var actor in actors) + { + var actorAndVoice = new ActorAndVoice + { + Actor = actor, + UseCount = _subtitle.Paragraphs.Count(p => p.Actor == actor), + }; + + _actorAndVoices.Add(actorAndVoice); + } + + FillActorListView(); + + for (var index = 0; index < nikseComboBoxVoice.Items.Count; index++) + { + var item = nikseComboBoxVoice.Items[index]; + + var tsi = new ToolStripMenuItem(); + tsi.Tag = new ActorAndVoice { Voice = item.ToString(), VoiceIndex = index }; + tsi.Text = item.ToString(); + tsi.Click += (sender, args) => + { + var a = (ActorAndVoice)(sender as ToolStripItem).Tag; + SetActor(a); + }; + contextMenuStripActors.Items.Add(tsi); + + listView1.Visible = true; + + } + } + } + } + + + private void SetActor(ActorAndVoice actor) + { + foreach (int index in listView1.SelectedIndices) + { + ListViewItem item = listView1.Items[index]; + var itemActor = (ActorAndVoice)item.Tag; + itemActor.Voice = actor.Voice; + itemActor.VoiceIndex = actor.VoiceIndex; + item.SubItems[1].Text = actor.Voice; + } + } + + private void FillActorListView() + { + listView1.BeginUpdate(); + listView1.Items.Clear(); + foreach (var actor in _actorAndVoices) + { + var lvi = new ListViewItem + { + Tag = actor, + Text = actor.Actor, + }; + lvi.SubItems.Add(actor.Voice); + listView1.Items.Add(lvi); + } + + listView1.EndUpdate(); } private void ButtonGenerateTtsClick(object sender, EventArgs e) @@ -65,7 +150,7 @@ namespace Nikse.SubtitleEdit.Forms var tempAudioFile = MergeAudioParagraphs(fileNames); var resultAudioFileName = Path.Combine(Path.GetDirectoryName(tempAudioFile), Path.GetFileNameWithoutExtension(_videoFileName) + ".wav"); File.Move(tempAudioFile, resultAudioFileName); - + Cleanup(_waveFolder, resultAudioFileName); if (checkBoxAddToVideoFile.Checked) @@ -226,7 +311,18 @@ namespace Nikse.SubtitleEdit.Forms var builder = new PromptBuilder(); if (voiceInfo != null) { - builder.StartVoice(voiceInfo); + var v = voiceInfo; + if (_actorAndVoices.Count > 0 && !string.IsNullOrEmpty(p.Actor)) + { + var f = _actorAndVoices.FirstOrDefault(x => x.Actor == p.Actor); + if (f != null && !string.IsNullOrEmpty(f.Voice)) + { + var item = vs[f.VoiceIndex]; + v = item.VoiceInfo; + } + } + + builder.StartVoice(v); } builder.AppendText(p.Text); @@ -283,13 +379,23 @@ namespace Nikse.SubtitleEdit.Forms var p = _subtitle.Paragraphs[index]; var outputFileName = Path.Combine(_waveFolder, index + ".wav"); + var v = voice; + if (_actorAndVoices.Count > 0 && !string.IsNullOrEmpty(p.Actor)) + { + var f = _actorAndVoices.FirstOrDefault(x => x.Actor == p.Actor); + if (f != null && !string.IsNullOrEmpty(f.Voice)) + { + v = f.Voice; + } + } + 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('"')}\"", + Arguments = $"do_tts.py --output_path \"{_waveFolder}\" --preset ultra_fast --voice {v} --text \"{p.Text.RemoveChar('"')}\"", UseShellExecute = false, CreateNoWindow = true, } @@ -298,7 +404,7 @@ namespace Nikse.SubtitleEdit.Forms processTortoiseTts.Start(); processTortoiseTts.WaitForExit(); - var inputFile = Path.Combine(_waveFolder, $"{voice}_0_2.wav"); + var inputFile = Path.Combine(_waveFolder, $"{v}_0_2.wav"); File.Move(inputFile, outputFileName); progressBar1.Refresh(); diff --git a/src/ui/Forms/TextToSpeech.resx b/src/ui/Forms/TextToSpeech.resx index 1af7de150..dec39f79f 100644 --- a/src/ui/Forms/TextToSpeech.resx +++ b/src/ui/Forms/TextToSpeech.resx @@ -117,4 +117,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 17, 17 + \ No newline at end of file