mirror of
https://github.com/SubtitleEdit/subtitleedit.git
synced 2024-11-22 03:02:35 +01:00
Testing naudio record
This commit is contained in:
parent
ec8020621d
commit
480152a2df
@ -2561,6 +2561,7 @@ can edit in same subtitle file (collaboration)</Information>
|
||||
<MainTextBoxAutoBreak>Auto break text</MainTextBoxAutoBreak>
|
||||
<MainTextBoxAutoBreakFromPos>Break at first space from cursor position</MainTextBoxAutoBreakFromPos>
|
||||
<MainTextBoxAutoBreakFromPosAndGoToNext>Break at first space from cursor position and go to next</MainTextBoxAutoBreakFromPosAndGoToNext>
|
||||
<MainTextBoxDictate>Dictate</MainTextBoxDictate>
|
||||
<MainTextBoxUnbreak>Unbreak text</MainTextBoxUnbreak>
|
||||
<MainTextBoxUnbreakNoSpace>Unbreak without space (CJK)</MainTextBoxUnbreakNoSpace>
|
||||
<MainTextBoxAssaIntellisense>Show ASSA tag helper</MainTextBoxAssaIntellisense>
|
||||
|
@ -179,6 +179,8 @@ COPY /Y /V "..\..\DLLs\Interop.QuartzTypeLib.dll" "temp_zip\"
|
||||
COPY /Y /V "System.Net.Http.Extensions.dll" "temp_zip\"
|
||||
COPY /Y /V "Newtonsoft.Json.dll" "temp_zip\"
|
||||
COPY /Y /V "System.Net.Http.Primitives.dll" "temp_zip\"
|
||||
COPY /Y /V "NAudio.Core.dll" "temp_zip\"
|
||||
COPY /Y /V "NAudio.WinMM.dll" "temp_zip\"
|
||||
COPY /Y /V "SubtitleEdit.exe" "temp_zip\"
|
||||
COPY /Y /V "Languages\*.xml" "temp_zip\Languages\"
|
||||
COPY /Y /V "..\..\..\..\Dictionaries\*.*" "temp_zip\Dictionaries\"
|
||||
|
@ -202,6 +202,9 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
private ListBox _intellisenceList;
|
||||
private ListBox _intellisenceListOriginal;
|
||||
private bool _updateSelectedCountStatusBar;
|
||||
private Dictate _dictateForm;
|
||||
private object _dictateTextBox;
|
||||
private bool _hasCurrentVosk;
|
||||
|
||||
public bool IsMenuOpen { get; private set; }
|
||||
|
||||
@ -10699,12 +10702,55 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
else if (e.KeyData == _shortcuts.MainTextBoxRecord)
|
||||
{
|
||||
e.SuppressKeyPress = true;
|
||||
using (var form = new Dictate())
|
||||
|
||||
if (_dictateTextBox != null && _dictateForm != null)
|
||||
{
|
||||
if (form.ShowDialog(this) != DialogResult.OK)
|
||||
return; // already recording
|
||||
}
|
||||
|
||||
if (!RequireFfmpegOk())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var voskFolder = Path.Combine(Configuration.DataDirectory, "Vosk");
|
||||
if (Configuration.IsRunningOnWindows && !HasCurrentVosk(voskFolder))
|
||||
{
|
||||
if (MessageBox.Show(string.Format(LanguageSettings.Current.Settings.DownloadX, "libvosk"), "Subtitle Edit", MessageBoxButtons.YesNoCancel) != DialogResult.Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (var form = new DownloadVosk())
|
||||
{
|
||||
if (form.ShowDialog(this) != DialogResult.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_subtitle?.GetParagraphOrDefault(_subtitleListViewIndex) == null || !(sender is TextBox || sender is AdvancedTextBox))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_dictateForm == null || string.IsNullOrEmpty(Configuration.Settings.Tools.VoskModel))
|
||||
{
|
||||
_dictateForm?.Dispose();
|
||||
_dictateForm = new Dictate();
|
||||
if (_dictateForm.ShowDialog(this) != DialogResult.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_dictateTextBox = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dictateTextBox = sender;
|
||||
_dictateForm.Record();
|
||||
ShowStatus("Recording...");
|
||||
}
|
||||
}
|
||||
|
||||
@ -12945,6 +12991,8 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
_dictateForm?.Dispose();
|
||||
}
|
||||
|
||||
private void SaveListViewWidths()
|
||||
@ -17281,7 +17329,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
{
|
||||
SetPlayRateAndPlay(200, false);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
SetPlayRateAndPlay(100, false);
|
||||
}
|
||||
@ -29830,6 +29878,28 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
_mainAdjustStartDownEndUpAndGoToNextParagraph = null;
|
||||
}
|
||||
else if (_dictateTextBox != null && _dictateForm != null)
|
||||
{
|
||||
Application.DoEvents();
|
||||
Cursor = Cursors.WaitCursor;
|
||||
ShowStatus(LanguageSettings.Current.AudioToText.Transcribing);
|
||||
var text = _dictateForm.RecordingToText();
|
||||
Cursor = Cursors.Default;
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
if (_dictateTextBox is TextBox tb)
|
||||
{
|
||||
tb.Paste(text);
|
||||
}
|
||||
else if (_dictateTextBox is AdvancedTextBox atb)
|
||||
{
|
||||
atb.SelectedText = text;
|
||||
}
|
||||
}
|
||||
|
||||
ShowStatus(string.Empty);
|
||||
_dictateTextBox = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void ToolStripMenuItemSurroundWithMusicSymbolsClick(object sender, EventArgs e)
|
||||
@ -34306,7 +34376,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
|
||||
private bool HasCurrentVosk(string voskFolder)
|
||||
{
|
||||
if (Configuration.IsRunningOnLinux)
|
||||
if (Configuration.IsRunningOnLinux || _hasCurrentVosk)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -34322,7 +34392,9 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
? "1cc13d8e2ffd3ad7ca76941c99e8ad00567d0b8135878c3a80fb938054cf98bde1f692647e6d19df7526c98aa5ad975d72dba20bf1759baedba5c753a14480bb"
|
||||
: "77479a934650b40968d54dcf71fce17237c59b62b6c64ad3d6b5433486b76b6202eb956e93597ba466c67aa0d553db7b2863e0aeb8856a6dd29a3aba3a14bf66";
|
||||
var hash = Utilities.GetSha512Hash(FileUtil.ReadAllBytesShared(voskDll));
|
||||
return currentVoskDllSha512Hash == hash;
|
||||
|
||||
_hasCurrentVosk = currentVoskDllSha512Hash == hash;
|
||||
return _hasCurrentVosk;
|
||||
}
|
||||
|
||||
private void Main_MouseDown(object sender, MouseEventArgs e)
|
||||
@ -34359,7 +34431,7 @@ namespace Nikse.SubtitleEdit.Forms
|
||||
{
|
||||
Cursor = Cursors.WaitCursor;
|
||||
var timeCode = new TimeCode(mediaPlayer.CurrentPosition * 1000.0 + 1000).ToHHMMSS();
|
||||
var colorMatrix = "bt601:bt709"; // ffmpeg bug with assa color?
|
||||
var colorMatrix = "bt601:bt709"; // ffmpeg bug with assa color?
|
||||
var bmpFileName = VideoPreviewGenerator.GetScreenShot(_videoFileName, timeCode, colorMatrix);
|
||||
using (var bmp = new Bitmap(bmpFileName))
|
||||
{
|
||||
|
@ -64,7 +64,7 @@ namespace Nikse.SubtitleEdit.Forms.SpeechRecognition
|
||||
|
||||
checkBoxUsePostProcessing.Checked = Configuration.Settings.Tools.VoskPostProcessing;
|
||||
_voskFolder = Path.Combine(Configuration.DataDirectory, "Vosk");
|
||||
FillModels(string.Empty);
|
||||
FillModels(comboBoxModels, string.Empty);
|
||||
|
||||
textBoxLog.Visible = false;
|
||||
textBoxLog.Dock = DockStyle.Fill;
|
||||
@ -86,11 +86,12 @@ namespace Nikse.SubtitleEdit.Forms.SpeechRecognition
|
||||
labelFC.Text = string.Empty;
|
||||
}
|
||||
|
||||
private void FillModels(string lastDownloadedModel)
|
||||
public static void FillModels(ComboBox comboBoxModels, string lastDownloadedModel)
|
||||
{
|
||||
var voskFolder = Path.Combine(Configuration.DataDirectory, "Vosk");
|
||||
var selectName = string.IsNullOrEmpty(lastDownloadedModel) ? Configuration.Settings.Tools.VoskModel : lastDownloadedModel;
|
||||
comboBoxModels.Items.Clear();
|
||||
foreach (var directory in Directory.GetDirectories(_voskFolder))
|
||||
foreach (var directory in Directory.GetDirectories(voskFolder))
|
||||
{
|
||||
var name = Path.GetFileName(directory);
|
||||
if (!File.Exists(Path.Combine(directory, "final.mdl")) && !File.Exists(Path.Combine(directory, "am", "final.mdl")))
|
||||
@ -338,7 +339,7 @@ namespace Nikse.SubtitleEdit.Forms.SpeechRecognition
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<ResultText> ParseJsonToResult(string result)
|
||||
public static List<ResultText> ParseJsonToResult(string result)
|
||||
{
|
||||
var list = new List<ResultText>();
|
||||
var jsonParser = new SeJsonParser();
|
||||
@ -597,7 +598,7 @@ namespace Nikse.SubtitleEdit.Forms.SpeechRecognition
|
||||
using (var form = new AudioToTextModelDownload { AutoClose = true })
|
||||
{
|
||||
form.ShowDialog(this);
|
||||
FillModels(form.LastDownloadedModel);
|
||||
FillModels(comboBoxModels, form.LastDownloadedModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ namespace Nikse.SubtitleEdit.Forms.SpeechRecognition
|
||||
|
||||
checkBoxUsePostProcessing.Checked = Configuration.Settings.Tools.VoskPostProcessing;
|
||||
_voskFolder = Path.Combine(Configuration.DataDirectory, "Vosk");
|
||||
FillModels(string.Empty);
|
||||
AudioToText.FillModels(comboBoxModels, string.Empty);
|
||||
|
||||
textBoxLog.Visible = false;
|
||||
textBoxLog.Dock = DockStyle.Fill;
|
||||
@ -64,31 +64,6 @@ namespace Nikse.SubtitleEdit.Forms.SpeechRecognition
|
||||
}
|
||||
}
|
||||
|
||||
private void FillModels(string lastDownloadedModel)
|
||||
{
|
||||
var selectName = string.IsNullOrEmpty(lastDownloadedModel) ? Configuration.Settings.Tools.VoskModel : lastDownloadedModel;
|
||||
comboBoxModels.Items.Clear();
|
||||
foreach (var directory in Directory.GetDirectories(_voskFolder))
|
||||
{
|
||||
var name = Path.GetFileName(directory);
|
||||
if (!File.Exists(Path.Combine(directory, "final.mdl")) && !File.Exists(Path.Combine(directory, "am", "final.mdl")))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
comboBoxModels.Items.Add(name);
|
||||
if (name == selectName)
|
||||
{
|
||||
comboBoxModels.SelectedIndex = comboBoxModels.Items.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (comboBoxModels.SelectedIndex < 0 && comboBoxModels.Items.Count > 0)
|
||||
{
|
||||
comboBoxModels.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void ButtonGenerate_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (comboBoxModels.Items.Count == 0)
|
||||
@ -258,7 +233,7 @@ namespace Nikse.SubtitleEdit.Forms.SpeechRecognition
|
||||
if (rec.AcceptWaveform(buffer, bytesRead))
|
||||
{
|
||||
var res = rec.Result();
|
||||
var results = ParseJsonToResult(res);
|
||||
var results = AudioToText.ParseJsonToResult(res);
|
||||
list.AddRange(results);
|
||||
}
|
||||
else
|
||||
@ -276,36 +251,12 @@ namespace Nikse.SubtitleEdit.Forms.SpeechRecognition
|
||||
}
|
||||
|
||||
var finalResult = rec.FinalResult();
|
||||
var finalResults = ParseJsonToResult(finalResult);
|
||||
var finalResults = AudioToText.ParseJsonToResult(finalResult);
|
||||
list.AddRange(finalResults);
|
||||
timer1.Stop();
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<ResultText> ParseJsonToResult(string result)
|
||||
{
|
||||
var list = new List<ResultText>();
|
||||
var jsonParser = new SeJsonParser();
|
||||
var root = jsonParser.GetArrayElementsByName(result, "result");
|
||||
foreach (var item in root)
|
||||
{
|
||||
var conf = jsonParser.GetFirstObject(item, "conf");
|
||||
var start = jsonParser.GetFirstObject(item, "start");
|
||||
var end = jsonParser.GetFirstObject(item, "end");
|
||||
var word = jsonParser.GetFirstObject(item, "word");
|
||||
if (!string.IsNullOrWhiteSpace(word) &&
|
||||
decimal.TryParse(conf, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var confidence) &&
|
||||
decimal.TryParse(start, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var startSeconds) &&
|
||||
decimal.TryParse(end, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var endSeconds))
|
||||
{
|
||||
var rt = new ResultText { Confidence = confidence, Text = word, Start = startSeconds, End = endSeconds };
|
||||
list.Add(rt);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private void buttonCancel_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (buttonGenerate.Enabled)
|
||||
@ -397,7 +348,7 @@ namespace Nikse.SubtitleEdit.Forms.SpeechRecognition
|
||||
using (var form = new AudioToTextModelDownload { AutoClose = true })
|
||||
{
|
||||
form.ShowDialog(this);
|
||||
FillModels(form.LastDownloadedModel);
|
||||
AudioToText.FillModels(comboBoxModels, form.LastDownloadedModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
93
src/ui/Forms/SpeechRecognition/Dictate.Designer.cs
generated
93
src/ui/Forms/SpeechRecognition/Dictate.Designer.cs
generated
@ -30,13 +30,20 @@
|
||||
{
|
||||
this.buttonCancel = new System.Windows.Forms.Button();
|
||||
this.buttonOK = new System.Windows.Forms.Button();
|
||||
this.groupBoxModels = new System.Windows.Forms.GroupBox();
|
||||
this.buttonDownload = new System.Windows.Forms.Button();
|
||||
this.linkLabelOpenModelsFolder = new System.Windows.Forms.LinkLabel();
|
||||
this.labelModel = new System.Windows.Forms.Label();
|
||||
this.comboBoxModels = new System.Windows.Forms.ComboBox();
|
||||
this.checkBoxUsePostProcessing = new System.Windows.Forms.CheckBox();
|
||||
this.groupBoxModels.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// buttonCancel
|
||||
//
|
||||
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.buttonCancel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.buttonCancel.Location = new System.Drawing.Point(713, 415);
|
||||
this.buttonCancel.Location = new System.Drawing.Point(539, 137);
|
||||
this.buttonCancel.Name = "buttonCancel";
|
||||
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonCancel.TabIndex = 6;
|
||||
@ -48,7 +55,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(632, 415);
|
||||
this.buttonOK.Location = new System.Drawing.Point(458, 137);
|
||||
this.buttonOK.Name = "buttonOK";
|
||||
this.buttonOK.Size = new System.Drawing.Size(75, 23);
|
||||
this.buttonOK.TabIndex = 5;
|
||||
@ -56,21 +63,95 @@
|
||||
this.buttonOK.UseVisualStyleBackColor = true;
|
||||
this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
|
||||
//
|
||||
// groupBoxModels
|
||||
//
|
||||
this.groupBoxModels.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.groupBoxModels.Controls.Add(this.buttonDownload);
|
||||
this.groupBoxModels.Controls.Add(this.linkLabelOpenModelsFolder);
|
||||
this.groupBoxModels.Controls.Add(this.labelModel);
|
||||
this.groupBoxModels.Controls.Add(this.comboBoxModels);
|
||||
this.groupBoxModels.Location = new System.Drawing.Point(12, 12);
|
||||
this.groupBoxModels.Name = "groupBoxModels";
|
||||
this.groupBoxModels.Size = new System.Drawing.Size(602, 82);
|
||||
this.groupBoxModels.TabIndex = 7;
|
||||
this.groupBoxModels.TabStop = false;
|
||||
this.groupBoxModels.Text = "Models";
|
||||
//
|
||||
// buttonDownload
|
||||
//
|
||||
this.buttonDownload.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.buttonDownload.Location = new System.Drawing.Point(265, 43);
|
||||
this.buttonDownload.Name = "buttonDownload";
|
||||
this.buttonDownload.Size = new System.Drawing.Size(28, 23);
|
||||
this.buttonDownload.TabIndex = 2;
|
||||
this.buttonDownload.Text = "...";
|
||||
this.buttonDownload.UseVisualStyleBackColor = true;
|
||||
this.buttonDownload.Click += new System.EventHandler(this.buttonDownload_Click);
|
||||
//
|
||||
// linkLabelOpenModelsFolder
|
||||
//
|
||||
this.linkLabelOpenModelsFolder.AutoSize = true;
|
||||
this.linkLabelOpenModelsFolder.Location = new System.Drawing.Point(301, 51);
|
||||
this.linkLabelOpenModelsFolder.Name = "linkLabelOpenModelsFolder";
|
||||
this.linkLabelOpenModelsFolder.Size = new System.Drawing.Size(98, 13);
|
||||
this.linkLabelOpenModelsFolder.TabIndex = 3;
|
||||
this.linkLabelOpenModelsFolder.TabStop = true;
|
||||
this.linkLabelOpenModelsFolder.Text = "Open models folder";
|
||||
this.linkLabelOpenModelsFolder.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelOpenModelsFolder_LinkClicked);
|
||||
//
|
||||
// labelModel
|
||||
//
|
||||
this.labelModel.AutoSize = true;
|
||||
this.labelModel.Location = new System.Drawing.Point(16, 29);
|
||||
this.labelModel.Name = "labelModel";
|
||||
this.labelModel.Size = new System.Drawing.Size(167, 13);
|
||||
this.labelModel.TabIndex = 0;
|
||||
this.labelModel.Text = "Choose speech recognition model";
|
||||
//
|
||||
// comboBoxModels
|
||||
//
|
||||
this.comboBoxModels.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.comboBoxModels.FormattingEnabled = true;
|
||||
this.comboBoxModels.Location = new System.Drawing.Point(19, 45);
|
||||
this.comboBoxModels.Name = "comboBoxModels";
|
||||
this.comboBoxModels.Size = new System.Drawing.Size(240, 21);
|
||||
this.comboBoxModels.TabIndex = 1;
|
||||
//
|
||||
// checkBoxUsePostProcessing
|
||||
//
|
||||
this.checkBoxUsePostProcessing.AutoSize = true;
|
||||
this.checkBoxUsePostProcessing.Location = new System.Drawing.Point(12, 102);
|
||||
this.checkBoxUsePostProcessing.Name = "checkBoxUsePostProcessing";
|
||||
this.checkBoxUsePostProcessing.Size = new System.Drawing.Size(312, 17);
|
||||
this.checkBoxUsePostProcessing.TabIndex = 8;
|
||||
this.checkBoxUsePostProcessing.Text = "Use post-processing (line merge, fix casing, and punctuation)";
|
||||
this.checkBoxUsePostProcessing.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// Dictate
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(800, 450);
|
||||
this.ClientSize = new System.Drawing.Size(626, 172);
|
||||
this.Controls.Add(this.checkBoxUsePostProcessing);
|
||||
this.Controls.Add(this.groupBoxModels);
|
||||
this.Controls.Add(this.buttonCancel);
|
||||
this.Controls.Add(this.buttonOK);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.KeyPreview = true;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "Dictate";
|
||||
this.ShowIcon = false;
|
||||
this.ShowInTaskbar = false;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Dictate";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Dictate_FormClosing);
|
||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Dictate_KeyDown);
|
||||
this.groupBoxModels.ResumeLayout(false);
|
||||
this.groupBoxModels.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
@ -78,5 +159,11 @@
|
||||
|
||||
private System.Windows.Forms.Button buttonCancel;
|
||||
private System.Windows.Forms.Button buttonOK;
|
||||
private System.Windows.Forms.GroupBox groupBoxModels;
|
||||
private System.Windows.Forms.Button buttonDownload;
|
||||
private System.Windows.Forms.LinkLabel linkLabelOpenModelsFolder;
|
||||
private System.Windows.Forms.Label labelModel;
|
||||
private System.Windows.Forms.ComboBox comboBoxModels;
|
||||
private System.Windows.Forms.CheckBox checkBoxUsePostProcessing;
|
||||
}
|
||||
}
|
@ -1,19 +1,126 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using NAudio.Wave;
|
||||
using Nikse.SubtitleEdit.Core.AudioToText;
|
||||
using Nikse.SubtitleEdit.Core.Common;
|
||||
using Nikse.SubtitleEdit.Logic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using Vosk;
|
||||
|
||||
namespace Nikse.SubtitleEdit.Forms.SpeechRecognition
|
||||
{
|
||||
public partial class Dictate : Form
|
||||
{
|
||||
private static WaveFileWriter _waveFile;
|
||||
private static Model _model;
|
||||
private WaveInEvent _waveSource;
|
||||
public string WaveFileName { get; set; }
|
||||
public static bool DataRecorded { get; set; }
|
||||
|
||||
public Dictate()
|
||||
{
|
||||
UiUtil.PreInitialize(this);
|
||||
InitializeComponent();
|
||||
UiUtil.FixFonts(this);
|
||||
groupBoxModels.Text = LanguageSettings.Current.AudioToText.Models;
|
||||
labelModel.Text = LanguageSettings.Current.AudioToText.ChooseModel;
|
||||
linkLabelOpenModelsFolder.Text = LanguageSettings.Current.AudioToText.OpenModelsFolder;
|
||||
checkBoxUsePostProcessing.Text = LanguageSettings.Current.AudioToText.UsePostProcessing;
|
||||
buttonOK.Text = LanguageSettings.Current.General.Ok;
|
||||
buttonCancel.Text = LanguageSettings.Current.General.Cancel;
|
||||
UiUtil.FixLargeFonts(this, buttonOK);
|
||||
AudioToText.FillModels(comboBoxModels, string.Empty);
|
||||
checkBoxUsePostProcessing.Checked = Configuration.Settings.Tools.VoskPostProcessing;
|
||||
}
|
||||
|
||||
public void Record()
|
||||
{
|
||||
_waveSource = new WaveInEvent();
|
||||
_waveSource.WaveFormat = new WaveFormat(16000, 1);
|
||||
_waveSource.DataAvailable += WaveSourceDataAvailable;
|
||||
WaveFileName = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.wav");
|
||||
_waveFile = new WaveFileWriter(WaveFileName, _waveSource.WaveFormat);
|
||||
DataRecorded = false;
|
||||
_waveSource.StartRecording();
|
||||
}
|
||||
|
||||
public string RecordingToText()
|
||||
{
|
||||
_waveSource.StopRecording();
|
||||
_waveSource.Dispose();
|
||||
_waveFile.Close();
|
||||
if (!DataRecorded || !File.Exists(WaveFileName))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var voskFolder = Path.Combine(Configuration.DataDirectory, "Vosk");
|
||||
Directory.SetCurrentDirectory(voskFolder);
|
||||
Vosk.Vosk.SetLogLevel(0);
|
||||
if (_model == null)
|
||||
{
|
||||
var modelFileName = Path.Combine(voskFolder, comboBoxModels.Text);
|
||||
_model = new Model(modelFileName);
|
||||
}
|
||||
|
||||
var rec = new VoskRecognizer(_model, 16000.0f);
|
||||
rec.SetMaxAlternatives(0);
|
||||
rec.SetWords(true);
|
||||
var list = new List<ResultText>();
|
||||
var buffer = new byte[4096];
|
||||
using (var source = File.OpenRead(WaveFileName))
|
||||
{
|
||||
int bytesRead;
|
||||
while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
if (rec.AcceptWaveform(buffer, bytesRead))
|
||||
{
|
||||
var res = rec.Result();
|
||||
var results = AudioToText.ParseJsonToResult(res);
|
||||
list.AddRange(results);
|
||||
}
|
||||
else
|
||||
{
|
||||
var res = rec.PartialResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var finalResult = rec.FinalResult();
|
||||
var finalResults = AudioToText.ParseJsonToResult(finalResult);
|
||||
list.AddRange(finalResults);
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(WaveFileName);
|
||||
WaveFileName = null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
return ResultListToText(list);
|
||||
}
|
||||
|
||||
private static string ResultListToText(List<ResultText> list)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (var resultText in list)
|
||||
{
|
||||
sb.Append(resultText.Text);
|
||||
sb.Append(" ");
|
||||
}
|
||||
|
||||
return sb.ToString().Trim();
|
||||
}
|
||||
|
||||
private static void WaveSourceDataAvailable(object sender, WaveInEventArgs e)
|
||||
{
|
||||
_waveFile.Write(e.Buffer, 0, e.BytesRecorded);
|
||||
DataRecorded = true;
|
||||
}
|
||||
|
||||
private void buttonOK_Click(object sender, EventArgs e)
|
||||
@ -33,5 +140,26 @@ namespace Nikse.SubtitleEdit.Forms.SpeechRecognition
|
||||
DialogResult = DialogResult.Cancel;
|
||||
}
|
||||
}
|
||||
|
||||
private void buttonDownload_Click(object sender, EventArgs e)
|
||||
{
|
||||
using (var form = new AudioToTextModelDownload { AutoClose = true })
|
||||
{
|
||||
form.ShowDialog(this);
|
||||
AudioToText.FillModels(comboBoxModels, form.LastDownloadedModel);
|
||||
}
|
||||
}
|
||||
|
||||
private void linkLabelOpenModelsFolder_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
var voskFolder = Path.Combine(Configuration.DataDirectory, "Vosk");
|
||||
UiUtil.OpenFolder(voskFolder);
|
||||
}
|
||||
|
||||
private void Dictate_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
Configuration.Settings.Tools.VoskModel = comboBoxModels.Text;
|
||||
Configuration.Settings.Tools.VoskPostProcessing = checkBoxUsePostProcessing.Checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2896,7 +2896,7 @@ can edit in same subtitle file (collaboration)",
|
||||
MainTextBoxAutoBreak = "Auto break text",
|
||||
MainTextBoxAutoBreakFromPos = "Break at first space from cursor position",
|
||||
MainTextBoxAutoBreakFromPosAndGoToNext = "Break at first space from cursor position and go to next",
|
||||
MainTextBoxDictate = "Dictate",
|
||||
MainTextBoxDictate = "Dictate (key down=start recording, key up=end recording)",
|
||||
MainTextBoxUnbreak = "Unbreak text",
|
||||
MainTextBoxUnbreakNoSpace = "Unbreak without space (CJK)",
|
||||
MainTextBoxAssaIntellisense = "Show ASSA tag helper",
|
||||
|
@ -7036,6 +7036,9 @@ namespace Nikse.SubtitleEdit.Logic
|
||||
case "Settings/MainTextBoxAutoBreakFromPosAndGoToNext":
|
||||
language.Settings.MainTextBoxAutoBreakFromPosAndGoToNext = reader.Value;
|
||||
break;
|
||||
case "Settings/MainTextBoxDictate":
|
||||
language.Settings.MainTextBoxDictate = reader.Value;
|
||||
break;
|
||||
case "Settings/MainTextBoxUnbreak":
|
||||
language.Settings.MainTextBoxUnbreak = reader.Value;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user