ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

728x90
๋ฐ˜์‘ํ˜•

ํ•ด๋‹น ๊ธ€์€, ํ™”๋ฉด๋ฐฉ์†ก์— ๋Œ€ํ•œ ๊ฐœ์ธ ๊ณต๋ถ€๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ ์‹œ์ฒญํ•œ WWDC 2016 - Go Live with ReplayKit์„ ์ •๋ฆฌํ•œ ๊ธ€ ์ž…๋‹ˆ๋‹ค.

ํ•ด์„๊ณผ ์ •๋ฆฌ๋œ ๋‚ด์šฉ์ด ์™„๋ฒฝํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ์ž˜๋ชป๋œ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„  ์ง€์  ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๐Ÿ™

 

WWDC 2016 - Go Live with ReplayKit

 

ReplayKit์€ ์‚ฌ์šฉ์ž์˜ ์•ฑ ๋‚ด ํ™”๋ฉด๊ณผ, ์‚ฌ์šด๋“œ ๊ทธ๋ฆฌ๊ณ  ๋งˆ์ดํฌ์˜ ์˜ค๋””์˜ค๋ฅผ ๋…นํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.
์ด๋ฅผ ํ†ตํ•ด, ๊ฒŒ์ž„์„ ํ•˜๋Š” ๋™์•ˆ ์Œ์„ฑ ๋‚ด๋ ˆ์ด์…˜์ด ๊ฐ€๋Šฅํ•˜๊ณ , ์ด๋ฅผ ์‹œ์Šคํ…œ ๊ณต์œ  ์‹œํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.


ReplayKit

1. Replaykit์€ HD ํ™”์งˆ์˜ ๋น„๋””์˜ค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

  • ๊ฒŒ์ž„ ์„ฑ๋Šฅ์— ๊ฑฐ์˜ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ณ , ๋ฐฐํ„ฐ๋ฆฌ์˜ ์†Œ๋ชจ๋ฅผ ์ตœ์†Œํ•œ์œผ๋กœ ์ค„์ž„

2. ๊ฐœ์ธ์ •๋ณด๋ฅผ ๋ณดํ˜ธํ•œ๋‹ค

  • ์œ ์ €์˜ ๊ฐœ์ธ์ •๋ณด๊ฐ€ ๋งค์šฐ ์ค‘์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋…นํ™” ์‹œ์ž‘ ์ „์— ์‚ฌ์šฉ์ž ํ”„๋กฌํ”„ํŠธ๋ฅผ ํ‘œ์‹œํ•ด์„œ ์œ ์ €๊ฐ€ ์ง์ ‘ ๊ถŒํ•œ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
  • ๋˜ํ•œ, ์•Œ๋ฆผ๊ณผ ๋ฉ”์‹œ์ง€ ๊ฐ™์€ System UI๋ฅผ ์ œ์™ธํ•˜๊ณ  ๊ธฐ๋ก๋œ๋‹ค.

3. iOS 9 ์ด์ƒ๋ถ€ํ„ฐ ๊ฐ€๋Šฅํ•˜๋‹ค.


์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ์†Œ๊ฐœ

1. Apple TV OS์—์„œ ์ง€์›ํ•œ๋‹ค.

  • ๋”ฐ๋ผ์„œ, TVOS์˜ ๊ฒŒ์ž„ํ”Œ๋ ˆ์ด๋„ ๋…นํ™”๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

2. Live BroadCasting์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

  • Third-Party ์„œ๋น„์Šค๋ฅผ ํ†ตํ•ด์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•จ.

3. FaceTime ์นด๋ฉ”๋ผ๋ฅผ ๋…นํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋งˆ์ดํฌ์˜ ๋…น์Œ ๊ด€๋ จ API๋ฅผ ํ–ฅ์ƒ์‹œ์ผฐ๋‹ค.

