質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Framework

Frameworkは、アプリケーションソフトを開発する際に、一般的な機能をより簡単に、より早く完了させる事を目的とした、ソフトウェアやライブラリのセットを指します。開発にフレームワークを使用する事で、追加で必要となる機能だけを開発するだけで済む為、開発効率の向上が見込めます。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

2025閲覧

【Speech Framework】【Swift4】音声認識してテキストを入力

Leader731

総合スコア20

Framework

Frameworkは、アプリケーションソフトを開発する際に、一般的な機能をより簡単に、より早く完了させる事を目的とした、ソフトウェアやライブラリのセットを指します。開発にフレームワークを使用する事で、追加で必要となる機能だけを開発するだけで済む為、開発効率の向上が見込めます。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2019/06/25 22:42

編集2019/06/25 22:52

問題

こちらのサイトを参考に音声認識システムを実装している最中につまづきました。

【Speech Framework】音声認識してテキストを入力する
https://qiita.com/chino_tweet/items/027c432cfb983f95679a

問題のコード

Swift4

1//audioEngineインスタンスのinputNodeプロパティを取得する 2guard let inputNode = audioEngine.inputNode else { fatalError("InputNodeエラー") }

エラー内容

Initializer for conditional binding must have Optional type, not 'AVAudioInputNode'

試したこと

let inputNode As Optionalとしましたが今度は別のエラーが2つ出ました

【エラー1】
Pattern matching in a condition requires the 'case' keyword
Insert 'case '

【エラー2】
Reference to generic type 'Optional' requires arguments in <...>
Insert '<Any>'

なおこれに対して、caseや<Any>を挿入してもまた別のエラーが出ます。

全体のコード

Swift4

