■SwiftUI+音声
【SwiftUI】AVFoundationでText to Speech - Qiita
https://qiita.com/mushroominger/items/5f4199d4eff8d2b4bc30
[Swift] AVSpeechSynthesizerで読み上げ機能を使ってみる | DevelopersIO
https://dev.classmethod.jp/articles/swfit-avspeechsynthesizer/
■音声読み上げ
ContentView.swift
import SwiftUI
import AVFoundation
struct ContentView: View {
@State private var language = "ja"
@State private var text: String = ""
var body: some View {
VStack {
Picker(selection: $language, label: Text("フルーツを選択")) {
Text("日本語").tag("ja")
Text("英語").tag("en")
}
.frame(width: 200, height: 100)
//Text("選択値:\(language)")
TextEditor(text: $text)
.frame(width: UIScreen.main.bounds.width * 0.9, height: 200)
.overlay(
RoundedRectangle(cornerRadius: 6)
.stroke(Color.gray, lineWidth: 1)
)
.padding()
Button("読み上げる") {
// 読み上げる内容
let utterance = AVSpeechUtterance(string: text)
// 言語
if (language == "ja") {
utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
} else {
utterance.voice = AVSpeechSynthesisVoice(language: "en-US")
}
// 速度
utterance.rate = 0.5
//utterance.rate = 0.6
// 高さ
utterance.pitchMultiplier = 1.0
//utterance.pitchMultiplier = 1.2
// 読み上げ実行
let synthesizer = AVSpeechSynthesizer()
synthesizer.speak(utterance)
}
.padding()
Spacer()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
■音声認識
※検証中
Swiftでリアルタイム音声認識するための最小コード - Qiita
https://qiita.com/mishimay/items/71304f0aa2a313ad93ac
Swift でリアルタイム音声認識をするサンプルコード - iOS アプリケーション開発の基本 - Swift による iOS 開発入門
https://swift-ios.keicode.com/ios/speechrecognition-live.php
SpeechFrameworkで音声認識されなくなる問題 - 野生のプログラマZ
http://harumi.sakura.ne.jp/wordpress/2020/04/20/speechframework%E3%81%A7%E9%9F%B3%E5%A3%B0%E8%AA%8D%...
SwiftUIとSpeech Frameworkで動画の文字起こしアプリを作ってみる - Qiita
https://qiita.com/rymshm/items/5ea968acb686c53133c7
Info.plist にKey「Privacy - Microphone Usage Description」を追加し、Valueに「マイクを使用します。」と記載しておく
同様に「Privacy - Speech Recognition Usage Description」を追加し、Valueに「音声認識を使用します。」と記載しておく
ファイルの内容を直接確認すると、dictタグ内に以下が追加されている
Info.plist
<key>NSMicrophoneUsageDescription</key>
<string>マイクを使用します。</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>音声認識を使用します。</string>
ContentView.swift
import SwiftUI
import Speech
struct ContentView: View {
private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "ja-JP"))!
@State private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
@State private var recognitionTask: SFSpeechRecognitionTask?
private let audioEngine = AVAudioEngine()
@State private var text: String = ""
var body: some View {
VStack {
TextEditor(text: $text)
.frame(width: UIScreen.main.bounds.width * 0.9, height: 200)
.overlay(
RoundedRectangle(cornerRadius: 6)
.stroke(Color.gray, lineWidth: 1)
)
.padding()
Button("音声認識開始") {
try? start()
}
Button("音声認識終了") {
stop()
}
}
.onAppear() {
SFSpeechRecognizer.requestAuthorization { (authStatus) in
}
}
}
private func start() throws {
if let recognitionTask = recognitionTask {
recognitionTask.cancel()
self.recognitionTask = nil
}
let audioSession = AVAudioSession.sharedInstance()
try audioSession.setCategory(.record, mode: .measurement, options: [])
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
let recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
self.recognitionRequest = recognitionRequest
recognitionRequest.shouldReportPartialResults = true
recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in
//recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { [weak self] (result, error) in
//guard let `self` = self else { return }
var isFinal = false
if let result = result {
print(result.bestTranscription.formattedString)
text = result.bestTranscription.formattedString
isFinal = result.isFinal
}
if error != nil || isFinal {
self.audioEngine.stop()
self.audioEngine.inputNode.removeTap(onBus: 0)
self.recognitionRequest = nil
self.recognitionTask = nil
}
})
let recordingFormat = audioEngine.inputNode.outputFormat(forBus: 0)
audioEngine.inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
self.recognitionRequest?.append(buffer)
}
audioEngine.prepare()
try? audioEngine.start()
}
private func stop() {
audioEngine.stop()
recognitionRequest?.endAudio()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
「音声認識開始」ボタンを連続してタップするとアプリが止まる
認識中ならタップできないようにする仕組みが必要か