ReplayKit Architecture

  • ์‚ฌ์šฉ์ž์˜ ์•ฑ์€, OS์—๊ฒŒ '์ง€๊ธˆ ๋…นํ™”๋ฅผ ์‹œ์ž‘ํ–ˆ์–ด!' ๋ผ๊ณ  ์•Œ๋ ค์•ผ ํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค
    -> ์ด๋ฅผ ์œ„ํ•ด ReplayKit์€ RPScreenRecorder ํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
  • RPScreenRecorder๋ฅผ ํ†ตํ•ด์„œ, ๋…นํ™”๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋…นํ™”๊ฐ€ ์‹œ์ž‘ ๋œ ์ˆœ๊ฐ€, Replay Daemon์œผ๋กœ ๋ฉ”์„ธ์ง€๊ฐ€ ์ „๋‹ฌ๋˜๊ณ , Replay Daemon์ด ์•ฑ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด์„œ Movie ํŒŒ์ผ์— ์ž‘์„ฑํ•˜๊ธฐ ์‹œ์ž‘ํ•œ๋‹ค.

  • RPScreenRecorder ๋ฅผ ํ†ตํ•ด ๋…นํ™”๋ฅผ ์ค‘์ง€ํ•˜๊ฒŒ ๋˜๋ฉด, Replay Daemon ์ด Movie ํŒŒ์ผ ์ž‘์„ฑ์„ ์ค‘๋‹จํ•˜๊ฒŒ ๋œ๋‹ค.
    -> ์ด ๋•Œ, Movie ํŒŒ์ผ์€ ์•„์ง Syetem์ƒ์— ์กด์žฌํ•œ๋‹ค.
  • ์ด Movie ํŒŒ์ผ์„ Application๋‹จ์œผ๋กœ ๋Œ๋ ค์ฃผ๊ธฐ ์œ„ํ•ด RPPreviewViewController ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
    -> RPPreviewViewController ๋ฅผ ํ†ตํ•ด, ์‚ฌ์šฉ์ž๋Š” ์˜์ƒ์„ ๋ฏธ๋ฆฌ๋ณด๊ณ , ํŽธ์ง‘ํ•˜๊ณ , ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.


Classes and Protocols

RPScreenRecorder

  • ๋…นํ™”๋ฅผ ์‹œ์ž‘, ์ค‘์ง€, ์ทจ์†Œ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ˜„์žฌ ๋””๋ฐ”์ด์Šค๊ฐ€ ๋…นํ™”๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ์ฒดํฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • RPScreenRecorderDelegate
    • ๋…นํ™” ๊ฐ€๋Šฅ ์—ฌ๋ถ€๊ฐ€ ๋ณ€๊ฒฝํ•˜๋Š” ์‹œ์ ์„ ์ „๋‹ฌํ•ด์ค€๋‹ค.
    • ์—๋Ÿฌ๋กœ ์ธํ•ด, ๋…นํ™”๊ฐ€ ์ค‘๋‹จ๋œ ์‹œ์ ์„ ์ „๋‹ฌํ•ด์ค€๋‹ค.

RPPreviewViewController

  • ๋…นํ™”๋œ ์˜์ƒ์˜ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ์ œ๊ณตํ•ด์ค€๋‹ค.
  • ์˜์ƒ์˜ ์ˆ˜์ •๊ณผ ์ž˜๋ผ๋‚ด๊ธฐ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
  • ๊ณต์œ ํ•˜๊ธฐ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.
  • RPPreviewViewControllerDelegate
    • ํ”„๋ฆฌ๋ทฐ๊ฐ€ ์ข…๋ฃŒ๋œ ์‹œ์ ์„ ์ „๋‹ฌํ•ด์ค€๋‹ค.

ReplayKit on Apple TV

Start Recording

func didPressRecordButton() {
    let sharedRecorder = RPScreenRecorder.shared()
    sharedRecorder.startRecording { error in
        if error == nil { 
            self.showIndicatorView(text: "Recording")
        }
    }
}
  • RPScreenRecorder์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ํ˜ธ์ถœ
  • startRecording()๋ฅผ ํ˜ธ์ถœํ•ด์„œ, ๋…นํ™” ์‹œ์ž‘!
