これは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 です!






