Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import UIKit
- import ARKit
- import AgoraRtcEngineKit
- class ViewController: UIViewController {
- @IBOutlet weak var stackView: UIStackView!
- var agoraKit: AgoraRtcEngineKit!
- var tags: [Int] = (1...100).map { $0 }
- var sceneView: ARSCNView?
- let noseOptions = ["👃", "🐽", "💧", " "]
- var isARSupported: Bool {
- return ARFaceTrackingConfiguration.isSupported
- }
- override func viewDidLoad() {
- super.viewDidLoad()
- initializeAgoraEngine()
- setupVideo()
- setChannelProfile()
- }
- override func viewDidAppear(_ animated: Bool) {
- super.viewDidAppear(animated)
- showJoinAlert()
- }
- func showJoinAlert() {
- let alertController = UIAlertController(title: nil, message: "Ready to join channel.", preferredStyle: .alert)
- let action = UIAlertAction(title: "Join", style: .destructive) { (action:UIAlertAction) in
- self.joinChannel()
- }
- alertController.addAction(action)
- present(alertController, animated: true, completion: nil)
- }
- func initializeAgoraEngine() {
- agoraKit = AgoraRtcEngineKit.sharedEngine(withAppId: AppID, delegate: self)
- }
- func setChannelProfile() {
- agoraKit.setChannelProfile(.communication)
- }
- func setupVideo() {
- agoraKit.enableVideo()
- agoraKit.setVideoEncoderConfiguration(
- AgoraVideoEncoderConfiguration(size: AgoraVideoDimension640x360,
- frameRate: .fps15,
- bitrate: AgoraVideoBitrateStandard,
- orientationMode: .adaptative)
- )
- }
- func joinChannel() {
- agoraKit.setDefaultAudioRouteToSpeakerphone(true)
- guard let uid = tags.randomElement() else { return }
- agoraKit.joinChannel(byToken: nil,
- channelId: "DemoChannel",
- info: nil,
- uid: UInt(uid)) { [weak self] (sid, uid, elapsed) -> Void in
- guard let _self = self else { return }
- DispatchQueue.main.async {
- _self.setupLocalVideo(uid: uid)
- }
- }
- UIApplication.shared.isIdleTimerDisabled = true
- }
- func setupLocalVideo(uid: UInt) {
- let videoView = ARSCNView()
- videoView.tag = Int(uid)
- videoView.backgroundColor = UIColor.orange
- // let videoCanvas = AgoraRtcVideoCanvas()
- // videoCanvas.uid = uid
- // videoCanvas.view = videoView
- // videoCanvas.renderMode = .hidden
- // agoraKit.setupLocalVideo(videoCanvas)
- self.sceneView = videoView
- self.sceneView?.delegate = self
- if isARSupported {
- let configuration = ARFaceTrackingConfiguration()
- sceneView?.session.run(configuration)
- }
- let tapGuesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
- tapGuesture.numberOfTapsRequired = 1
- self.sceneView?.addGestureRecognizer(tapGuesture)
- stackView.addArrangedSubview(videoView)
- }
- @IBAction func didClickHangUpButton(_ sender: UIButton) {
- leaveChannel()
- }
- func leaveChannel() {
- agoraKit.leaveChannel(nil)
- UIApplication.shared.isIdleTimerDisabled = false
- }
- @IBAction func didClickMuteButton(_ sender: UIButton) {
- sender.isSelected = !sender.isSelected
- agoraKit.muteLocalAudioStream(sender.isSelected)
- }
- func updateFeatures(for node: SCNNode, using anchor: ARFaceAnchor) {
- let child = node.childNode(withName: "nose", recursively: false) as? EmojiNode
- let vertices = [anchor.geometry.vertices[9]]
- child?.updatePosition(for: vertices)
- }
- @IBAction func handleTap(_ sender: UITapGestureRecognizer) {
- let location = sender.location(in: sceneView)
- let results = sceneView?.hitTest(location, options: nil)
- if let result = results?.first,
- let node = result.node as? EmojiNode {
- node.next()
- }
- }
- }
- extension ViewController: AgoraRtcEngineDelegate {
- func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid:UInt, size:CGSize, elapsed:Int) {
- let videoView = UIView()
- videoView.tag = Int(uid)
- videoView.backgroundColor = UIColor.purple
- stackView.addArrangedSubview(videoView)
- let videoCanvas = AgoraRtcVideoCanvas()
- videoCanvas.uid = uid
- videoCanvas.view = videoView
- videoCanvas.renderMode = .hidden
- agoraKit.setupRemoteVideo(videoCanvas)
- }
- internal func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid:UInt, reason:AgoraUserOfflineReason) {
- guard let view = stackView.arrangedSubviews.first(where: { (view) -> Bool in
- return view.tag == Int(uid)
- }) else { return }
- stackView.removeArrangedSubview(view)
- }
- func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoMuted muted:Bool, byUid:UInt) {
- // remoteVideoMutedIndicator.isHidden = !muted
- }
- }
- extension ViewController: ARSCNViewDelegate {
- func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
- guard let faceAnchor = anchor as? ARFaceAnchor,
- let device = sceneView?.device else { return nil }
- let faceGeometry = ARSCNFaceGeometry(device: device)
- let node = SCNNode(geometry: faceGeometry)
- node.geometry?.firstMaterial?.fillMode = .lines
- node.geometry?.firstMaterial?.transparency = 0.0
- let noseNode = EmojiNode(with: noseOptions)
- noseNode.name = "nose"
- node.addChildNode(noseNode)
- updateFeatures(for: node, using: faceAnchor)
- return node
- }
- func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
- guard let faceAnchor = anchor as? ARFaceAnchor,
- let faceGeometry = node.geometry as? ARSCNFaceGeometry else {
- return
- }
- faceGeometry.update(from: faceAnchor.geometry)
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement