iOS AVPlayer 영상 재생 예제
CustomPlayerController.h
스토리보드에서 만든 버튼 및 뷰, 슬라이더를 컨트롤러와 이어주고 필요한 메소드 선언.
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface CustomPlayerController : UIViewController
@property (strong, nonatomic) IBOutlet UIButton *doneButton; //닫기
@property (strong, nonatomic) IBOutlet UIView *controlView; //컨트롤러 뷰
@property (strong, nonatomic) IBOutlet UIButton *playBackButton; //재생 버튼
@property (strong, nonatomic) IBOutlet UIButton *seekBackButton; //뒤가기 버튼
@property (strong, nonatomic) IBOutlet UIButton *seekFwdButton; //앞으로 가기 버튼
@property (strong, nonatomic) IBOutlet UILabel *progressLabel; //재생중시간
@property (strong, nonatomic) IBOutlet UILabel *totalTimeLabel; //전체 러닝 타임
@property (strong, nonatomic) IBOutlet UISlider *timeSlider; //타임 슬라이더
@property (nonatomic, assign) BOOL isPlaying; //재생 여부
@property (nonatomic, strong) NSTimer *controlTimer; //타이머[1]
@property (nonatomic, strong) NSTimer *updateTimer; //타이머[2]
@property (nonatomic, strong) AVPlayer *player; //플레이어
@property (nonatomic, strong) AVPlayerItem *playerItem; //플레이할 아이템
@property (nonatomic, assign) BOOL controlsVisible;
//액션 메소드
- (IBAction)seekForward:(id)sender;
- (IBAction)seekBack:(id)sender;
- (IBAction)toglePlayback:(id)sender;
- (IBAction)sliderChange:(UISlider *)sender;
- (IBAction)done:(id)sender;
-(void) play;
-(id)initWithContentURL:(NSURL *) contentURL;
@end
NS_ASSUME_NONNULL_END
CustomPlayerController.m
재생, 앞으로 감기, 뒤로감기, 정지, 슬라이더 이동관련 함수 작성
#import "CustomPlayerController.h"
@interface CustomPlayerController ()
@end
@implementation CustomPlayerController
//1.초기자 메소드
-(id)initWithContentURL:(NSURL *)contentURL
{
//스토리 보드 -> CustomPlayerController 접근 (identifier 명 지정 필수!)
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
CustomPlayerController *myViewController = [storyBoard instantiateViewControllerWithIdentifier:@"CustomPlayerController"];
self = myViewController;
if (self) {
//플레이어 초기화
self.playerItem = [[AVPlayerItem alloc] initWithURL:contentURL];
self.player = [AVPlayer playerWithPlayerItem:self.playerItem];
//KVO - 플레이어 상태 계속 체크
[self.player addObserver:self forKeyPath:@"status" options:0 context:nil];
self.isPlaying = NO;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (IBAction)toglePlayback:(id)sender {
//플레이어 정지 시키기
if (self.isPlaying) {
[self.player pause];
[self.playBackButton setTitle:@"재생" forState:UIControlStateNormal];
//[self showControlles:nil];
[self.updateTimer invalidate];
//플레이어 재생
}else{
[self.player play];
[self.playBackButton setTitle:@"정지" forState:UIControlStateNormal];
self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateProcess) userInfo:nil repeats:YES];
}
self.isPlaying = !self.isPlaying;
}
//프로그래스바 정보 업데이트
-(void)updateProcess{
//1.전체 러닝 타임 [분 : 초]
int durationMinutes = CMTimeGetSeconds([self.playerItem duration]) / 60;
int durationSeconds = CMTimeGetSeconds([self.playerItem duration]) - durationMinutes * 60;
//2.현재 시간 [분 : 초]
int currentTimeMinutes = CMTimeGetSeconds([self.playerItem currentTime]) / 60;
int currentTImeSeconds = CMTimeGetSeconds([self.playerItem currentTime]) - currentTimeMinutes * 60;
//3.타임 슬라이스 이동
self.timeSlider.value = CMTimeGetSeconds([self.playerItem currentTime]) / CMTimeGetSeconds([self.playerItem duration]);
//+ 0.0f;
//4.현재 러닝 타임
self.progressLabel.text = [NSString stringWithFormat:@"%02i:%02i",
currentTimeMinutes , currentTImeSeconds];
//5.전체 러닝 타임
self.totalTimeLabel.text = [NSString stringWithFormat:@"%02i:%02i",
durationMinutes , durationSeconds];
}
//컨트롤러 숨기게
-(void)hideControls:(id)sender{
NSLog(@"hideControls - ");
NSLog(@"self.controlsVisible : %d" , self.controlsVisible);
if (self.controlsVisible) {
[self.view sendSubviewToBack:self.controlView];
self.controlView.userInteractionEnabled = NO;
self.controlsVisible = NO;
}else{
[self showControlles:nil];
}
}
//컨트롤러 보이게
-(void)showControlles:(id) sender{
NSLog(@"showControlles - ");
NSLog(@"self.controlsVisible : %d" , self.controlsVisible);
NSLog(@"self.controlTimer: %@" , self.controlTimer);
if(self.controlTimer != nil){
[self.controlTimer invalidate];
}
//컨트롤러 뷰 앞으로 가져오기
[self.view bringSubviewToFront:self.controlView];
self.controlView.userInteractionEnabled = YES;
//컨트롤러 2초뒤 종료
self.controlTimer = [NSTimer scheduledTimerWithTimeInterval:2.0f target:self selector:@selector(hideControls:) userInfo:nil repeats:NO];
//보여있는 상태
self.controlsVisible = YES;
}
//KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
//관찰하려는 key 가 player 의 status 일때
if (object == self.player && [keyPath isEqualToString:@"status"]) {
//플레이어가 준비된 상태이면
if (self.player.status == AVPlayerStatusReadyToPlay) {
NSLog(@"AVPlayerStatusReadyToPlay - 준비완료");
//플레이어 레이어 설정
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
playerLayer.frame = self.view.bounds;
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
[self.view.layer addSublayer:playerLayer];
playerLayer.needsDisplayOnBoundsChange = YES;
self.view.layer.needsDisplayOnBoundsChange = YES;
//컨트롤러 보이기
//[self showControlles:nil];
//2초뒤 숨기기
//self.controlTimer = [NSTimer scheduledTimerWithTimeInterval:2.0f target:self selector:@selector(hideControls:) userInfo:nil repeats:NO];
NSDictionary *userDict = [NSDictionary dictionaryWithObject:@"ready" forKey:@"status"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"customPlayerLoadStateChanged" object:self userInfo:userDict];
}else{
NSDictionary *userDict = [NSDictionary dictionaryWithObject:@[@"error" , @"unable to load file"] forKey:@[@"status" , @"reason"]];
[[NSNotificationCenter defaultCenter] postNotificationName:@"customPlayerLoadStateChanged" object:self userInfo:userDict];
}
[self.player removeObserver:self forKeyPath:@"status"];
}
}
//앞으로 감기
- (IBAction)seekForward:(id)sender {
//전체 시간
Float64 duration =CMTimeGetSeconds([self.playerItem duration]);
//현재 시간
Float64 currentTime = CMTimeGetSeconds([self.playerItem currentTime]);
//현재 시간 + 5
Float64 desiredTime = currentTime + 5.0;
//
if (desiredTime < duration) {
//이동할 시간
CMTime seekTime = CMTimeMake(desiredTime, 1);
[self.player seekToTime:seekTime];
//프로그레스바 업데이트
[self updateProcess];
}
}
//뒤로 감기
- (IBAction)seekBack:(id)sender {
//현재 시간
Float64 currentTime = CMTimeGetSeconds([self.playerItem currentTime]);
//현재시간 - 5
Float64 desiredTime = currentTime - 5.0;
if (desiredTime < 0) {
desiredTime = 0;
}
CMTime seekTime = CMTimeMake(desiredTime, 1);
[self.player seekToTime:seekTime];
//프로그레스바 업데이트
[self updateProcess];
}
//슬라이더 체인지
- (IBAction)sliderChange:(UISlider *)sender {
//이동시킨 프로그레스바 값
float progress = sender.value;
NSLog(@"progress.value : %f" , progress);
//전체시간
NSInteger durationSeconds = CMTimeGetSeconds([self.playerItem duration]);
NSLog(@"전체 시간 : %ld" , (long)durationSeconds);
//이동시간 프로그레스바 값 * 플레이어 전체시간
float result = durationSeconds * progress;
NSLog(@"result : %f" , result);
//찾을 시간
CMTime seekTime = CMTimeMakeWithSeconds(result, 1);
//플레이어의 특정시간값을 이용해서 영상재생 위치 찾기
[self.player seekToTime:seekTime];
}
//닫기
- (IBAction)done:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
@end
ViewController 에서 호출해서 사용
//플레이어 컨트롤러 호출
- (IBAction)showPlayerVC:(id)sender {
//플레이어 세그 호출
//[self performSegueWithIdentifier:@"PlayerSegue" sender:sender];
//파일 경로
NSBundle *bundle = [NSBundle mainBundle];
NSURL *moveURL = [bundle URLForResource:@"a" withExtension:@"mov"];
//플레이어 객체 생성
self.moviePlayer = [[CustomPlayerController alloc] initWithContentURL:moveURL];
//full screen 으로 열기
[self.moviePlayer setModalPresentationStyle:UIModalPresentationFullScreen];
//플레이어 열기
[self presentViewController:self.moviePlayer animated:NO completion:^{
NSLog(@"플레이어 열림");
}];
}
drive.google.com/file/d/1knad3mYhVSqRA1-5l4a_Sybx9jhhupTa/view?usp=sharing
참고
wnstkdyu.github.io/2018/05/03/avfoundationprogrammingguide/
'아이폰 개발 > ios 개념&튜토리얼' 카테고리의 다른 글
CGContextRef 예제 - 그림 그리기 (0) | 2021.02.22 |
---|---|
iOS 카테고리 예제 - (UIColor 확장하기) (0) | 2021.02.21 |
iOS CLLocation 위도경도, 속도, 이동거리 구하기 (0) | 2021.02.18 |
iOS 애플 중간 인증서 (0) | 2021.02.18 |
iOS 애플로그인 - Apple Login 예제 (1) | 2021.02.17 |