+1

Xây dựng ứng dụng Speech-to-Text sử dụng Speech Framework trên iOS

Giới thiệu.

Apple giới thiệu về Speech framework tại sự kiện WWDC2016, cung cấp các API hữu ích cho xử lý nhận diện tiếng nóii, cho phép lập trình viên xây dựng các ứng dụng nhận diện xử lý giọng nói như ứng dụng Siri.

Trong phạm vi bài viết này sẽ từng bước xây dựng một ứng dụng nhận diện giọng nói đơn giản sử dụng Speech kit. Trước khi đi vào bài viết, ta cần phải chuẩn bị một số hành trang cơ bản gồm:

  • IDE Xcode 8 trở lên
  • Thiết bị sử dụng iOS 10 trở lên.

Mô tả chương trình

Chương trình rất đơn giản và hoạt động như sau:

  • Khi người dùng nhấn nút Start Record và nói qua micro của thiết bị thì sẽ hiển thị nội dung người dùng đã nói lên một UILabel
  • Ứng dụng sẽ có giao diện như sau:

Sử dụng Speech Framework

Thư viện và interface

Để sử dụng Speech Framework ta cần phải import thư viện Speech và implement delegate SFSpeechRecognizerDelegate như code dưới đây

import UIKit
import Speech

class ViewController: UIViewController, SFSpeechRecognizerDelegate {
    
    
    @IBOutlet weak var textView: UITextView!
    @IBOutlet weak var microphoneButton: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }

    @IBAction func microphoneTapped(_ sender: AnyObject) {

    }

}

User Authorization

Trước khi sử dụng Speech Framework để nhận diện giọng nói, ta cần phải yêu cầu phân quyền từ người dùng, vì framework xử lý không chỉ hoạt động trên thiết bị, mà còn chuyển dữ liệu lên server của Apple để xử lý. Việc yêu cầu phân quyền này cho phép ứng dụng có thể sử dụng tiến hiệu đầu vào Audio và nhận diện giọng nói. Các bước như sau:

  • Bổ sung hai dòng sau vào file info.plist để cho phép ứng dụng sử dụng Microphone và Speech Recognition
<key>NSMicrophoneUsageDescription</key>  <string>Your microphone will be used to record your speech when you press the "Start Recording" button.</string> 
<key>NSSpeechRecognitionUsageDescription</key>  <string>Speech recognition will be used to determine which words you speak into this device&apos;s microphone.</string>
  • Khởi tạo để xác định ngôn ngữ sẽ nhận diện Ví dụ: Ta đặt ngôn ngữ nhận diện là tiếng Anh, ta sử dụng đoạn code sau: private let speechRecognizer = SFSpeechRecognizer(locale: Locale.init(identifier: "en-US"))

  • Đăng ký delegate xử lý và yêu cầu phân quyền từ người dùng:

 speechRecognizer.delegate = self
 SFSpeechRecognizer.requestAuthorization { (authStatus) in 
        switch authStatus {  
        case .authorized:
           // Người dùng đồng ý phân quyền            
        case .denied:
            print("User denied access to speech recognition")
        case .restricted:            
            print("Speech recognition restricted on this device")
        case .notDetermined:           
            print("Speech recognition not yet authorized")
        }       
    }

Khi đó ta sẽ nhận được dialog yêu cầu phần quyền như hình dưới đây:

Xử lý khi nhận diện giọng nói

Ta sử dụng 3 đối tượng sau để nhận diện giọng nói:

  • SFSpeechAudioBufferRecognitionRequest để xử lý các request gửi tín hiệu tiếng nói đầu vào chuyển tới bộ nhận diện tiếng nói. private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
  • SFSpeechRecognitionTask để định danh cho các request xử lý nhận diện, cho phép start, cancel các request private var recognitionTask: SFSpeechRecognitionTask?
  • AVAudioEngine là audio engine để lấy tín hiệu tiếng nói đầu vào. private let audioEngine = AVAudioEngine()

Chi tiết từng bước thực hiện như sau:

  • Bước 1: Kiểm tra recognitionTask còn hoạt động hay không, nếu còn đang xử lý thì dừng task

    if recognitionTask != nil {
            recognitionTask?.cancel()
            recognitionTask = nil
        }
    
  • Bước 2: Khởi tạo AVAudioSession để chuẩn bị ghi âm giọng nói

    let audioSession = AVAudioSession.sharedInstance()
        do {
            try audioSession.setCategory(AVAudioSessionCategoryRecord)
            try audioSession.setMode(AVAudioSessionModeMeasurement)
            try audioSession.setActive(true, with: .notifyOthersOnDeactivation)
        } catch {
            print("audioSession properties weren't set because of an error.")
        }
    
  • Bước 3: Khởi tạo SFSpeechAudioBufferRecognitionRequest để chuyển dữ liệu audio tới Apple server recognitionRequest = SFSpeechAudioBufferRecognitionRequest()

  • Bước 4: Kiểm tra thiết bị có cho phép đầu vào audio không

    guard let inputNode = audioEngine.inputNode else {
            fatalError("Audio engine has no input node")
        }
    
  • Bước 5: Bắt đầu quá trình nhận diện gióng nọi bằng cách gọi phương thức recognitionTask của đối tượng speechRecognizer. Complete handler của hàm này sẽ được gọi khi engine nhận diện nhận được dữ liệu, và chỉ ra kêt quả nhận diện hoặc lỗi trong quá trình xử lý

    recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in 
    
        var isFinal = false
    
        if result != nil {
    
            self.textView.text = result?.bestTranscription.formattedString
            isFinal = (result?.isFinal)!
        }
    
        if error != nil || isFinal {
            self.audioEngine.stop()
            inputNode.removeTap(onBus: 0)
    
            self.recognitionRequest = nil
            self.recognitionTask = nil
    
            self.microphoneButton.isEnabled = true
        }
    })
    
  • Bước 6: Đưa audio input vào** recognitionRequest**. Speech Framework sẽ bắt đầu nhận diện ngay khi có tín hiệu audio.

    let recordingFormat = inputNode.outputFormat(forBus: 0)
        inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
            self.recognitionRequest?.append(buffer)
        }
    
  • Bước 7: Khởi động Audio Engine để nhận tín hiệu audio

    audioEngine.prepare()
    do {
        try audioEngine.start()
    } catch {
        print("audioEngine couldn't start because of an error.")
    }
    

    Triggering Speech Recognition

    Ta sử dụng availabilityDidChange của protocol SFSpeechRecognizerDelegate để nhận biết trạng thái hoạt động module Speech Recognition.

    func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
        if available {
            microphoneButton.isEnabled = true
        } else {
            microphoneButton.isEnabled = false
        }
    }
    

    Hàm này sẽ được gọi khi trạng thái cho phép hoạt động của bộ nhận diện thay đổi.

    Để dừng chức năng nhận diện, ta cần phải dừng audio engine và recognition request, như đoạn code dưới đây:

    audioEngine.stop()
    recognitionRequest?.endAudio()
    

Lưu ý

  • Apple giới hạn sử dụng chức năng nhận diện đối với mỗi thiết bị
  • Apple giới hạn chức năng nhận diện đối với từng app
  • Speech recognition là chức năng tốn pin và đường truyền mạng
  • Mỗi phiên sử dụng Speech Recognition kiểu dài tối đa 1 phút.

Kết luận.

Sau bài viết này ta có thể dễ dàng xây dựng một ứng dụng đơn giản sử dụng tính năng nhận diện giọng nói như siri. Ta có thể mở rộng thêm như sử dụng giọng nói để làm controller game, media player.

Mã nguồn và nguồn thao khảo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí