Add vosk, Naudio
This commit is contained in:
1
.idea/.idea.VisionAsist/.idea/avalonia.xml
generated
1
.idea/.idea.VisionAsist/.idea/avalonia.xml
generated
@@ -4,6 +4,7 @@
|
|||||||
<option name="projectPerEditor">
|
<option name="projectPerEditor">
|
||||||
<map>
|
<map>
|
||||||
<entry key="VisionAsist/Views/MainWindow.axaml" value="VisionAsist/VisionAsist.csproj" />
|
<entry key="VisionAsist/Views/MainWindow.axaml" value="VisionAsist/VisionAsist.csproj" />
|
||||||
|
<entry key="VisionAsist/Views/Settings.axaml" value="VisionAsist/VisionAsist.csproj" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
2
VisionAsist.sln.DotSettings.user
Normal file
2
VisionAsist.sln.DotSettings.user
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APorcupine_002Ecs_002Fl_003AC_0021_003FUsers_003Fmarin_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F395b25d8175b43798becf32fa73896954c00_003Fa6_003F28640b1d_003FPorcupine_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
||||||
35
VisionAsist/Models/Core.cs
Normal file
35
VisionAsist/Models/Core.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
namespace VisionAsist.Models;
|
||||||
|
|
||||||
|
public class Core
|
||||||
|
{
|
||||||
|
public static TrigerCore triger = new();
|
||||||
|
public static string TextAsist;
|
||||||
|
static Core()
|
||||||
|
{
|
||||||
|
Console.OutputEncoding = System.Text.Encoding.UTF8;
|
||||||
|
Console.InputEncoding = System.Text.Encoding.UTF8;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static void StartListing()
|
||||||
|
{
|
||||||
|
// Подписываемся на событие новых слов
|
||||||
|
triger.OnRecognized += word =>
|
||||||
|
{
|
||||||
|
Console.OutputEncoding = System.Text.Encoding.UTF8;
|
||||||
|
Console.InputEncoding = System.Text.Encoding.UTF8;
|
||||||
|
Console.WriteLine(word); // печатаем сразу, как распознано
|
||||||
|
TextAsist = triger.RecognizedText;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Запускаем запись
|
||||||
|
triger.StartRecording();
|
||||||
|
}
|
||||||
|
|
||||||
|
static public async void StopListing ()
|
||||||
|
{
|
||||||
|
triger.StopRecording();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
6
VisionAsist/Models/Selector.cs
Normal file
6
VisionAsist/Models/Selector.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace VisionAsist.Models;
|
||||||
|
|
||||||
|
public class Selector
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
76
VisionAsist/Models/TrigerCore.cs
Normal file
76
VisionAsist/Models/TrigerCore.cs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using Vosk;
|
||||||
|
using System.Text.Json;
|
||||||
|
using NAudio.Wave;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Threading;
|
||||||
|
|
||||||
|
namespace VisionAsist.Models;
|
||||||
|
|
||||||
|
public class TrigerCore
|
||||||
|
{
|
||||||
|
|
||||||
|
private WaveInEvent? _waveIn;
|
||||||
|
private Model? _model;
|
||||||
|
private VoskRecognizer? _rec;
|
||||||
|
private readonly object _voskLock = new();
|
||||||
|
public string RecognizedText { get; private set; } = "";
|
||||||
|
|
||||||
|
|
||||||
|
public TrigerCore()
|
||||||
|
{
|
||||||
|
string VoskPath = Path.Combine(AppContext.BaseDirectory, "models/Vosk/");
|
||||||
|
if (!Directory.Exists(VoskPath))
|
||||||
|
throw new DirectoryNotFoundException($"Модель не найдена по пути: {VoskPath}");
|
||||||
|
|
||||||
|
_model = new Model(VoskPath);
|
||||||
|
_rec = new VoskRecognizer(_model, 16000.0f);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartRecording()
|
||||||
|
{
|
||||||
|
if (_waveIn != null || _rec == null) return;
|
||||||
|
|
||||||
|
_waveIn = new WaveInEvent { WaveFormat = new WaveFormat(16000, 1) };
|
||||||
|
_waveIn.DataAvailable += OnDataAvailable;
|
||||||
|
_waveIn.StartRecording();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void StopRecording()
|
||||||
|
{
|
||||||
|
_waveIn?.StopRecording();
|
||||||
|
_waveIn?.Dispose();
|
||||||
|
_waveIn = null;
|
||||||
|
}
|
||||||
|
public event Action<string>? OnRecognized;
|
||||||
|
|
||||||
|
private void OnDataAvailable(object? sender, WaveInEventArgs e)
|
||||||
|
{
|
||||||
|
lock (_voskLock)
|
||||||
|
{
|
||||||
|
if (_rec != null && _rec.AcceptWaveform(e.Buffer, e.BytesRecorded))
|
||||||
|
{
|
||||||
|
var json = _rec.Result();
|
||||||
|
using var doc = JsonDocument.Parse(json);
|
||||||
|
var result = doc.RootElement.GetProperty("text").GetString();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(result))
|
||||||
|
{
|
||||||
|
RecognizedText += result + " ";
|
||||||
|
OnRecognized?.Invoke(result); // уведомляем подписчиков
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Stop()
|
||||||
|
{
|
||||||
|
StopRecording();
|
||||||
|
_rec?.Dispose();
|
||||||
|
_model?.Dispose();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ sealed class Program
|
|||||||
[STAThread]
|
[STAThread]
|
||||||
public static void Main(string[] args) => BuildAvaloniaApp()
|
public static void Main(string[] args) => BuildAvaloniaApp()
|
||||||
.StartWithClassicDesktopLifetime(args);
|
.StartWithClassicDesktopLifetime(args);
|
||||||
|
|
||||||
// Avalonia configuration, don't remove; also used by visual designer.
|
// Avalonia configuration, don't remove; also used by visual designer.
|
||||||
public static AppBuilder BuildAvaloniaApp()
|
public static AppBuilder BuildAvaloniaApp()
|
||||||
=> AppBuilder.Configure<App>()
|
=> AppBuilder.Configure<App>()
|
||||||
|
|||||||
@@ -1,6 +1,45 @@
|
|||||||
namespace VisionAsist.ViewModels;
|
using System;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using VisionAsist.Models;
|
||||||
|
namespace VisionAsist.ViewModels;
|
||||||
|
|
||||||
public partial class MainWindowViewModel : ViewModelBase
|
public partial class MainWindowViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
public string Greeting { get; } = "Welcome to Avalonia!";
|
[ObservableProperty]
|
||||||
|
private bool isListening;
|
||||||
|
[ObservableProperty]
|
||||||
|
private string recognizedtext;
|
||||||
|
private Action<string>? _coreHandler;
|
||||||
|
|
||||||
|
partial void OnIsListeningChanged(bool value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
Core.StartListing();
|
||||||
|
|
||||||
|
// Сохраняем ссылку на обработчик
|
||||||
|
_coreHandler = word =>
|
||||||
|
{
|
||||||
|
|
||||||
|
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||||
|
{
|
||||||
|
Recognizedtext = Core.TextAsist;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Core.triger.OnRecognized += _coreHandler;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Core.StopListing();
|
||||||
|
|
||||||
|
// Правильная отписка
|
||||||
|
if (_coreHandler != null)
|
||||||
|
{
|
||||||
|
Core.triger.OnRecognized -= _coreHandler;
|
||||||
|
_coreHandler = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
6
VisionAsist/ViewModels/SettingsViewModel.cs
Normal file
6
VisionAsist/ViewModels/SettingsViewModel.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace VisionAsist.ViewModels;
|
||||||
|
|
||||||
|
public class SettingsViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using System;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
namespace VisionAsist.ViewModels;
|
namespace VisionAsist.ViewModels;
|
||||||
|
|
||||||
public abstract class ViewModelBase : ObservableObject
|
public partial class ViewModelBase : ObservableObject
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -7,14 +7,30 @@
|
|||||||
x:Class="VisionAsist.Views.MainWindow"
|
x:Class="VisionAsist.Views.MainWindow"
|
||||||
x:DataType="vm:MainWindowViewModel"
|
x:DataType="vm:MainWindowViewModel"
|
||||||
Icon="/Assets/avalonia-logo.ico"
|
Icon="/Assets/avalonia-logo.ico"
|
||||||
Title="VisionAsist">
|
Title="VisionAsist" Height="400" Width="600">
|
||||||
|
|
||||||
<Design.DataContext>
|
<Design.DataContext>
|
||||||
<!-- This only sets the DataContext for the previewer in an IDE,
|
<!-- This only sets the DataContext for the previewer in an IDE,
|
||||||
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
||||||
<vm:MainWindowViewModel/>
|
<vm:MainWindowViewModel/>
|
||||||
</Design.DataContext>
|
</Design.DataContext>
|
||||||
|
<StackPanel>
|
||||||
<TextBlock Text="{Binding Greeting}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
<StackPanel Orientation="Horizontal" Margin="10">
|
||||||
|
<Button Content="Настройки"/>
|
||||||
|
<ToggleButton IsChecked="{Binding IsListening, Mode=TwoWay}"
|
||||||
|
Content="Запуск асистента"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<ScrollViewer Height="350" CornerRadius="5" Background="Black">
|
||||||
|
<TextBlock Text="{Binding Recognizedtext}"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Padding="10"
|
||||||
|
/>
|
||||||
|
</ScrollViewer>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Window>
|
</Window>
|
||||||
|
|||||||
17
VisionAsist/Views/Settings.axaml
Normal file
17
VisionAsist/Views/Settings.axaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<Window xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:vm="using:VisionAsist.ViewModels"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="VisionAsist.Views.Settings"
|
||||||
|
x:DataType="vm:SettingsViewModel"
|
||||||
|
Icon="/Assets/avalonia-logo.ico"
|
||||||
|
Title="VisionAsist" Height="400" Width="600">
|
||||||
|
<Design.DataContext>
|
||||||
|
<!-- This only sets the DataContext for the previewer in an IDE,
|
||||||
|
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
||||||
|
<vm:MainWindowViewModel/>
|
||||||
|
</Design.DataContext>
|
||||||
|
|
||||||
|
</Window>
|
||||||
13
VisionAsist/Views/Settings.axaml.cs
Normal file
13
VisionAsist/Views/Settings.axaml.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
|
||||||
|
namespace VisionAsist.Views;
|
||||||
|
|
||||||
|
public partial class Settings : Window
|
||||||
|
{
|
||||||
|
public Settings()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Models\"/>
|
|
||||||
<AvaloniaResource Include="Assets\**"/>
|
<AvaloniaResource Include="Assets\**"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -22,6 +21,8 @@
|
|||||||
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
||||||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1"/>
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||||
|
<PackageReference Include="NAudio" Version="2.3.0" />
|
||||||
|
<PackageReference Include="Vosk" Version="0.3.38" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Reference in New Issue
Block a user