func showIndicatorView(text: String) {
    self.recordingIndicatorWindow = UIWindow(frame: UIScreen.main().bounds)
    self.recordingIndicatorWindow?.isHidden = false
    self.recordingIndicatorWindow?.backgroundColor = UIColor.clear
    self.recordingIndicatorWindow?.isUserInteractionEnabled = false

    let indicatorView = IndicatorView(text: text)
    self.recordingIndicatorWindow?.addSubview(indicatorView)
}
  • ReplayKit์€ Application์˜ Main-Window๋งŒ ๋…นํ™”ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ธ๋””์ผ€์ดํ„ฐ๊ฐ€ ํฌํ•จ๋˜์ง€ ์•Š๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด, ๋ณ„๋„์˜ Window๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
func didPressStopButton() {
    sharedRecorder.stopRecording { previewViewController, error in
        self.hideIndicatorView()
        if error == nil {
            self.previewViewController = previewViewController
            self.previewViewController?.previewControllerDelegate = self
        }    
    }
}
  • Stop ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์„œ, didPressStopButton()์„ ํ˜ธ์ถœํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž.
  • RPScreenRecorder์˜ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด stopRecording()์„ ํ˜ธ์ถœํ•˜๋ฉด, previewViewController ๊ฐ์ฒด๊ฐ€ ํ•จ๊ป˜ ๋„˜์–ด์˜จ๋‹ค!
  • ๊ทธ๋ฆฌ๊ณ , ๋„˜์–ด์˜จ previewViewController๋ฅผ self.previewViewController์— ํ• ๋‹นํ•จ์œผ๋กœ์จ ์‚ฌ๋ผ์ง€์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.
  • previewControllerDelegate ๋˜ํ•œ, self๋กœ ์œ„์ž„.
func didPressPreviewButton() {
    if let preview = previewViewController {
        preview.mode = .preview /// .share ์˜ต์…˜๋„ ์žˆ์Œ.
        self.present(preview, animated: true)
    }
}
  • preview๋ฅผ ์‹ค์ œ ํ™”๋ฉด์œผ๋กœ ๋ณด์—ฌ์ค„ ๋•Œ, mode๋ฅผ .preview, .share ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค.
func previewControllerDidFinish(_ previewController: RPPreviewViewController) {
    previewController.dismiss(animated: true)
}
  • ๋ชจ๋“œ์— ์ƒ๊ด€์—†์ด previewํ™”๋ฉด์—์„œ ๋Œ์•„์˜ค๋ ค๊ณ  ํ•  ๋•Œ RPPreviewViewControllerDelegate์˜ previewControllerDidFinish(_ previewController: RPPreviewViewController)๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
  • ์ด ํ•จ์ˆ˜๋Š” previewControoler๋ฅผ ์ „๋‹ฌํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์—,ํ˜„์žฌ ViewController์—์„œ dismiss ํ•ด์ค€๋‹ค.

Discarding the Recording

์ƒˆ๋กœ์šด ๋…นํ™”๊ฐ€ ์‹œ์ž‘์ด ๋˜๋ฉด, ์ด์ „์˜ ๋…นํ™”๋Š” ์ž๋™์œผ๋กœ ์ œ๊ฑฐ๋œ๋‹ค

  • ํ•˜๋‚˜์˜ ์•ฑ์—๋Š” ํ•˜๋‚˜์˜ Record๋งŒ ํ—ˆ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • ๋˜ํ•œ, RPScreenRecorder.discardRecording()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋ช…์‹œ์ ์œผ๋กœ ์ œ๊ฑฐ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

ReplayKit on Apple TV

  • ์•ฑ์˜ ๋น„๋””์˜ค์™€ ์˜ค๋””์˜ค ์ปจํ…์ธ ๋ฅผ ๋…นํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.
    -> ๋งˆ์ดํฌ๋Š” ์‹œ์Šคํ…œ์—์„œ ์ง€์ •๋œ ๋งˆ์ดํฌ๋ฅผ ์ˆ˜์Œํ•œ๋‹ค.
  • ํ”„๋ฆฌ๋ทฐ์™€ ๊ณต์œ ํ•˜๊ธฐ ๊ธฐ๋Šฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ๋‹จ์ˆœํ•œ API ํ•ญ๋ชฉ๋“ค์€ iOS์™€ ๊ฐ™์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•จ
  • tvOS 10 ๋ถ€ํ„ฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

Live Broadcast

  • ์œ ์ €๋Š” ๋ณธ์ธ์˜ ๊ฒŒ์ž„ ํ”Œ๋ ˆ์ด๋ฅผ ์™ธ๋ถ€ ์ŠคํŠธ๋ฆฌ๋ฐ ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•ด์„œ iOS ํ˜น์€ tvOS ๋””๋ฐ”์ด์Šค๋ฅผ ํ†ตํ•ด ์ง์ ‘ ์ƒ๋ฐฉ์†ก ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • iOS๋Š” ์‹ค์‹œ๊ฐ„์œผ๋กœ FaceTime ์นด๋ฉ”๋ผ๋ฅผ ํ†ตํ•ด ๊ฒŒ์ž„ ํ”Œ๋ ˆ์ด์— ๋Œ€ํ•œ ํ•ด์„ค์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์˜ค๋””์˜ค์™€ ๋น„๋””์˜ค ๋ฐ์ดํ„ฐ๋Š” ๋งค์šฐ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌ๋œ๋‹ค.

1. Initiating a Broadcast

func didPressBroadcastButton() {
    RPBroadcastActivityViewController.load { broadcastAVC, error in
        if let broadcastAVC = broadcastAVC {
            broadcastAVC.delegate = self
            self.present(broadcastAVC, animated: true)
        }
    }
}
  • ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก์„ ์œ„ํ•ด, RPBroadcastActivityViewController ๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  • ๋˜ํ•œ, RPBroadcastActivityViewController์˜ ๊ฐ์ฒด๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด .load() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์ด๋ฅผ ํ†ตํ•ด ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ์•ฑ์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ํ™”๋ฉด์„ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Œ.
// RPBroadcastActivityViewControllerDelegate
func broadcastActivityViewController(
    _ broadcastAVC: RPBroadcastActivityViewController,
    didFinishWith broadcastContoller: RPBroadcastController,
    error: NSError?) {
        broadcastAVC.dismiss(animated: true) {
            self.startCountDownTimer {
                broadcastController?.startBroadcast { error in

                }
            }
        }
    }
)
  • ๋ฐฉ์†ก ์„œ๋น„์Šค๋ฅผ ์„ ํƒํ•˜๊ณ , ๋ฐฉ์†ก์‹œ์ž‘ ์ „ ์—ฌ๋Ÿฌ ์„ค์ •์„ ๋งˆ์น˜๊ฒŒ ๋˜๋ฉดRPBroadcastActivityViewControllerDelegate์˜ ํ•จ์ˆ˜์ธ broadcastActivityController๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
  • ํ•ด๋‹น ํ•จ์ˆ˜์—์„œ broadcastAVC๋ฅผ dismissํ•ด์ฃผ๊ณ , ์ผ์ • ์นด์šดํŠธ๋‹ค์šด ์ดํ›„ ๋ฐฉ์†ก์„ ์‹œ์ž‘ํ•œ๋‹ค.

2. Indicating a Broadcast

์‚ฌ์šฉ์ž๊ฐ€ ํ˜„์žฌ ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก์ค‘ ์ž„์„ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์—,
broadcastController?.isBroadcasting์„ ํ™œ์šฉํ•ด์„œ ๊ด€๋ จ UI๋ฅผ ๋…ธ์ถœ์‹œ์ผœ์ค˜์•ผํ•จ

3. Finish Broadcast

func didPressBroadcastButton() {
    self.broadcastController?.finishBroadcast { error in
        if error == nil {
            /// ๋ฐฉ์†ก ์ข…๋ฃŒ
            self.updateBroadcastUI()
        }
    }
}

// RPBroadcastActivityViewControllerDelegate
func broadcastActivityVeiwController(
    _ broadcastActivityViewController: RPBroadcastActivityViewController,
    didFinishWith broadcastController: RPBroadcastController,
    error: NSError?
) {
    self.broadcastController = broadcastController

    /// delegate๋ฅผ ์„ธํŒ…ํ•จ์œผ๋กœ์จ, error๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์Œ
    self.broadcastController?.delegate = self
}

// RPBroadcastControllerDelegate
func broadcastController(
    _ broadcastController: RPBroadcastContoller,
    didFinishWithError error: NSError?
) {
    if error != nil {
        self.showErrorMessage(text: error!.localizedDescription)
        self.updateBroadcastUI()
    }
}
func applicationWillResignActive() {
        // ReplayKit์€ ์ž๋™์œผ๋กœ ๋ฐฉ์†ก์„ ์ผ์‹œ ์ค‘์ง€ํ•˜๊ฒŒ ๋œ๋‹ค.
}

func applicationDidBecomeActive() {
	if self.broadcastController?.isBroadcasting == true {
		self.promptUserToResumeBroadcast { userWantsToResume in
			if userWantsToResume {	
            	self.broadcastController?.resumeBroadcast()
				self.updateBroadcastUI()
			} else {
            	self.broadcastController?.finishBroadcast { error in
                	self.updateBroadcastUI()
				}
			}
		}
	}
}
  • ์ถ”๊ฐ€์ ์œผ๋กœ, ์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ์„ background๋กœ ๋ณด๋‚ด๊ฑฐ๋‚˜ ์ „ํ™”๊ฐ€ ์˜ค๋Š” ๋“ฑ์˜ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋ฉด ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก์€ ์ž๋™์œผ๋กœ ์ผ์‹œ ์ค‘๋‹จ๋œ๋‹ค.
  • ๋”ฐ๋ผ์„œ, ๋‹ค์‹œ ์•ฑ์ด ํ™œ์„ฑํ™” ๋˜๋Š” ์‹œ์ ์— ์‚ฌ์šฉ์ž์—๊ฒŒ ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก์„ ๋‹ค์‹œ ์žฌ๊ฐœํ•  ๊ฒƒ์ธ์ง€ ๋ฌผ์–ด๋ด์•ผํ•œ๋‹ค.

Classes and Protocols

Game API

RPBroadcastActivityViewController

  • ํ˜„์žฌ ์„ค์น˜๋˜์–ด์žˆ๋Š” broadcast ์„œ๋น„์Šค๋“ค์„ ๋ณด์—ฌ์ค€๋‹ค
  • RPBroadcastActivityViewControllerDelegate
    • broadcast์˜ ์‹œ์ž‘ ์ค€๋น„๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์Œ์„ ์•Œ๋ ค์ฃผ๋Š” delegate

RPBroadcastController

  • broadcast๋ฅผ ์‹œ์ž‘ / ์ค‘์ง€ ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
  • ํ˜„์žฌ ๋ฐฉ์†ก์˜ ์ƒํƒœ(๋ฐฉ์†ก ์ค‘ ์ธ์ง€)๋ฅผ ์ฒดํฌํ•  ์ˆ˜ ์žˆ๋‹ค.
    • RPBroadcastControllerDelegate
      • broadcast์ค‘ ๋ฐœ์ƒํ•˜๋Š” error๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋Š” delegate

Broadcast Services

Broadcast UI Extension

  • broadcast๋ฅผ ์‚ฌ์šฉ์ž๊ฐ€ ์ค€๋น„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณด์—ฌ์ฃผ๋Š” UI

Broadcast Upload Extension

  • broadcast์˜ ๋น„๋””์˜ค / ์˜ค๋””์˜ค ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋กœ๋“œ ์ฒ˜๋ฆฌ ํ•ด์ฃผ๋Š” non-UI extension

Broadcast Extensions

  • ๋ถ€๋ชจ App์— Target์œผ๋กœ ์ž„๋ฒ ๋””๋“œํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.
  • ๋ณ„๋„์˜ App์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ถ€๋ชจ App๊ณผ๋Š” ์•„์˜ˆ ๋ถ„๋ฆฌ๋œ Process์—์„œ ์‹คํ–‰๋œ๋‹ค.
    • ํ•˜์ง€๋งŒ, ๋ถ€๋ชจ App๊ณผ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋˜ํ•œ, Extension์€ ๋ถ€๋ชจ App์— ๋น„ํ•ด ์ฃผ์–ด์ง„ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ œํ•œ์ ์ด๋‹ค.
    • ๋”ฐ๋ผ์„œ, ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•ด์•ผํ•จ

