ARKit có vẻ đáng sợ nhưng không tệ nếu đã có kinh nghiệm cơ bản xây dựng app iOS.
Tôi kiểu học bằng làm, nên chơi với ARKit, xây app cơ bản để quen. Bài này review những gì học được tạo app face tracking đơn giản.
Làm 3 phần:
- Thiết Lập Ban Đầu → Trước hết, xin quyền Camera và đảm bảo thiết bị hỗ trợ ARKit.
- Theo dõi nụ cười → Bắt đầu theo dõi nụ cười với ARKit. Có lẽ bạn đến vì này.
- Giao Diện Người Dùng → Thêm UI cho app phản ứng với nụ cười.
Tại thời điểm viết, Xcode simulator không hỗ trợ front camera nên cần thiết bị thật chạy app. Thiết bị cũng cần TrueDepth camera (iPhone X hoặc mới hơn ổn).
Cuối cùng, cho các thành viên Copy Paste Club, toàn bộ code có trên Github.
Thiết Lập Ban Đầu
Mở Xcode tạo project mới tên "SmileTracker" (hoặc tên bạn thích).
Trước khi vào face tracking, cần làm 2 việc:
- Đảm bảo thiết bị hỗ trợ ARKit
- Xin quyền truy cập camera thiết bị
Trong project mới, mở ViewController.swift. Gần đầu file, dưới import UIKit, thêm: import ARKit. Cho phép truy cập mọi thứ Apple cung cấp để face tracking siêu dễ.
Thêm code sau trong viewDidLoad:
guard ARFaceTrackingConfiguration.isSupported else { fatalError("Thiết bị không hỗ trợ face tracking") }ARFaceTrackingConfiguration.isSupported là boolean true nếu thiết bị chạy app hỗ trợ face tracking, false nếu không. Trong trường hợp này, nếu thiết bị không hỗ trợ, crash app với fatal error.
Tiếp, xin quyền dùng camera. Thêm sau câu guard trong viewDidLoad:
AVCaptureDevice.requestAccess(for: AVMediaType.video) { granted in
if (granted) {
DispatchQueue.main.async {
// Sẽ implement hàm này ngay
self.setupSmileTracker()
}
} else {
fatalError("User không cấp quyền camera!")
}
}Yêu cầu thiết bị xin quyền camera. Nếu user cấp, chạy hàm setup smile tracking (đừng lo error, sẽ implement ngay).
Wrap hàm trong DispatchQueue.main.async vì sẽ thêm UI element trong hàm này, chỉ làm được trên main thread.
Cũng cần thêm Camera Usage Description vào Info.plist. Mở Info.plist thêm row mới (highlight row cuối nhấn enter).
Row vừa tạo, thêm Privacy — Camera Usage Description vào cột Key và cột Type để string. Cột Value để trống hoặc thêm message giải thích dùng camera cho user.
Info.plist giờ trông như sau:

