[watchOS 3] AVSpeechSynthesizer による合成音声再生について

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは。モバイルアプリサービス部の平屋です。

watchOS 3 の API の差分を解説している資料「watchOS 3.0 API Diffs」によると、watchOS 3 からは AVFoundation framework を使えるようになったようです。

本記事では、AVFoundation framework の AVSpeechSynthesizer を使用して watchOS 3 アプリ上で合成音声を再生する実装を紹介していきます。

検証環境

  • Xcode Version 8.1
  • iPhone 7, iOS 10.1
  • Apple Watch, watchOS 3.1

実装

さっそく合成音声を生成する実装を紹介していきます。

「iOS App with WatchKit App」テンプレートからプロジェクトを作成し、WatchKit Extension の InterfaceController にコードを追加していきます。

AVSpeechUtterance と AVSpeechSynthesizer

合成音声再生を行うのに最低限必要なのは、AVSpeechUtterance を作成し、AVSpeechSynthesizerspeak(_:) メソッドを呼ぶことだけです。

AVSpeechUtterance は読み上げるテキストや話す速さなどの設定を保持するクラスです。

AVSpeechSynthesizer は合成音声の再生を行うためのクラスです。内部に AVSpeechUtterance のキューを持っていて speak(_:) メソッドを呼ぶと引数に指定した AVSpeechUtterance がキューに入ります。キューが空の場合はすぐに再生されます。

import WatchKit
import Foundation
import AVFoundation

class InterfaceController: WKInterfaceController {

    let synthesizer = AVSpeechSynthesizer()

    // ...

    @IBAction func didTapButton() {
        // テキストを指定して、AVSpeechUtterance を作成
        let utterance = AVSpeechUtterance(string: "The AVSpeechSynthesizer class produces synthesized speech.")
        // 言語を指定して、声を設定
        utterance.voice = AVSpeechSynthesisVoice(language: "en-US")
        // 話す速度を設定
        utterance.rate = AVSpeechUtteranceMinimumSpeechRate
        // 声の高さを設定
        utterance.pitchMultiplier = 1.0

        // AVSpeechSynthesizer の キューに AVSpeechUtterance をセットする
        // キューが空の場合は、発声がすぐに始まる
        self.synthesizer.speak(utterance)
    }
}

AVSpeechSynthesizerDelegate

AVSpeechSynthesizerDelegate のメソッドを実装すれば、再生開始のイベントなどをハンドリングできます。

class InterfaceController: WKInterfaceController {

    // ...

    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

        self.synthesizer.delegate = self
    }

    // ...
}

extension InterfaceController: AVSpeechSynthesizerDelegate {
    // 再生開始時に呼ばれる
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer,
                           didStart utterance: AVSpeechUtterance) {
        print("didStart!")
    }

    // 再生終了時に呼ばれる
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer,
                           didFinish utterance: AVSpeechUtterance) {
        print("didFinish!")
    }

    // 再生中のテキスト範囲を取得
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer,
                           willSpeakRangeOfSpeechString characterRange: NSRange,
                           utterance: AVSpeechUtterance) {
        let word = (utterance.speechString as NSString).substring(with: characterRange)
        print("Speech: \(word)")
    }
}

動作結果

Apple Watch 実機 (watchOS 3.1)

サンプルアプリをビルドし、音声を再生することができました。 (テキスト "The AVSpeechSynthesizer class produces synthesized speech." を読み上げ)

Simulator (Watch)

ビルドできませんでした。

/Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator3.1.sdk/System/Library/Frameworks/AVFoundation.framework/Headers/AVAsset.h:16:9: 'CoreMedia/CMTime.h' file not found

/Users/hirayashingo/XXXXX/WatchSpeechSynthesizer/WatchSpeechSynthesizer WatchKit Extension/InterfaceController.swift:11:8: Could not build Objective-C module 'AVFoundation'

さいごに

本記事では、AVFoundation framework の AVSpeechSynthesizer を使用して watchOS 3 アプリ上で合成音声を再生する実装を紹介しました。

次の記事では AVFoundation framework の別のクラスの機能を試してみたいと思います!

参考資料