Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 스위프트
- HIG
- Protocol
- 리펙토링
- uitableview
- SWIFT
- swift documentation
- Clean Code
- MVVM
- UICollectionView
- collectionview
- Refactoring
- ios
- swiftUI
- clean architecture
- ribs
- uiscrollview
- Observable
- map
- tableView
- 리펙터링
- rxswift
- combine
- UITextView
- 리팩토링
- Xcode
- 클린 코드
- 애니메이션
- RxCocoa
- Human interface guide
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - Swift] PIP(Picture In Picture) 사용 방법 (AVPictureInPictureControllerDelegate, 유튜브 PIP) 본문
iOS 응용 (swift)
[iOS - Swift] PIP(Picture In Picture) 사용 방법 (AVPictureInPictureControllerDelegate, 유튜브 PIP)
jake-kim 2022. 12. 6. 22:39
PIP 모드 구현 방법
- iOS 14+
- Target -> Signing & Capabilities -> Capability -> Background 추가
- 아래 그림과 같이 Modes > Audio, AirPlay, and Picture in Picture 체크
- 테스트에 사용될 mp4 url 준비
- 테스터에 사용될, HTTP 통신으로 위 mp4를 가져와야 하므로 info.plist에서 ATS추가 후 Allow Arbitrary Loads를 Yes 설정
- ViewController에 필요한 AVKit, AVFoundation 임포트
import AVKit
import AVFoundation
- 필요한 UI 선언
- playerLayer: 비디오 화면이 들어갈 layer
- player: URL을 입력 받아서 플레이하는 인스턴스
- pipController: PIP 기능이 있는 컨트롤러이고, playerLayer를 주입해주면 바로 사용이 가능
class ViewController: UIViewController {
private let playerLayer = AVPlayerLayer()
private let player = AVPlayer()
private var pipController: AVPictureInPictureController?
private let button: UIButton = {
let button = UIButton(type: .system)
button.setTitle("pip 활성화", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
}
- pip 사용
- AVPlayerItem을 가지고 player에 mp4파일을 준 후 재생
- playerLayer의 player를 위 player로 지정
- AVPictureInPictureController에 playerLayer를 주입하면 완성
- (델리게이트는 아래에서 계속)
override func viewDidLoad() {
super.viewDidLoad()
setPip()
}
private func setPip() {
guard let url = URL(string: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4") else { return }
let asset = AVPlayerItem(url: url)
player.replaceCurrentItem(with: asset)
playerLayer.player = player
playerLayer.videoGravity = .resizeAspect
view.layer.addSublayer(playerLayer)
player.play()
guard AVPictureInPictureController.isPictureInPictureSupported() else { return }
pipController = AVPictureInPictureController(playerLayer: playerLayer)
pipController?.delegate = self
}
- playerLayer의 frame은 런타임시에 정해진 view의 크기만큼 넣어줄 것이므로 viewDidLayoutSubviews()에서 할당
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
playerLayer.frame = view.bounds
}
- PIP모드 활성화/끄기
- AVPictureInPictureController의 메소드 사용
- 끄기 - stopPictureInPicture()
- 켜기 - startPictureInPicture()
@objc func tapButton() {
guard let isActive = pipController?.isPictureInPictureActive else { return }
isActive ? pipController?.stopPictureInPicture() : pipController?.startPictureInPicture()
isActive ? button.setTitle("비활성화", for: .normal) : button.setTitle("활성화", for: .normal)
}
- 델리게이트 AVPictureInPictureControllerDelegate
- 위에서 설정한 pipController?.delegate = self 델리게이트
- pip 버튼을 눌렀을때 willStart, didStart
- 중지할때 willStop, didStart
- 작아진 pip화면을 다시 키울때 restore
extension ViewController: AVPictureInPictureControllerDelegate {
func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
print("willStart")
}
func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
print("didStart")
}
func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) {
print("error")
}
func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
print("willStop")
}
func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
print("didStop")
}
func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
print("restore")
}
}
* 전체 코드: https://github.com/JK0369/ExPip
* 참고
https://jplanet89.tistory.com/entry/PictureInPicture
https://developer.apple.com/documentation/avkit/adopting_picture_in_picture_in_a_custom_player
'iOS 응용 (swift)' 카테고리의 다른 글
Comments