ばーちーぶろぐ

iOS関連の話をざっくりと。

iOS7の新機能、音声読み上げ(AVSpeech Synthesizer)についてまとめてみた

iOS7の新機能、音声読み上げ機能について

今回は、iOS7で新たに追加されたAVSpeech Synthesizerについて説明したいと思います。

AVSpeech Synthesizerとは

iOSデバイス上のテキストから合成音声を生成し、発話の進行を制御、監視するための方法を提供するクラスです。
発話させる為に、まずは再生したいテキストを含んだAVSpeechUtteranceのインスタンスを作成する必要があります。

AVSpeechUtteranceとは

AVSpeechUtteranceのプロパティには読み上げ時の音声指定、スピード、ボリューム、声のピッチ、再生までの待ち時間、再生終了後の待ち時間などが設定出来ます。

  • 音声はAVSpeechSynthesisVoiceのインスタンスを指定、使用出来る音声取得方法は下記メソッド一覧に記述。
  • スピードは0から1で指定。
  • ボリュームは0から1で指定。
  • 声のピッチは0.5から2で指定。

音声読み上げ

AVSpeech SynthesizerのspeakUtteranceメソッドにAVSpeechUtteranceのインスタンス与えることで発話が開始されます。
AVSpeech SynthesizerはAVSpeechUtteranceのインスタンスをキューで管理し、キューに追加した順番で再生されます。
AVSpeech Synthesizerが発話されていない場合は直ちに再生されます(待機時間を設定してる場合は待機時間後に発話が開始されます)。
AVSpeech Synthesizerがすでに発話されている場合はAVSpeechUtteranceのインスタンスをキューに追加します。

制御

発話開始後、音声を一時停止や停止する制御が出来ます。
Delegateを設定すると再生状態を監視出来ます。

メソッド、プロパティ一覧


実装例

1.AVSpeechSynthesizerのインスタンスを作成し、デリゲートを設定
- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    // initialize AVSpeechSynthesizer インスタンスを作成し、デリゲートを設定する
    _speechSynthesizer = [[AVSpeechSynthesizer alloc] init];
    _speechSynthesizer.delegate = self;
}
2.再生したいタイミングで、AVSpeechSynthesizerのspeakUtterance:にAVSpeechUtteranceのインスタンスを与えると再生が開始されます。
- (IBAction)start:(id)sender {
    // AVSpeechUtteranceに再生テキストを設定し、インスタンス作成
    AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:[[self textView] text]];
    // 英語に設定し、AVSpeechSynthesisVoiceのインスタンス作成
    AVSpeechSynthesisVoice *voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"en-US"];
    // AVSpeechSynthesisVoiceをAVSpeechUtterance.voiceに指定。
    utterance.voice =  voice;
    // デフォルトは早すぎるので
    utterance.rate = 0.2;
    // 男性ぽく
    utterance.pitchMultiplier = 0.5;
    // 0.2秒のためを作る
    utterance.preUtteranceDelay = 0.2f;
    // 再生開始
    [self.speechSynthesizer speakUtterance:utterance];
}
3.再生の制御
- (IBAction)pause:(id)sender {
    // 停止していたら再開、停止していなかったら停止
    self.speechSynthesizer.paused?
    [self.speechSynthesizer continueSpeaking]:
    [self.speechSynthesizer pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
}

- (IBAction)finish:(id)sender {
    // 直ちに停止
    [self.speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
}
4.再生状況でなにかごにょごにょしたい場合
#pragma mark - AVSpeechSynthesizerDelegate

- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didStartSpeechUtterance:(AVSpeechUtterance *)utterance{
    NSLog(@"読み上げを開始しました");
}

- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance{
    NSLog(@"読み上げを終了しました");
}

- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didPauseSpeechUtterance:(AVSpeechUtterance *)utterance{
    NSLog(@"読み上げを一時停止しました");
}

- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didContinueSpeechUtterance:(AVSpeechUtterance *)utterance{
    NSLog(@"読み上げを再開しました");
}

- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didCancelSpeechUtterance:(AVSpeechUtterance *)utterance{
    NSLog(@"読み上げを停止しました");
}

- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(AVSpeechUtterance *)utterance{
    NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:self.textView.text];
    // 読み上げ中の単語の文字色、文字の大きさを設定
    [attrStr addAttribute:NSForegroundColorAttributeName
                    value:[UIColor redColor]
                    range:NSMakeRange((unsigned long)characterRange.location, characterRange.length)];
    [attrStr addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Futura-CondensedMedium" size:20.] range:NSMakeRange((unsigned long)characterRange.location, characterRange.length)];
    [self.textView setAttributedText:attrStr];
}

だいたいこんな感じで再生と制御は出来ると思います。
ゆるくざっくりと説明出来たのではないでしょうかー。
こんな感じで定期的にiOSについて書いていきます。

サンプルコードも一応置いておきます。
https://github.com/tochiba/AVSpeechSynthesizerSample

音声読み上げ機能は、下記のアプリに実装したのでどんなもんか確認してみてもいいかも!
http://www1415uo.sakura.ne.jp/jumon.html


間違いなどあったら誰か教えてください!