これはVOYAGE GROUP Advent Calendar 2015の13日目の記事です。
今日はiPhoneを使った音声認識の話です。
スターウォーズ!
今月の18日、いよいよスターウォーズの最新作、「フォースの覚醒」が公開されますね。 前作から10年、懐かしいキャラにも会えるし、新しいキャラの登場も楽しみです。
せっかくなので、もう一度6つのエピソードを見直してみましたが、スターウォーズシリーズは何回見ても飽きない面白さがありますね。 今見てみると、前半シリーズと後半シリーズの物語の複雑さが違うのもまた面白かったりします。
個人的には、先日亡くなったクリストファー・リー演じるドゥークー伯爵を見て、しんみりしたりしていました。
I love you. I know.
さて、スターウォーズの名シーンとしてよくあげられるのがこちらのシーン。
エピソード5「帝国の逆襲」で、ハリソン・フォード演じるハン・ソロが、急速冷凍されてしまう直前。 恋人のレイア姫の "I love you."(愛してるわ)に答えて、"I know."(知ってるさ)と答えるハン・ソロ。 それまで言葉に出さなかったお互いの気持ちが、死を前に初めて言葉になり、小さい頃にこのシーンを見て、大人の恋だなぁ……!と思ったのを思い出します。
ちなみに、これと逆のシーンがエピソード6の「ジェダイの逆襲」に出てくるんですよね。 (そっちのシーンでは、ハン・ソロの「I love you.」に、レイア姫が「I know.」って答えるんです。)
せっかくクリスマスだし、ここは、私もハン・ソロに "I know."って言って欲しい! というわけで、さっそく実装してみました。
音声認識と音声出力
iOSの音声認識機能として、Siriがあるんですが、SiriのAPIは公開されていないので、サードパーティー製のライブラリを使うことにしました。
いくつか見てみたところ、OpenEarsというライブラリがよさそうなので、それを使ってみることに。 (shuさんの記事を参考にさせていただきました。)
音声出力も実装する必要があります。 iOSのAVSpeechsyntheを使えばSiriと同じ合成音声で「I love you」と答えてもらうことはできます。(AVSpeechSynthesizer による音声読み上げ)
でも、Siriじゃ意味がないんです!ハリソン・フォードじゃないと!
というわけで、ここは、ハリソン・フォードの動画を再生することにしました。
OpenEars
まず新規プロジェクトを作成、OpenEarsのサイトからダウンロードしたフレームワークのSlt.frameworkとOpenEars.frameworkをプロジェクトに追加。 AcousticModelEnglish.bundleも追加しておきます。
ViewControllerにOEEventsObserverの変数を追加し、viewDidLoadで初期化処理を行います。 ここで、認識したい文字列を一緒に指定しておきます。
下記の場合には、"I love you."と"He told me you killed."の2つの文章を指定してあります。
class ViewController: UIViewController,OEEventsObserverDelegate { let observer : OEEventsObserver = OEEventsObserver() override func viewDidLoad() { super.viewDidLoad() observer.delegate = self let modelgenerator : OELanguageModelGenerator = OELanguageModelGenerator() let words = [ "I love you.", "He told me you killed."] let modelname = "NameIWantForMyLanguageModelFiles" let model = OEAcousticModel.pathToModel("AcousticModelEnglish") modelgenerator.generateLanguageModelFromArray(words, withFilesNamed: modelname, forAcousticModelAtPath: model) let languagepath = modelgenerator.pathToSuccessfullyGeneratedLanguageModelWithRequestedName("NameIWantForMyLanguageModelFiles") let dictionarypath = modelgenerator.pathToSuccessfullyGeneratedDictionaryWithRequestedName("NameIWantForMyLanguageModelFiles") try! OEPocketsphinxController.sharedInstance().setActive(true) OEPocketsphinxController.sharedInstance().startListeningWithLanguageModelAtPath( languagepath, dictionaryAtPath: dictionarypath, acousticModelAtPath: model, languageModelIsJSGF: false) }
上記のコードの最終行で音声認識を始めます。
ライブラリによって単語や文章が認識されると、ViewControllerのかきのメソッドが呼ばれます。(事前にViewControllerをOEEventsObserverのdelegateに設定しておきます。)
これで、I love you.
に反応してくれる部分までできました。
func pocketsphinxDidReceiveHypothesis(hypothesis: String!, recognitionScore: String!, utteranceID: String!) { if hypothesis == "I love you." { // ここでハン・ソロが答えてくれるはず。 } }
動画再生
さて、次は動画再生。
動画再生ってMPMoviePlayerControllerだっけ?と思っていたら、いつの間にかこのクラスdeprecatedされてたんですね。 今はAVPlayerViewControllerを使えということだったので、おとなしく従って、こんな感じに。
let avViewCon = AVPlayerViewController() avViewCon.showsPlaybackControls = false let movieurl = NSBundle.mainBundle().pathForResource("iamfather", ofType: "m4v") avViewCon.player = AVPlayer(URL: NSURL(string: movieurl!)! ) avViewCon.player?.play() avViewCon.view.frame = CGRectMake(0,0,300,300) view.addSubview(avViewCon.view)
さっそく起動して、iPhoneに向かってしつこくI love you.
を繰り返してみました。
無事ハン・ソロからI know
のお返事が。
やったあ!
(あ、このビデオはネタバレを含むので、スターウォーズシリーズの旧6部作をまだ見てない人は見ないでくださいね。)
ところでSiriさんは……
ところで、Siriの音声認識機能は開発者に公開されていないので、実装に使うことはできませんが、SiriにI love you.
って言ったらどうなるかな?と思い、さっそくSiri先生にも聞いてみました。
うーん、つれないですね。
日本語だからダメなのかもしれない、と思って、Siriの言語を英語にしてみたところ……
というわけで、別に自分でアプリを作らなくても、同じことができることがわかりました。 さすがApple。
明日は頼れる新人、@sakmtech です!