1 2import UIKit 3import Speech 4 5class ViewController: UIViewController, SFSpeechRecognitionTaskDelegate { 6 7 //UIラベルの変数 8 @IBOutlet weak var textView: UILabel! 9 @IBOutlet weak var recordButton: UIButton! 10 //UIボタンの変数 11 @IBAction func recordButton(_ sender: UIButton) { 12 if audioEngine.isRunning { 13 // 音声エンジン動作中なら停止 14 audioEngine.stop() 15 recognitionRequest?.endAudio() 16 recordButton.isEnabled = false 17 recordButton.setTitle("Stopping", for: .disabled) 18 recordButton.backgroundColor = UIColor.lightGray 19 return 20 } 21 // 録音を開始する 22 try! startRecording() 23 recordButton.setTitle("認識を完了する", for: []) 24 recordButton.backgroundColor = UIColor.red 25 } 26 //メンバプロパティでタスクのオブジェクトを宣言 27 private var recognitionTask: SFSpeechRecognitionTask? 28 //認識リクエストのインスタンスを宣言 29 private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest? 30 31 //SFSpeechRecognizerインスタンスを生成 32 //日本語に指定 33 private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "ja-JP"))! 34 35 //端末のマイクを使う準備 36 private let audioEngine = AVAudioEngine() 37 38 override func viewDidLoad() { 39 super.viewDidLoad() 40 // Do any additional setup after loading the view. 41 42 //マイクの許可をデフォルトでは無効にしておく 43 recordButton.isEnabled = false 44 } 45 46 // 画面に表示される直前に呼ばれます。 47 override func viewWillAppear(_ animated: Bool) { 48 speechRecognizer.delegate = self as! SFSpeechRecognizerDelegate // デリゲート先になる 49 SFSpeechRecognizer.requestAuthorization { (status) in 50 OperationQueue.main.addOperation { 51 switch status { 52 case .authorized: // 許可OK 53 self.recordButton.isEnabled = true 54 self.recordButton.backgroundColor = UIColor.blue 55 case .denied: // 拒否 56 self.recordButton.isEnabled = false 57 self.recordButton.setTitle("録音許可なし", for: .disabled) 58 case .restricted: // 限定 59 self.recordButton.isEnabled = false 60 self.recordButton.setTitle("このデバイスでは無効", for: .disabled) 61 case .notDetermined:// 不明 62 self.recordButton.isEnabled = false 63 self.recordButton.setTitle("録音機能が無効", for: .disabled) 64 } 65 } 66 } 67 } 68 69 private func startRecording() throws { 70 //ここに録音する処理を記述 71 //オプショナルバインディング 72 if let recognitionTask = recognitionTask { 73 // 既存タスクがあればキャンセルしてリセット 74 recognitionTask.cancel() 75 self.recognitionTask = nil 76 } 77 78 let audioSession = AVAudioSession.sharedInstance() 79 try audioSession.setCategory(AVAudioSession.Category.record) 80 try audioSession.setMode(AVAudioSession.Mode.measurement) 81 try audioSession.setActive(true) 82 83 //認識開始の前に認識リクエストを初期化 84 recognitionRequest = SFSpeechAudioBufferRecognitionRequest() 85 guard let recognitionRequest = recognitionRequest else { fatalError("リクエスト生成エラー") } 86 87 //録音完了前に途中の結果を報告してくれる 88 recognitionRequest.shouldReportPartialResults = true 89 90 //audioEngineインスタンスのinputNodeプロパティを取得する 91 guard let inputNode = audioEngine.inputNode else { fatalError("InputNodeエラー") } 92 93 //リクエストを登録してタスクを実行 94 recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { (result, error) in 95 var isFinal = false 96 97 if let result = result { 98 self.textView.text = result.bestTranscription.formattedString 99 isFinal = result.isFinal 100 } 101 102 if error != nil || isFinal { 103 self.audioEngine.stop() 104 inputNode.removeTap(onBus: 0) 105 106 self.recognitionRequest = nil 107 self.recognitionTask = nil 108 109 self.recordButton.isEnabled = true 110 self.recordButton.setTitle("Start Recording", for: []) 111 self.recordButton.backgroundColor = UIColor.blue 112 113 } 114 } 115 116 117 //マイクからの録音フォーマット 118 let recordingFormat = inputNode.outputFormat(forBus: 0) 119 120 inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in 121 self.recognitionRequest?.append(buffer) 122 } 123 124 //オーディオエンジンで録音を開始して、テキスト表示を変更する 125 audioEngine.prepare() // オーディオエンジン準備 126 try audioEngine.start() // オーディオエンジン開始 127 128 textView.text = "Hello World" 129 130 } 131 132 //音声認識機能の状態が変化するタイミングで呼ばれる 133 //録音ボタンの有効と無効を切り替える 134 public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) { 135 if available { 136 // 利用可能になったら、録音ボタンを有効にする 137 recordButton.isEnabled = true 138 recordButton.setTitle("Start Recording", for: []) 139 recordButton.backgroundColor = UIColor.blue 140 } else { 141 // 利用できないなら、録音ボタンは無効にする 142 recordButton.isEnabled = false 143 recordButton.setTitle("現在、使用不可", for: .disabled) 144 } 145 } 146 147 148 149}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こんにちは。

元記事が2016年なので、たぶんいろいろframework側が変わっていると思います。

https://developer.apple.com/documentation/avfoundation/avaudioengine/1386063-inputnode
をみた感じinputNodeはOptionalではないので、gurad letのようなオプショナルを剥がす処理は不要だと思われます。

そのまま

let inputNode = audioEngine.inputNode

で良いと思います。

別件ですが、

speechRecognizer.delegate = self as! SFSpeechRecognizerDelegate // デリゲート先になる

delegate代入時にこの書き方(as!以降)は普通はありえません(たぶん実行時にクラッシュすると思います)。
speechRecognizer.delegateの型を調べて、それに準拠するようにしましょう。

投稿2019/06/27 01:05

takabosoft

総合スコア8356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Leader731

2019/06/27 07:48

ご返信有難うございます。 デリゲートの扱いに詳しくないのですが、 speechRecognizer.delegate = self as! SFSpeechRecognizerDelegate はなぜありえないのでしょうか? こちらの理由をお教えいただきたいです。
takabosoft

2019/06/27 07:50

正しい実装をしていれば speechRecognizer.delegate = self のようにキャストが不要だからです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問