見出し画像

iOSDC 2022 参加報告と発表内容補足

AmaziaでiOS開発者をやっている日向です。
今年も、iOS関連技術をコアのテーマとしたソフトウェア技術者のためのカンファレンス「iOSDC 2022」に参加してきました。

自分の発表としましては、

の二つに参加させていただきました。
それぞれについて補足説明させていただきます。

令和時代のXML処理を考える 〜もしあなたが巨大なXMLと相見える(あいまみえる)ことになったら〜

このトークを行おうと思ったきっかけは、ヘルスケアからエクスポートされるXMLにあります。

ヘルスケアからエクスポートされるxmlには二種類あり、export_cda.xmlと、export.xmlがあります。export_cda.xmlは、CDA(Clinical Document Architecture)のフォーマットであり、export.xmlはAppleのHealthKitが独自にエクスポートするものになります。

iPhoneの使い方次第ですが、どちらのxmlもあまりに巨大でテキストエディタで固まったりするので、これはXMLParserで解析するのが一番の近道と考えました。その際、export.xmlにはDTDが付与されているので、DTDを解析しようとして「おや?」と思ったのが今回のトークを申し込んだ理由になります。

XMLParserのDTDサポート状況については資料を見ていただければいいのですが、資料中に出てくるMultiple delegatesに関しては公式のドキュメント Introduction to Event-Driven XML Programming Guide for Cocoa から言葉と実装内容を参考にしています。

手で触れずにアプリを動かす技術

iPhone上の動画や資料を見ながら両手で料理や工作などをおこなっていると、両手が塞がってしまう可能性があると思います。両手があいたとしても、両手が汚れている状態になり、iPhoneにさわれない状況にもなると思います。
また、iPadを両手で見ながら寝転んでいたり、あるいは小さい子どもが両手でiPadを使っていて、タッチが困難な場合もあるでしょう。
そんな、タッチインターフェースが使えない一時的な状態への一助となればと思い、今回のプロポーザブルを提出しました。

一番のネックはデモを行うところでありましたが、本番では無事に手を使わずに声での撮影に成功しました。両手を上げていることで、手を使って撮影していないことがお分かりいただけると思います。(タイマーの可能性が否定できませんが)

手を使わずに、自撮りに成功している写真

他にも、顔認識での撮影機能も準備していたのですが、当日のレギュレーションとして「マスクの着用」というものがありましたので、顔認識のデモ自体は断念しました。しかし、去年までのオンラインと今年のリアル会場とのハイブリッドでは、デモの体験は大きく異なるものになっていただろうと思いますので、iOSDCスタッフの皆様には感謝です。惜しむらくは時間が足りず自己紹介が出来なかったので、次回があれば自己紹介出来るようにに頑張ります。

文字認識について

いくつかの人がコメントしていましたが、Vision frameworkでの日本語の文字認識についてはiOS 16で対応になりました。「撮影」と掲げて、写真を撮ることが可能になります。

コード

それぞれの認識について、軽くコードを抜粋します。
まずは音声認識です。

private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "ja-JP"))!
private let audioEngine = AVAudioEngine()
private var recognitionTask: SFSpeechRecognitionTask?
private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?

private func stopRecording() {
    audioEngine.stop()
    recognitionRequest?.endAudio()
}

func startRecording() throws {
    recognitionTask?.cancel()
    recognitionTask = nil
    let audioSession = AVAudioSession.sharedInstance()
    try audioSession.setCategory(.record, mode: .measurement, options: .duckOthers)
    try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
    let inputNode = audioEngine.inputNode
    let recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
    self.recognitionRequest = recognitionRequest
    recognitionRequest.shouldReportPartialResults = true
    recognitionRequest.requiresOnDeviceRecognition = false
    recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in
        var isFinal = false
        if let result = result {
            isFinal = result.isFinal
            switch result.bestTranscription.segments.last?.substring {
            case "撮影":
                self.takePicture(sender: result)
            case "終了":
                recognitionRequest.endAudio()
            default:
                break
            }
        }
        
        if error != nil || isFinal {
            self.audioEngine.stop()
            inputNode.removeTap(onBus: 0)
            self.recognitionRequest = nil
            self.recognitionTask = nil
        }
    }
    
    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()
}

続いて顔認識です。
カメラの映像をアプリに映す処理はTracking the User’s Face in Real Timeのサンプルコードが参考になります。このコードの `captureOutput(_:didOutput:from:)` の部分を書き換えることによって顔認識が確認できます。

private var faceDetector: CIDetector?
faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: context)

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    guard let faceDetector = self.faceDetector else { return }
    let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
    let ciImage: CIImage = CIImage(cvPixelBuffer: pixelBuffer)
    
    let faceFeatures:[CIFaceFeature] = faceDetector.features(in: ciImage, options: [
        CIDetectorSmile:true,
        CIDetectorEyeBlink:true
    ]) as! [CIFaceFeature]
    
    faceFeatures.map { faceFeature in
        faceFeature.hasSmile // 笑顔
        faceFeature.rightEyeClosed // 右目閉じている
        faceFeature.leftEyeClosed // 左目閉じている
    }
}

続いて、気圧です。

let altimeter = CMAltimeter()
altimeter.startRelativeAltitudeUpdates(to: .main) { data, error in
    print(data!.pressure)
}

requestAuthorizationの処理もいらないので一番シンプルで扱えそうですね。

最後に

今回のiOSDC 2022への資料作成、またiOSDC参加は全て弊社Amaziaの業務の一環として取り組んでいます。こういったカンファレンスへの社員の発表だけでなく、もちろん参加も奨励されておりますので、今回の発表を見て興味が出てきた方は是非ともAmaziaの採用情報をご覧ください。
iOSエンジニアもですが、Androidエンジニアも大募集中です。

株式会社Amaziaでは新しいメンバーを積極的に採用しています!詳しくは採用ページをご覧ください!