ㄷㅣㅆㅣ's Amusement

[iOS/Objective-C] Video Player tutorial using AVPlayer (AVFoundation) 본문

Programming/iOS

[iOS/Objective-C] Video Player tutorial using AVPlayer (AVFoundation)

ㄷㅣㅆㅣ 2016. 2. 23. 21:59

[iOS/Objective-C] Video Player tutorial using AVPlayer (AVFoundation)

오늘은 간단하게 아이폰/아이패드에서 비디오를 재생시키는 앱을 만들어보자.

Today's post is about simple Video Player on iPhone/iPad.


1. 안드로이드의 비디오 뷰와 같이 사용할 수 있도록 UIView를 상속받아 비디오 레이어를 붙여준다.

1. To use like an android video view, Inherit UIView and add the video layer to it.

1
2
3
4
5
6
@import AVFoundation;
#import <UIKit/UIKit.h>
 
@interface VideoView : UIView
@property (strong, nonatomic) AVPlayerLayer *videoLayer;
@end
cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#import "VideoView.h"
 
@implementation VideoView
- (void)setVideoLayer:(AVPlayerLayer *)videoLayer {
    _videoLayer = videoLayer;
    [self.layer addSublayer:_videoLayer];
}
 
- (void)layoutSublayersOfLayer:(CALayer *)layer {
    [super layoutSublayersOfLayer:layer];
 
    self.videoLayer.frame = CGRectMake(00, self.frame.size.width, self.frame.size.height);
}
 
@end
cs

 - 레이어는 비디오 뷰의 크기와 같게 조정한다.

 - Making layer size same with Video player's size.


2. AVPlayer를 이용하여 매우 심플한 비디오 플레이어 컨트롤러를 만든다.

2. Making Simple Video View Controller using AVPlayer in AVFoundation.

1
2
3
4
5
6
7
8
#import "TBaseViewController.h"
@import AVFoundation;
 
@interface VideoPlayerViewController : TBaseViewController
- (instancetype)initWithURL:(NSURL *)videoUrl;
- (instancetype)initWithAsset:(AVURLAsset *)videoAsset;
@end
 
cs

 - 초기화 단계에서 2가지 경우가 있는데, 외부의 동영상 파일(ex. streaming service)과 로컬파일이 초기화가 다르다.

 - There are 2 initiater. one is for external video file (ex. streaming service) another is for local files (in the camera roll)


 3. Implementation of init

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (instancetype)initWithURL:(NSURL *)videoUrl {
    self = [super init];
    if (self) {
        _videoPlayer = [AVPlayer playerWithURL:videoUrl];
    }
    
    return self;
}
 
- (instancetype)initWithAsset:(AVURLAsset *)videoAsset {
    self = [super init];
    if (self) {
        AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithAsset:videoAsset];
        _videoPlayer = [AVPlayer playerWithPlayerItem:playerItem];
    }
 
    return self;
}
cs

 1) url로 초기화하는 경우... AVPlayer가 매우 잘 되어있으므로 그대로 넣어주면 된다.

 1) if you initiate AVPlayer with NSURL, It is very simple because AVPlayer can play video which is stored in Web, cloud, External Storage, etc.

 2) 그러나 카메라 롤에 있는 파일을 재생할 경우에는 맞는URL을 넣어줘도 플레이하지는 않는다. 따라서 AVAsset으로 초기화 하는 함수를 만든다.

 2) but, if you need to play video file in local camera roll, You Should make a initiater that initiate AVPlayer using AVAsset.


 4. Video Layer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (void)viewDidLoad {
    [super viewDidLoad];
    
    //.....
    
    self.videoView.videoLayer = [AVPlayerLayer playerLayerWithPlayer:self.videoPlayer];
    
    // video infomations
    CMTime videoDuration = self.videoPlayer.currentItem.asset.duration;
    NSInteger videoDurationInSec = (long)videoDuration.value / videoDuration.timescale;
    [self.labelRemainTime setText:[Formatter timeFormat:videoDurationInSec]];
    [self.runningTimeSlider setMaximumValue:videoDurationInSec];
    [self.runningTimeSlider setValue:0];
}
cs

 - 뷰가 로드되면 AVPlayer의 비디오 레이어를 처음에 만들어놓았던 비디오 뷰의 레이어에 붙여준다.

 - When the View loaded, link AVPlayer's layer to VideoView we made before. and you can get Video information


 5. Audio Session and Video play.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
 
    [self showControlPanels];
    
    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:nil];
    self.prevCategory = [[AVAudioSession sharedInstance] category];
    [self registerObserver:@[AVPlayerItemDidPlayToEndTimeNotification]];
    
    [self playVideo];
}
 
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [[AVAudioSession sharedInstance] setCategory: self.prevCategory error:nil];
    [self unregisterObserver];
}
cs

 1) 일단 AVPlayer만 잘 초기화되면, 그 다음부터는 그냥 play함수를 호출하는 것 만으로도 비디오가 재생된다. 여기서는 자동으로 플레이 되도록 viewWillAppear에서 호출했다.

 1) Once you initiate well, you can just call "play" function. I want to play automatically when the view is appeared. so I call "play" in viewWillAppear.


 2) 오디오 세션을 AVAudioSessionCategoryPlayback으로 지정한다. 그래야 알람이나 노티가 왔을 때 프레임웤에서 자동으로 제어해준다. (안드로이드의 Music stream과 유사하다)

 2) if you make AVAudioSession to AVAudioSessionCategoryPlayback. and get back previous AVAudioSession when the video stopped. then, iOS audio framework can control the video/audio when alarm or phone call ringing. (AVAudioSessionCategoryPlayback is similar with Android's Music Stream)


 6. Getting AVAsset from PHAsset.

1
2
3
4
5
6
7
8
9
10
11
PHAsset *asset = [imageManager getAssetByLocalId:assetId];
if (asset) {
    [PhotoQueryHelper getAVAssetFromPHAsset:asset completionHandler:^(BOOL success, id responseObject) {
        AVURLAsset *avUrlAsset = responseObject;
        dispatch_async(dispatch_get_main_queue(), ^{
            VideoPlayerViewController *vpVC = [[VideoPlayerViewController alloc] initWithAsset:avUrlAsset];
            vpVC.thumbnailImage = [(UIImageView *)self.targetView image];
            [self.navigationController pushViewController:vpVC animated:NO];
        });
    }];
}
cs

 - 호출하는 쪽에서 AVAsset을 가져와서 초기화시켜준다.

 - Caller have to initiate the AVPlayer using AVAsset from PHAsset.


 7. 질문은 댓글로... 

 7. If you would like to know more, please reply me.

 



2 Comments
댓글쓰기 폼