Skip to content

Commit adfd303

Browse files
committed
Audio Transcribe view
1 parent 00e3dee commit adfd303

15 files changed

+415
-105
lines changed

DemoApp/App.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public App()
3737
builder.Services.AddSingleton<IDetectService, DetectService>();
3838
builder.Services.AddSingleton<ITextService, TextService>();
3939
builder.Services.AddSingleton<IInterpolationService, InterpolationService>();
40-
builder.Services.AddSingleton<IWhisperService, WhisperService>();
40+
builder.Services.AddSingleton<ITranscribeService, TranscribeService>();
4141

4242
_appHost = builder.Build();
4343

DemoApp/Common/PipelineModel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ public class PipelineModel : BaseModel
1212
public UpscaleModel UpscaleModel { get; init; }
1313
public DetectModel DetectModel { get; init; }
1414
public TextModel TextModel { get; init; }
15+
public TranscribeModel TranscribeModel { get; set; }
1516
}
1617
}

DemoApp/Common/TextModel.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ public enum TextModelType
6161
{
6262
Summary = 0,
6363
Phi3 = 1,
64-
Whisper = 2,
6564
Supertonic = 3
6665
}
6766
}

DemoApp/Common/TranscribeModel.cs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System.IO;
2+
using System.Linq;
3+
using System.Text.Json.Serialization;
4+
using System.Threading.Tasks;
5+
using TensorStack.Common;
6+
using TensorStack.Common.Common;
7+
using TensorStack.WPF;
8+
using TensorStack.WPF.Services;
9+
10+
namespace DemoApp.Common
11+
{
12+
public class TranscribeModel : BaseModel, IModelDownload
13+
{
14+
private bool _isValid;
15+
16+
public int Id { get; init; }
17+
public string Name { get; init; }
18+
public bool IsDefault { get; set; }
19+
public DeviceType[] SupportedDevices { get; init; }
20+
public string Version { get; set; }
21+
public int MinLength { get; init; }
22+
public int MaxLength { get; init; }
23+
public string[] UrlPaths { get; init; }
24+
25+
26+
[JsonIgnore]
27+
public string Path { get; set; }
28+
29+
[JsonIgnore]
30+
public bool IsValid
31+
{
32+
get { return _isValid; }
33+
private set { SetProperty(ref _isValid, value); }
34+
}
35+
36+
public void Initialize(string modelDirectory)
37+
{
38+
var directory = System.IO.Path.Combine(modelDirectory, Name);
39+
var modelFiles = FileHelper.GetUrlFileMapping(UrlPaths, directory);
40+
if (modelFiles.Values.All(File.Exists))
41+
{
42+
IsValid = true;
43+
Path = directory;
44+
}
45+
}
46+
47+
48+
public async Task<bool> DownloadAsync(string modelDirectory)
49+
{
50+
var directory = System.IO.Path.Combine(modelDirectory, Name);
51+
if (await DialogService.DownloadAsync($"Download '{Name}' model?", UrlPaths, directory))
52+
Initialize(modelDirectory);
53+
54+
return IsValid;
55+
}
56+
}
57+
}

DemoApp/Controls/TextModelControl.xaml.cs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public partial class TextModelControl : BaseControl
2323
private TextModel _selectedModel;
2424
private Device _currentDevice;
2525
private TextModel _currentModel;
26-
private TextModelType? _modelType;
2726

2827
/// <summary>
2928
/// Initializes a new instance of the <see cref="TextModelControl"/> class.
@@ -79,13 +78,6 @@ public ListCollectionView ModelCollectionView
7978
set { SetProperty(ref _modelCollectionView, value); }
8079
}
8180

