こんにちは。エクセルソフトの田淵です。
Xamarin.Forms for Windows でストアアプリにチャレンジしています。
Accessing Native Features via the DependencyService - Xamarin
で Text To Speech (以下 TTS) の機能を Dependency Service で使用するサンプルがあるので、それを Windows ストアで実装しました。
Windows ストアアプリで TTS を使用するには
WinRT/Metro TIPS:Windows 8.1の新機能、テキスト読み上げを利用するには?[Windows 8.1ストア・アプリ開発] - @IT
と
WinRT/Metro TIPS:アプリに埋め込んだ効果音を鳴らすには?[Win 8/WP 8] - @IT
を参考に、
using XF_Slider.Windows81; using Xamarin.Forms; using Windows.Media.SpeechSynthesis; using Windows.UI.Xaml.Controls; [assembly: Dependency(typeof(TextToSpeech_Windows81))] namespace XF_Slider.Windows81 { class TextToSpeech_Windows81 : ITextToSpeech { public TextToSpeech_Windows81() { } public async void Speak(string text) { SpeechSynthesisStream stream; // MediaElement をインスタンス化 var media = new MediaElement(); // SpeechSynthesizerオブジェクトを作る using (var synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer()) { // プレーン・テキストから合成音声ストリームを生成する stream = await synth.SynthesizeTextToStreamAsync(text); } // ストリームをMediaElement のインスタンスに渡して再生させる media.SetSource(stream, stream.ContentType); media.Play(); } } }
で大丈夫でした。半日くらい悩んだんですが、良かったです。
Xamarin 気になった方は
是非 ダウンロード(直接) / ダウンロード(弊社経由) して触ってみてください。 学習用リソース や JXUG リンクページ に参考資料を纏めてますので併せてどうぞ。
以上です。
以下は色んなやり方があるからコントロールの使い方をまずは調べろよ?っていう自分メモとして残しておきます。
MainPage.xaml
に <MediaElement x:Name="mediaElement1" Volume="100" />
を追加して… フムフム
コードビハインド MainPage.xaml.cs
に
string text = ……省略……; // 読み上げるテキスト // 合成した音声を受け取るストリーム Windows.Media.SpeechSynthesis.SpeechSynthesisStream stream; // SpeechSynthesizerオブジェクトを作る using (var synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer()) { // プレーン・テキストから合成音声ストリームを生成する stream = await synth.SynthesizeTextToStreamAsync(text); } // ストリームをMediaElementコントロールに渡して、再生させる this.mediaElement1.SetSource(stream, stream.ContentType); this.mediaElement1.Play();
を書くと。フムフム
でも、Xamarin.Forms for Windows で Dependency Service を使うので、私は Froms プロジェクトに ITextToSpeech.cs
を、 Windows ストアプロジェクトに TextToSpeech_Windows81.cs
を追加して、そこに Dependency の記述を追加しないと行けなくてですね。
ITextToSpeech.cs はこんな感じで
public interface ITextToSpeech { void Speak (string text); }
TextToSpeech_Windows81.cs はこんな感じ
using XXXXX.Windows81; using Xamarin.Forms; using Windows.Media.SpeechSynthesis; [assembly: Dependency(typeof(TextToSpeech_Windows81))] namespace XXXXX.Windows81 { class TextToSpeech_Windows81 : ITextToSpeech { public TextToSpeech_Windows81() { } public async void Speak(string text) { // テスト1 Windows Phone のをそのまま持ってきてみる。 // Windows.Phone.Speech.Synthesis には SpeakTextAsync() メソッドがあるが、Windows.Media.SpeechSynthesis には存在しない //SpeechSynthesizer synth = new SpeechSynthesizer(); //await synth.SpeakTextAsync(text); // テスト2 WinRT/Metro TIPS:Windows 8.1の新機能、テキスト読み上げを利用するには?[Windows 8.1ストア・アプリ開発] - @IT // http://www.atmarkit.co.jp/ait/articles/1311/07/news088.html // をそのまま使ってみる。 SpeechSynthesisStream stream; // SpeechSynthesizerオブジェクトを作る using (var synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer()) { // プレーン・テキストから合成音声ストリームを生成する stream = await synth.SynthesizeTextToStreamAsync(text); } // ストリームをMediaElementコントロールに渡して、再生させる this.mediaElement1.SetSource(stream, stream.ContentType); this.mediaElement1.Play(); } } }
'XXXXX.Windows81.TextToSpeech_Windows81' に 'mediaElement1' の定義が含まれておらず、型 'XXXXX.Windows81.TextToSpeech_Windows81' の最初の引数を受け付ける拡張メソッドが見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足しています。
まぁそりゃそうですよね。コードビハインドじゃないし。
XXXXX.Windows81.MainPage.mediaElement1 って参照すればいいのかしら?とやってみたところ、
'XXXXX.Windows81.MainPage.mediaElement1' はアクセスできない保護レベルになっています。
ウムム…
で、ウチの技術に助けを求めてみたところ
- MediaElement に x:FieldModifier="public" の属性を追加してみる :
静的でないフィールド、メソッド、またはプロパティ 'XXXXX.Windows81.MainPage.mediaElement1' で、オブジェクト参照が必要です
エラーでダメでした - Forms の ITextToSpeech インターフェイスで string を渡していますが、MediaElement ごと渡してしまう? : PCL だから Windows.Media.SpeechSynthesis を using できずダメでした
という感じでどうやら Custom Renderer を使って、Windows ストアの場合は MediaElement を配置してあげないとダメじゃないですかね?という所に落ち着きました。
何か良いアイディアないですかね…?
以上です。。