Muốn test app đến đây, comment dòng gọi setupSmileTracker(). Nhớ uncomment sau.
Chạy app, sẽ thấy popup xin quyền camera. Nếu chọn no phải vào settings bật quyền mới chạy app.
Nếu app crash, check console lỗi hai trường hợp trên.
Theo Dõi Nụ Cười
Mở ViewController.swift thêm variable sau lên đầu ViewController:
class ViewController: UIViewController {
let sceneView = ARSCNView()
override func viewDidLoad() {...}
}ARSCNView trang bị ARSession iPhone dùng điều phối trải nghiệm AR. Dùng sceneView ARSession phân tích khuôn mặt user qua front camera.
Thêm hàm sau dưới viewDidLoad:
func setupSmileTracker() {
let configuration = ARFaceTrackingConfiguration()
sceneView.session.run(configuration)
sceneView.delegate = self
view.addSubview(sceneView)
}Tạo configuration xử lý face tracking và dùng chạy sceneView ARSession.
Set sceneView delegate = self và add vào view.
Xcode báo lỗi vì ViewController không conform ARSCNViewDelegate. Đi chỗ khai báo ViewController đầu file đổi dòng thành:
class ViewController: UIViewController, ARSCNViewDelegate { ... }Giờ thêm hàm ARSCNViewDelegate trong class ViewController setupSmileTracker:
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
...
}renderer chạy mỗi lần scene update và cung cấp ARAnchor tương ứng khuôn mặt user.
Để tạo face tracking dễ dàng, Apple tự tạo ARFaceAnchor và thêm vào session khi dùng ARFaceTrackingConfiguration chạy nó. ARFaceAnchor này truyền vào renderer như ARAnchor.
Thêm code vào renderer:
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
// 1
guard let faceAnchor = anchor as? ARFaceAnchor else { return }
// 2
let leftSmileValue = faceAnchor.blendShapes[.mouthSmileLeft] as! CGFloat
let rightSmileValue = faceAnchor.blendShapes[.mouthSmileRight] as! CGFloat
// 3
print(leftSmileValue, rightSmileValue)
}Nhiều chuyện trong hàm nên đánh số bước (style Ray Wenderlich).
Bước 1 convert ARAnchor thành ARFaceAnchor gán cho biến faceAnchor.
ARFaceAnchor chứa info vị trí, orientation, topology, và biểu cảm khuôn mặt của face đang track.
ARFaceAnchor lưu info biểu cảm trong biến blendShapes. blendShapes là dictionary lưu coefficient tương ứng các feature khuôn mặt. Quan tâm, xem full list trong tài liệu Apple. (Gợi ý: muốn thêm frown tracking tìm cách ở đây.)
Bước 2, dùng faceAnchor.blendShapes lấy CGFloat tương ứng mức độ nụ cười bên trái/phải miệng dùng key mouthSmileLeft và mouthSmileRight.
Bước 3 in ra hai giá trị check hoạt động 🤔.
Lúc này app nên:
- Xin quyền camera và face tracking từ user
- Dùng ARKit track biểu cảm khuôn mặt user
- In mức độ nụ cười trái/phải miệng ra console
Đã tiến bộ nhiều, check chạy đúng không.
Chạy app lần đầu, popup xin quyền camera. Chọn yes.
Màn hình trắng, nhưng console in giá trị CGFloat (có thể delay ngắn).
Khi cười vào điện thoại, giá trị in ra tăng. Cười to hơn số cao hơn.
Nếu hoạt động tốt, chúc mừng 🎉! Nếu lỗi, check thiết bị hỗ trợ face tracking và bật quyền camera. Nếu theo hướng dẫn từ đầu, console in lỗi cả hai trường hợp.
Giao Diện Người Dùng
Đang track face, giờ xây UI phản ứng nụ cười.
Thêm UILabel mới tên smileLabel lên đầu file, dưới sceneView.
class ViewController: UIViewController {
let sceneView = ARSCNView()
let smileLabel = UILabel()
...
}View này phản ứng biểu cảm khuôn mặt user.
Thêm code cuối hàm setupSmileTracker:
smileLabel.text = "😐"
smileLabel.font = UIFont.systemFont(ofSize: 150)
view.addSubview(smileLabel)
// Set constraints
smileLabel.translatesAutoresizingMaskIntoConstraints = false
smileLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
smileLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = trueThêm UI property cơ bản cho smileLabel và constraint đặt giữa màn hình. Chạy app, thấy emoji 😐 to giữa màn hình.

Khi thấy emoji, thêm hàm sau vào ViewController:
func handleSmile(leftValue: CGFloat, rightValue: CGFloat) {
let smileValue = (leftValue + rightValue)/2.0
switch smileValue {
case _ where smileValue > 0.5:
smileLabel.text = "😁"
case _ where smileValue > 0.2:
smileLabel.text = "🙂"
default:
smileLabel.text = "😐"
}
}Hàm đổi emoji trong smileLabel tùy mức độ cười. Tính smileValue bằng trung bình left/right smile value từ ARFaceAnchor (rất scientific, tôi biết).
Cho giá trị vào switch, cười to hơn emoji vui hơn.
Cuối cùng, quay lại hàm renderer thêm cuối để plug left/right smile value vào handleSmile:
DispatchQueue.main.async {
self.handleSmile(leftValue: leftSmileValue, rightValue: rightSmileValue)
}Lại dùng DispatchQueue vì thay đổi UI, phải trên main thread.
Chạy app, emoji thay đổi tùy mức độ cười vào camera.
GIF dưới tôi thêm face để thấy hoạt động với camera output cùng emoji.

App bạn không có camera output, nhưng thêm được bằng cách add ARSCNView sceneView vào superview cho dimensions.
Tổng Kết
Hy vọng bài viết giúp bắt đầu tạo app với ARKit.
Muốn mở rộng app, check list feature khuôn mặt khác có thể track. Tôi để gợi ý mở rộng check frown.
Quay lại comment project cool bạn tự tạo, tôi vẫn mới ARKit nên hào hứng thấy app phức tạp hơn.
Đăng toàn bộ code app này lên Github cho feedback và câu hỏi. Cảm ơn đọc và chúc may mắn!
Cảm ơn đã đọc! Nếu thích, follow Twitter tôi cập nhật story đang làm và đang up to.