Help us understand the problem. What is going on with this article?

【UiPath】しゃべるアクティビティを作る

More than 1 year has passed since last update.

引き続きカスタムアクティビティ作りで遊んでみます。
前回>[カスタムアクティビティのプロパティを見える化する]

せっかくロボットが人間の代わりに働いてくれるので、
 :computer:「今からXXXX作業を始めます」
とか喋ってから作業をしてくれるとそれっぽいよね。
という事で、指定したテキスト通りにしゃべってくれるアクティビティを作ります。

喋るアクティビティは既にV.Vaidyaという方が VVaidya.TextToSpeechActivities として公開してるけど、
日本語テキストに対応していないので自分で作るしかないのです。

事前準備:Speech Platform 11の用意(Win7の場合)

恥ずかしながら私のPCはまだWindows7で、Win7は標準で日本語の音声合成機能が無いようなので
こちらのサイトを参考に、Microsoft Speech Platform 11+HarukaをPCに導入します。
※このサイト、"簡単インストーラー"なるものまで用意されていたので利用させていただきました。

install.png

アクティビティデザイナーの実装

アクティビティデザイナーの実装の仕方は前回 前々回で触れているのでざっと流します。

まずMS Expression Designerでアイコン絵を描いて、
"XAML WPF リソースディクショナリ"形式でXAMLファイルをエクスポート。
speechicon.png

次にVisual Studioで新規にアクティビティデザイナー(SpeechTextDesigner.xaml)をプロジェクトに追加し、
XAMLペインに<sap:ActivityDesigner.Icon>と<DrawingBrush>、その中にExpression Designerから
エクスポートしたXAMLファイルの中の<DrawingBrush.Drawing>タグ以降を貼り付ける。
最後にExpressionTextBoxのくだりを追加すればアクティビティデザイナー側は完了。

とまぁ文章で説明するとわかりにくいので、↓に全文載っけました。

SpeechTextDesigner.xaml
<sap:ActivityDesigner x:Class="Umemaru.SpeechTextDesigner"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:s="clr-namespace:System;assembly=mscorlib"
    xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
    xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"
    xmlns:sapc="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation">

    <sap:ActivityDesigner.Icon>
        <DrawingBrush>
            <DrawingBrush.Drawing>
                <DrawingGroup>
                    <DrawingGroup.Children>
                        ~中略~
                    </DrawingGroup.Children>
                </DrawingGroup>
            </DrawingBrush.Drawing>
        </DrawingBrush>
    </sap:ActivityDesigner.Icon>

    <sap:ActivityDesigner.Resources>
        <ResourceDictionary>
            <sapc:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter" />
        </ResourceDictionary>
    </sap:ActivityDesigner.Resources>

    <DockPanel>
        <sapv:ExpressionTextBox OwnerActivity="{Binding Path=ModelItem}" ExpressionType="s:String" 
            HintText="Text must be quoted." MaxLines="1"
            Expression="{Binding Path=ModelItem.Text, Converter={StaticResource ArgumentToExpressionConverter}, 
            ConverterParameter=In, Mode=TwoWay}"/>
    </DockPanel>

</sap:ActivityDesigner>

Speech Object Libraryの参照設定とnupkg化の注意点

アクティビティのコードを書く前に、プロジェクトにSpeech Object Libraryを参照登録します。

まずプロジェクトの参照設定-COMに"Microsoft Speech Object Library 11.0"を追加。
com.png

追加すると参照ツリーの下に"SpeechLib"が出てくるので、"相互運用型の埋め込み"をFalseに変更。
 property.png

※このプロパティはデフォルトでTrue(=アクティビティのDLLに埋め込む)になってますが、
それだとnupkg化してUiPathに食わせても、アクティビティのTreeに出てきません。
System.BadImageFormatException: Format of the executable (.exe) or library (.dll) is invalid.
というエラーがUiPath Studioのログ(Studio.log)に出力されます。
つまりSpeechLibを埋め込んだDLLはUiPathが正常に食えないようです。

False(=埋め込まない)にしてビルドすると、SpeechLibの正体であるInterop.SpeechLib.dllが
プロジェクトのDLLとは別に出力されます。
dll.png

nupkg化する際にこのInterop.SpeechLib.dllもlibに追加する必要があります。
ここが非常に大事なポイントです。
pupkgka.png

最初はこれに気づかずにプロジェクトのDLLだけでnupkg化したら、実行時に
"Interop.SpeechLib.dll"が無い、とエラーになりました。
UiPath的にはDLLに埋め込むのはダメだけど、nupkgには含める必要があるという事です。
error.png

アクティビティクラスの実装

順序が逆になりましたが、肝心のアクティビティクラスを実装します。
ここでもこのサイトのお世話になります。
Windows form版のサンプルコードを公開されていたので、それを参考にします。

参照登録したライブラリSpeechLibをusingして、そのオブジェクト群を使って喋らせます。

SpeechText.cs
using System;
using System.Activities;
using System.ComponentModel;
using SpeechLib;

namespace Umemaru.Activities
{
    [Category("Umemaru.Activities")]
    [DisplayName("Speech Text")]
    [Designer(typeof(SpeechTextDesigner))]    
    public class SpeechText : CodeActivity
    {
        SpVoice speaker;// 音声合成オブジェクト
        ISpeechObjectTokens info;// 音声情報

        [Category("Input")]
        [RequiredArgument]
        public InArgument<string> Text { get; set; }

        protected override void Execute(CodeActivityContext context)
        {
            speaker = new SpVoice();
            info = speaker.GetVoices("", "");
            speaker.Voice = info.Item(0);// Haruka
            speaker.Volume = 100;// 音量の設定(0~100)
            speaker.Rate = -1;// 速度の設定(-10~10、0だとちょっと速い)

            speaker.Speak(Text.Get(context), SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak);
        }
    }
}

ここまでやれば、無事にSpeech Textアクティビティが実行できます。ちゃんと漢字も喋ってくれます。
(しかし声がロボットっぽくないんだよなぁ…昔の勇者ロボみたいなのがいいんだけど)
tree.png speech.png

使いどころとしては、ワークフローの先頭だけでなくエラー時の対応にも使えるかな。
例えばSelectorで指定したボタンが見つからず押せない時は、try~catchのExceptionで
 :computer:「だっ誰かっ、誰か俺の代わりに[登録]ボタンを見つけて押してくれぇぇ!」
と叫ばせて人を呼ぶとか。


今回はここまで。

今はWin7マシンなのでMicrosoft Speech Platform 11を追加インストールして使いましたが、
Win8以降はデフォルトで違う音声合成技術が搭載されているそうなので、
次にWin10マシンに替えたらそっちを使うように作り直さなきゃな・・・

その時はWin10向けの内容で記事追記します。

UmegayaRollcake
UiPath Academyの外堀を浅く埋める形でUiPathネタを書いていこうと思ってます。
https://www.youtube.com/channel/UCdo1xFEK-wRiVIQDs2cdvUg
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away