82-
public TextModelType? ModelType
83-
{
84-
get { return _modelType; }
85-
set { SetProperty(ref _modelType, value); OnSettingsChanged(); }
86-
}
87-
88-
8981
private async Task LoadAsync()
9082
{
9183
if (!await IsModelValidAsync())
@@ -151,9 +143,6 @@ private Task OnSettingsChanged()
151143
if (_selectedDevice == null)
152144
return false;
153145

154-
if (_modelType != null && _modelType != viewModel.Type)
155-
return false;
156-
157146
return viewModel.SupportedDevices?.Contains(_selectedDevice.Type) ?? false;
158147
};
159148

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<CommonControls:BaseControl x:Class="DemoApp.Controls.TranscribeModelControl"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
7+
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
8+
xmlns:base="clr-namespace:DemoApp"
9+
xmlns:local="clr-namespace:DemoApp.Controls"
10+
xmlns:Behaviors="clr-namespace:TensorStack.WPF.Behaviors;assembly=TensorStack.WPF"
11+
xmlns:CommonControls="clr-namespace:TensorStack.WPF.Controls;assembly=TensorStack.WPF"
12+
xmlns:CommonConverters="clr-namespace:TensorStack.WPF.Converters;assembly=TensorStack.WPF"
13+
xmlns:Controls="clr-namespace:DemoApp.Controls"
14+
xmlns:Common="clr-namespace:DemoApp.Common"
15+
xmlns:Views="clr-namespace:DemoApp.Views">
16+
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:TranscribeModelControl}}}">
17+
<UniformGrid Columns="1">
18+
19+
<DockPanel>
20+
<TextBox DockPanel.Dock="Left" Text="Device" IsReadOnly="True" IsHitTestVisible="False" Width="60" FontStyle="Italic" FontSize="11" Opacity="0.7" Padding="4,2,0,0"/>
21+
<ComboBox DisplayMemberPath="Name" SelectedItem="{Binding SelectedDevice, Mode=TwoWay}" ItemsSource="{Binding Settings.Devices}" SelectionChanged="Device_SelectionChanged"/>
22+
</DockPanel>
23+
24+
<DockPanel>
25+
<DockPanel DockPanel.Dock="Right" Width="80" Height="22" >
26+
<Button x:Name="UnloadButton" DockPanel.Dock="Right" Command="{Binding UnloadCommand}" Width="22">
27+
<CommonControls:FontAwesome Icon="f00d" IconStyle="Solid" >
28+
<CommonControls:FontAwesome.Style>
29+
<Style TargetType="{x:Type CommonControls:FontAwesome}" BasedOn="{StaticResource {x:Type CommonControls:FontAwesome}}">
30+
<Setter Property="Opacity" Value="0.5" />
31+
<Style.Triggers>
32+
<DataTrigger Binding="{Binding IsEnabled, ElementName=UnloadButton}" Value="True">
33+
<Setter Property="Opacity" Value="0.7" />
34+
<Setter Property="Color" Value="{StaticResource DangerColour}" />
35+
</DataTrigger>
36+
</Style.Triggers>
37+
</Style>
38+
</CommonControls:FontAwesome.Style>
39+
</CommonControls:FontAwesome>
40+
</Button>
41+
<Button x:Name="LoadButton" Command="{Binding LoadCommand}" >
42+
<Button.Style>
43+
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
44+
<Setter Property="Content" Value="Load" />
45+
<Style.Triggers>
46+
<DataTrigger Binding="{Binding IsEnabled, ElementName=LoadButton}" Value="False">
47+
<Setter Property="Content" Value="Ready" />
48+
</DataTrigger>
49+
</Style.Triggers>
50+
</Style>
51+
</Button.Style>
52+
</Button>
53+
</DockPanel>
54+
55+
<DockPanel>
56+
<TextBox DockPanel.Dock="Left" Text="Model" IsReadOnly="True" IsHitTestVisible="False" Width="60" FontStyle="Italic" FontSize="11" Opacity="0.7" Padding="4,2,0,0"/>
57+
<ComboBox SelectedItem="{Binding SelectedModel, Mode=TwoWay}" ItemsSource="{Binding ModelCollectionView}" IsSynchronizedWithCurrentItem="True" HorizontalContentAlignment="Stretch">
58+
<ComboBox.ItemTemplate>
59+
<DataTemplate>
60+
<DockPanel>
61+
<CommonControls:FontAwesome DockPanel.Dock="Right" Icon="f111" Size="12" IconStyle="Solid" >
62+
<CommonControls:FontAwesome.Style>
63+
<Style TargetType="{x:Type CommonControls:FontAwesome}" BasedOn="{StaticResource {x:Type CommonControls:FontAwesome}}">
64+
<Setter Property="Color" Value="#10FFFFFF"/>
65+
<Style.Triggers>
66+
<DataTrigger Binding="{Binding IsValid}" Value="True">
67+
<Setter Property="Color" Value="{StaticResource AccentColour1}"/>
68+
</DataTrigger>
69+
</Style.Triggers>
70+
</Style>
71+
</CommonControls:FontAwesome.Style>
72+
</CommonControls:FontAwesome>
73+
<TextBlock Text="{Binding Name}" />
74+
</DockPanel>
75+
</DataTemplate>
76+
</ComboBox.ItemTemplate>
77+
</ComboBox>
78+
</DockPanel>
79+
</DockPanel>
80+
81+
</UniformGrid>
82+
</Grid>
83+
</CommonControls:BaseControl>
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
using DemoApp.Common;
2+
using System;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Threading.Tasks;
6+
using System.Windows;
7+
using System.Windows.Data;
8+
using TensorStack.Common;
9+
using TensorStack.WPF;
10+
using TensorStack.WPF.Controls;
11+
12+
namespace DemoApp.Controls
13+
{
14+
/// <summary>
15+
/// Interaction logic for TranscribeModelControl.xaml
16+
/// </summary>
17+
public partial class TranscribeModelControl : BaseControl
18+
{
19+
private ListCollectionView _modelCollectionView;
20+
private Device _selectedDevice;
21+
private TranscribeModel _selectedModel;
22+
private Device _currentDevice;
23+
private TranscribeModel _currentModel;
24+
25+
/// <summary>
26+
/// Initializes a new instance of the <see cref="TranscribeModelControl"/> class.
27+
/// </summary>
28+
public TranscribeModelControl()
29+
{
30+
LoadCommand = new AsyncRelayCommand(LoadAsync, CanLoad);
31+
UnloadCommand = new AsyncRelayCommand(UnloadAsync, CanUnload);
32+
InitializeComponent();
33+
}
34+
35+
public static readonly DependencyProperty SettingsProperty = DependencyProperty.Register(nameof(Settings), typeof(Settings), typeof(TranscribeModelControl), new PropertyMetadata<TranscribeModelControl>((c) => c.OnSettingsChanged()));
36+
public static readonly DependencyProperty IsSelectionValidProperty = DependencyProperty.Register(nameof(IsSelectionValid), typeof(bool), typeof(TranscribeModelControl));
37+
public static readonly DependencyProperty CurrentPipelineProperty = DependencyProperty.Register(nameof(CurrentPipeline), typeof(PipelineModel), typeof(TranscribeModelControl), new PropertyMetadata<TranscribeModelControl>((c) => c.OnPipelineChanged()));
38+
39+
public event EventHandler<PipelineModel> SelectionChanged;
40+
public AsyncRelayCommand LoadCommand { get; }
41+
public AsyncRelayCommand UnloadCommand { get; }
42+
43+
public Settings Settings
44+
{
45+
get { return (Settings)GetValue(SettingsProperty); }
46+
set { SetValue(SettingsProperty, value); }
47+
}
48+
49+
public bool IsSelectionValid
50+
{
51+
get { return (bool)GetValue(IsSelectionValidProperty); }
52+
set { SetValue(IsSelectionValidProperty, value); }
53+
}
54+
55+
public PipelineModel CurrentPipeline
56+
{
57+
get { return (PipelineModel)GetValue(CurrentPipelineProperty); }
58+
set { SetValue(CurrentPipelineProperty, value); }
59+
}
60+
61+
public Device SelectedDevice
62+
{
63+
get { return _selectedDevice; }
64+
set { SetProperty(ref _selectedDevice, value); }
65+
}
66+
67+
public TranscribeModel SelectedModel
68+
{
69+
get { return _selectedModel; }
70+
set { SetProperty(ref _selectedModel, value); }
71+
}
72+
73+
public ListCollectionView ModelCollectionView
74+
{
75+
get { return _modelCollectionView; }
76+
set { SetProperty(ref _modelCollectionView, value); }
77+
}
78+
79+
private async Task LoadAsync()
80+
{
81+
if (!await IsModelValidAsync())
82+
return;
83+
84+
_currentDevice = SelectedDevice;
85+
_currentModel = SelectedModel;
86+
CurrentPipeline = new PipelineModel
87+
{
88+
Device = _currentDevice,
89+
TranscribeModel = _currentModel
90+
};
91+
}
92+
93+
94+
private bool CanLoad()
95+
{
96+
var isReloadRequired = SelectedDevice is not null
97+
&& SelectedModel is not null
98+
&& HasCurrentChanged();
99+
100+
var isSelectionValid = !isReloadRequired;
101+
if (IsSelectionValid != isSelectionValid)
102+
IsSelectionValid = isSelectionValid;
103+
104+
return isReloadRequired;
105+
}
106+
107+
108+
private Task UnloadAsync()
109+
{
110+
_currentModel = default;
111+
CurrentPipeline = new PipelineModel
112+
{
113+
Device = _selectedDevice
114+
};
115+
116+
return Task.CompletedTask;
117+
}
118+
119+
120+
private bool CanUnload()
121+
{
122+
return _currentModel is not null;
123+
}
124+
125+
126+
private bool HasCurrentChanged()
127+
{
128+
return _currentDevice != SelectedDevice
129+
|| _currentModel != SelectedModel;
130+
}
131+
132+
133+
private Task OnSettingsChanged()
134+
{
135+
ModelCollectionView = new ListCollectionView(Settings.TranscribeModels);
136+
ModelCollectionView.Filter = (obj) =>
137+
{
138+
if (obj is not TranscribeModel viewModel)
139+
return false;
140+
141+
if (_selectedDevice == null)
142+
return false;
143+
144+
return viewModel.SupportedDevices?.Contains(_selectedDevice.Type) ?? false;
145+
};
146+
147+
SelectedDevice = Settings.DefaultDevice;
148+
return Task.CompletedTask;
149+
}
150+
151+
152+
private void Device_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
153+
{
154+
ModelCollectionView?.Refresh();
155+
if (ModelCollectionView is not null)
156+
{
157+
SelectedModel = ModelCollectionView.Cast<TranscribeModel>().FirstOrDefault(x => x == _currentModel || x.IsDefault);
158+
}
159+
}
160+
161+
162+
private Task OnPipelineChanged()
163+
{
164+
SelectedDevice = CurrentPipeline?.Device ?? Settings.DefaultDevice;
165+
if (CurrentPipeline?.TranscribeModel is not null)
166+
{
167+
SelectedModel = CurrentPipeline.TranscribeModel;
168+
}
169+
170+
_currentDevice = CurrentPipeline?.Device;
171+
_currentModel = CurrentPipeline?.TranscribeModel;
172+
SelectionChanged?.Invoke(this, CurrentPipeline);
173+
return Task.CompletedTask;
174+
}
175+
176+
177+
private async Task<bool> IsModelValidAsync()
178+
{
179+
if (_selectedModel is null)
180+
return false;
181+
182+
if (_selectedModel.IsValid)
183+
return true;
184+
185+
return await _selectedModel.DownloadAsync(Path.Combine(Settings.DirectoryModel, "Transcribe"));
186+
}
187+
}
188+
}

0 commit comments

Comments
 (0)