Last active
February 3, 2021 04:51
-
-
Save takoikatakotako/cecd673920cab46a0bcfc67162f43fe4 to your computer and use it in GitHub Desktop.
音声認識のサンプル
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import Speech | |
class ViewController: UIViewController, SFSpeechRecognizerDelegate { | |
// MARK: Properties | |
//localeのidentifierに言語を指定、。日本語はja-JP,英語はen-US | |
private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "ja-JP"))! | |
private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest? | |
private var recognitionTask: SFSpeechRecognitionTask? | |
private let audioEngine = AVAudioEngine() | |
//録音の開始、停止ボタン | |
var recordButton : UIButton! | |
//文字音声認識された | |
var voiceStr : String! = "" | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
//録音を開始するボタンの設定 | |
recordButton = UIButton() | |
recordButton.frame = CGRect(x: 50, y: 50, width: 200, height: 40) | |
recordButton.backgroundColor = UIColor.lightGray | |
recordButton.addTarget(self, action: #selector(recordButtonTapped(sender:)), for:.touchUpInside) | |
recordButton.setTitle("Start Recording", for: []) | |
recordButton.isEnabled = false | |
self.view.addSubview(recordButton) | |
//デリゲートの設定 | |
speechRecognizer.delegate = self | |
//ユーザーに音声認識の許可を求める | |
SFSpeechRecognizer.requestAuthorization { authStatus in | |
OperationQueue.main.addOperation { | |
switch authStatus { | |
case .authorized: | |
//ユーザが音声認識の許可を出した時 | |
self.recordButton.isEnabled = true | |
case .denied: | |
//ユーザが音声認識を拒否した時 | |
self.recordButton.isEnabled = false | |
self.recordButton.setTitle("User denied access to speech recognition", for: .disabled) | |
case .restricted: | |
//端末が音声認識に対応していない場合 | |
self.recordButton.isEnabled = false | |
self.recordButton.setTitle("Speech recognition restricted on this device", for: .disabled) | |
case .notDetermined: | |
//ユーザが音声認識をまだ認証していない時 | |
self.recordButton.isEnabled = false | |
self.recordButton.setTitle("Speech recognition not yet authorized", for: .disabled) | |
} | |
} | |
} | |
} | |
// MARK: 録音ボタンが押されたら呼ばれる | |
func recordButtonTapped(sender: UIButton) { | |
if audioEngine.isRunning { | |
audioEngine.stop() | |
recognitionRequest?.endAudio() | |
recordButton.isEnabled = false | |
recordButton.setTitle("Stopping", for: .disabled) | |
//録音が停止した! | |
print("録音停止") | |
//入力された文字列の入った文字列を表示 | |
showStrAlert(str: self.voiceStr) | |
} else { | |
try! startRecording() | |
recordButton.setTitle("Stop recording", for: []) | |
} | |
} | |
//渡された文字列が入ったアラートを表示する | |
func showStrAlert(str: String){ | |
// UIAlertControllerを作成する. | |
let myAlert: UIAlertController = UIAlertController(title: "音声認識結果", message: str, preferredStyle: .alert) | |
// OKのアクションを作成する. | |
let myOkAction = UIAlertAction(title: "OK", style: .default) { action in | |
print("Action OK!!") | |
} | |
// OKのActionを追加する. | |
myAlert.addAction(myOkAction) | |
// UIAlertを発動する. | |
present(myAlert, animated: true, completion: nil) | |
} | |
//録音を開始する | |
private func startRecording() throws { | |
// Cancel the previous task if it's running. | |
if let recognitionTask = recognitionTask { | |
recognitionTask.cancel() | |
self.recognitionTask = nil | |
} | |
let audioSession = AVAudioSession.sharedInstance() | |
try audioSession.setCategory(AVAudioSessionCategoryRecord) | |
try audioSession.setMode(AVAudioSessionModeMeasurement) | |
try audioSession.setActive(true, with: .notifyOthersOnDeactivation) | |
recognitionRequest = SFSpeechAudioBufferRecognitionRequest() | |
guard let inputNode = audioEngine.inputNode else { fatalError("Audio engine has no input node") } | |
guard let recognitionRequest = recognitionRequest else { fatalError("Unable to created a SFSpeechAudioBufferRecognitionRequest object") } | |
// Configure request so that results are returned before audio recording is finished | |
recognitionRequest.shouldReportPartialResults = true | |
// A recognition task represents a speech recognition session. | |
// We keep a reference to the task so that it can be cancelled. | |
recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in | |
var isFinal = false | |
if let result = result { | |
//音声認識の区切りの良いところで実行される。 | |
self.voiceStr = result.bestTranscription.formattedString | |
print(result.bestTranscription.formattedString) | |
isFinal = result.isFinal | |
} | |
if error != nil || isFinal { | |
self.audioEngine.stop() | |
inputNode.removeTap(onBus: 0) | |
self.recognitionRequest = nil | |
self.recognitionTask = nil | |
self.recordButton.isEnabled = true | |
self.recordButton.setTitle("Start Recording", for: []) | |
} | |
} | |
let recordingFormat = inputNode.outputFormat(forBus: 0) | |
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in | |
self.recognitionRequest?.append(buffer) | |
} | |
audioEngine.prepare() | |
try audioEngine.start() | |
} | |
// MARK: SFSpeechRecognizerDelegate | |
//speechRecognizerが使用可能かどうかでボタンのisEnabledを変更する | |
public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) { | |
if available { | |
recordButton.isEnabled = true | |
recordButton.setTitle("Start Recording", for: []) | |
} else { | |
recordButton.isEnabled = false | |
recordButton.setTitle("Recognition not available", for: .disabled) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment