環境
- Windows 11
- Visual Studio 2022
- .NET 7
テキスト情報を読み上げるUWPアプリケーションを作成する や テキスト情報を読み上げるWindows Formsアプリケーションを作成する でテキストを読み上げるアプリケーションを作成していたけど、 GitHub にリポジトリーを作成していなかった事、手軽に実行したい事(UWP だとインストールされてしまうし、 .NET Framework より .NET で作った方が今後は良さそうだし)を理由に WPF 版として再度作ってみた。
今回作成したサンプルコードは https://github.com/nakamurakko/WpfTextReader を参照。
プロジェクト作成
Visual Studio を起動して、 WPF アプリケーションのプロジェクトを新規作成する。 プロジェクトに下記 NuGet パッケージを追加する。
パッケージ | 説明 |
---|---|
System.Speech | 音声出力に必要なパッケージ。使用している SpeechSynthesizer クラスのドキュメントが .NET Framework 4.8.1 で止まっているので、 .NET 7 で使用すべきパッケージではないかもしれない。 |
CommunityToolkit.Mvvm | MVVM の実装をサポートするパッケージ。サンプルでは ObservableProperty、 RelayCommand を使用している。 |
ViewModel 実装
MainView 用 の ViewModel を用意し、システムで利用可能な音声一覧、選択した音声用のプロパティを用意する。
/// <summary> /// 音声一覧。 /// </summary> [ObservableProperty] private ObservableCollection<InstalledVoice> _voices = new ObservableCollection<InstalledVoice>(); /// <summary> /// 選択した音声。 /// </summary> [ObservableProperty] private InstalledVoice _selectedVoice;
コンストラクターで、 SpeechSynthesizer.GetInstalledVoices() を使って音声一覧を取得して、1つ目を選択状態にしておく。
public MainWindowViewModel() { using (SpeechSynthesizer synthesizer = new SpeechSynthesizer()) { // 利用可能な音声を一覧に追加する。 foreach (InstalledVoice voice in synthesizer.GetInstalledVoices()) { this.Voices.Add(voice); } } // 音声の1つ目を選択状態にする。 this.SelectedVoice = this.Voices.FirstOrDefault(); }
テキストを読み上げるコマンドを用意する。
/// <summary> /// テキストを読み上げる。 /// </summary> [RelayCommand] private void ReadText() { if ((this.SelectedVoice == null) || string.IsNullOrWhiteSpace(this.TargetText)) { return; } Task.Run(() => { using (SpeechSynthesizer synthesizer = new SpeechSynthesizer()) { // 選択音声を設定。 synthesizer.SelectVoice(this.SelectedVoice.VoiceInfo.Name); // テキストを読み上げる。 synthesizer.Speak(this.TargetText); } }); }
SpeechSynthesizer クラス の説明に、
とあるため、メソッド内で SpeechSynthesizer
をインスタンス化して、かつテキスト読み上げ中のアプリケーションフリーズを避けるには Task.Run()
で SpeechSynthesizer.Speak() を呼び出すのが良いと思う。
View 実装
ViewModel の各機能を View に紐づければ完成。
<Window x:Class="WpfTextReader.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfTextReader" mc:Ignorable="d" xmlns:viewModels="clr-namespace:WpfTextReader" Title="{Binding Title}" d:DataContext="{d:DesignInstance viewModels:MainWindowViewModel}" d:Height="400" d:Width="600"> <Window.DataContext> <local:MainWindowViewModel /> </Window.DataContext> <Grid> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid Grid.Row="0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <!-- ①テキストを読み上げるコマンドを呼び出すボタン。 --> <Button Grid.Column="0" Content="読み上げ" Command="{Binding ReadTextCommand}" /> <TextBlock Grid.Column="1" HorizontalAlignment="Center" Text="音声選択" VerticalAlignment="Center" /> <!-- ②音声を選択するコンボボックス。 --> <ComboBox Grid.Column="2" ItemsSource="{Binding Voices}" SelectedItem="{Binding SelectedVoice}"> <ComboBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding VoiceInfo.Name}" /> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> </Grid> <!-- ③読み上げたいテキスト。 --> <TextBox Grid.Row="1" Text="{Binding TargetText}" TextWrapping="Wrap" /> </Grid> </Window>
実行結果
読ませたいテキストを入力し、読み上げボタンをクリックすれば、 Windows にインストールされている音声で読み上げてくれる。
フランス語など別言語の音声を使いたい場合、「設定 > 時刻と言語 > 音声認識」で音声を追加すれば可能。