Xcode Templates

  • Add Target -> iOS/tvOS -> Application Extension -> Broadcast UI Extension & Broadcast Upload Extension

Xcode์˜ Target์— ์ถ”๊ฐ€ํ•˜๊ฒŒ ๋˜๋Š” Extensions ํ•ญ๋ชฉ์—์„œ ํ™•์ธ ๊ฐ€๋Šฅ

  • ์ƒ์„ฑํ•œ Extension์— ๋Œ€ํ•œ ์ „์ฒ˜๋ฆฌ(Pre-Configure)์ž‘์—…์ด ํ•„์š”ํ•˜๋‹ค๋ฉด, Extension์— ์ƒ์„ฑ๋œ info.plist์—์„œ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•˜๋‹ค.

1. Broadcast UI Extension

  • ์œ ์ € ์ธ์ฆ์„ ์ œ๊ณตํ•ด์•ผํ•จ (๋งŒ์•ฝ, ์ธ์ฆ ์ •๋ณด๊ฐ€ ์—†์œผ๋ฉด ํšŒ์›๊ฐ€์ž…๋„ ์ œ๊ณต)
    -> ์œ ์ € ์ž…์žฅ์—์„œ๋Š”, ๋ณ„๋„์˜ ์•ฑ์ธ์ง€ ๊ตฌ๋ถ„์„ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ˜ผ๋™์ด ์ผ์–ด๋‚˜์ง€ ์•Š์Œ
  • ์ด์šฉ์•ฝ๊ด€ ๋“ฑ์˜ ์ •๋ณด๋„ ์ด ๊ณณ์—์„œ ๋ณด์—ฌ์ค˜์•ผํ•œ๋‹ค.
  • ๋ฐฉ์†ก์ค€๋น„๊ณผ์ •๋„ ์ด ๊ณณ์—์„œ ์ง„ํ–‰ํ•ด์•ผํ•œ๋‹ค.
  • ๋ชจ๋“  ์ค€๋น„๊ฐ€ ์™„๋ฃŒ ๋˜์—ˆ๋‹ค๋ฉด, ์ค€๋น„์™„๋ฃŒ๊ฐ€ ๋˜์—ˆ์Œ์„ ReplayKit์—๊ฒŒ ์•Œ๋ ค์ค˜์•ผํ•œ๋‹ค.

2. Broadcast Upload Extension

  • ์ „๋‹ฌ๋ฐ›์€ ๋น„๋””์˜ค ๋ฐ ์˜ค๋””์˜ค ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์— uploadํ•ด์ฃผ๋Š” ๊ณผ์ •์„ ์ˆ˜ํ–‰
  • ์‹ค์ œ broadcast๋ฅผ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ๋กœ์ง๋“ค์„ ์ด ๊ณณ์—์„œ ์„ค๊ณ„ ๋ฐ ๊ตฌํ˜„ ํ•ด์•ผํ•จ

์•„๋ž˜์˜ ์‚ฌ์ง„์€, ๊ฐ Feature๋ณ„๋กœ ๋‹ด๋‹นํ•ด์•ผํ•˜๋Š” ์—ญํ• ๋“ค


Expanded Commentary Options

  • FaceTime ์นด๋ฉ”๋ผ๋ฅผ ์ง€์›ํ•œ๋‹ค
  if let cameraPreview = RPScreenRecorder.shared().cameraPreviewView {
      cameraPreview.frame = CGRect(...)
      self.view.addSubview(cameraPreview)
  }
  • ์œ ์—ฐํ•œ ์นด๋ฉ”๋ผ ๋…น์Œ ๊ธฐ๋Šฅ
  func enableMic {
      RPScreenRecorder.shared().isMicrophoneEnabled = true
  }

  func disableMic {
      RPScreenRecorder.shared().isMicrophoneEnabled = false
  }
  • iOS 10+ ์ ์šฉ
728x90
๋ฐ˜์‘ํ˜•
๋Œ“๊ธ€
๋ฐ˜์‘ํ˜•
๋งํฌ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
Total
Today
Yesterday