iOS
Swift

[Swift] iOS でテキストの読み上げをする

More than 3 years have passed since last update.


AVSpeechSynthesizer を使って音声読み上げをする

iOS アプリで音声読み上げをやりたくなったので調べてみたメモです。

AVSpeechSynthesizer というクラスを使うと簡単に読み上げができました。


  1. AVSpeechSynthesizer を生成

  2. 読み上げるテキストを引数に AVSpeechUtterance を生成

  3. voice プロパティに言語指定した Voice を指定(ここでは ja-JP)

  4. 読み上げ

という順で処理を行います。コードにすると下記の通り。

let talker = AVSpeechSynthesizer()

let utterance = AVSpeechUtterance(string: text)
utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
talker.speakUtterance(utterance)


テキストをひとつずつ読み上げていく

ただ上記の処理では複数のテキストを読み上げる場合などに同時に読み上げてしまいます。そこでシングルトンを作って読み上げ処理を1つずつ行うようにしてみました。

やっていることは簡単で、


  1. 1. 読み上げたいテキストをリストに追加

  2. リストにあるテキストを音声読み上げ(再生は同時にひとつだけ)

  3. 読み上げ終了、2に戻る

をやっています。

import UIKit

import AVFoundation

final class TtsManager: NSObject, AVSpeechSynthesizerDelegate {

static let sharedInstance = TtsManager()

var texts = [String]()
let talker = AVSpeechSynthesizer()

private override init() {
super.init()
talker.delegate = self
}

func append(text: String) {
texts.append(text)
if texts.count == 1 {
play(texts[0])
}
}

// MARK: AVSpeechSynthesizerDelegate
func speechSynthesizer(synthesizer: AVSpeechSynthesizer, didFinishSpeechUtterance utterance: AVSpeechUtterance) {
if texts.count > 0 {
texts.removeFirst()
if texts.count > 0 {
play(texts[0])
}
} else {
// speech finished
}
}

func clear() {
texts.removeAll()
if talker.speaking {
talker.stopSpeakingAtBoundary(.Immediate)
}
}

private func play(text: String) {
let utterance = AVSpeechUtterance(string: text)
utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
talker.speakUtterance(utterance)
}

}