AVPlayerLayer 사용, 비디오 썸네일 만들기
국내에 AVPlayer라는 앱이 있어서 AVFoundation 안에 포함된 AVPlayer의 정보를 찾기가 상당히 쉽지가 않다.
그래서 일단 제목은 "AVPlayerLayer 사용" 으로 했다.
AVPLayer 사용은 일단 MPMoviePlayerController 와 크게 다르지 않다.
MPMoviePlayerController 객체 선언후 MPMoviePlayerViewController 에 넣은 후 사용하면 되는데 AVPlayer도 마찬가지 이다.
* AVPLayer 사용
#import <AVFoundation/AVFoundation.h>
- (void)loadView {
[super loadView];
_url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"mp4"]];
UIView *playerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
playerView.backgroundColor = [UIColor blackColor];
{
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:_url];
AVPlayer *avPlayer = [AVPlayer playerWithPlayerItem:playerItem];
{
AVPlayerLayer *avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer: avPlayer];
avPlayerLayer.frame = CGRectMake(0, 0, 320, 480);
avPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
[playerView.layer addSublayer:avPlayerLayer];
[self.view addSubview:playerView];
}
avPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[ avPlayer currentItem]];
}
}
- (void)playerItemDidReachEnd:(NSNotification *)notification {
NSLog(@"video end");
}
단순하게 생각해서 AVPlayerLayer 안에 AVPlayer 넣고 이 AVPlayerLayer를 뷰의 Layer에 넣어주면 끝이다.
그리고 마지막에 영상의 재생이 끝날때 노티 설정해주면 끝.
* 비디오 썸네일 만들기
참고자료
1. 2010 WWDC의 AVFoundation
https://developer.apple.com/videos/wwdc/2010/ (로그인하면 꽁짜로 볼 수 있다.)
Session 405 - Discovering AV Foundation
Session 407 - Editing Media with AV Foundation
Session 409 - Using the Camera with AV Foundation
2. http://www.subfurther.com/
http://www.subfurther.com/blog/category/avfoundation/
VTM_AVEditor, VTM_Player
우선 썸네일을 만드는게 단순히 한장만 필요한게 아니라 한 비디오의 여러장(수십장)의 썸네일이 필요했다.
왜냐하면 내 목적은 아래의 UI를 만드는게 목적이었기 때문이었다.
이 UI를 기본적으로 제공하지 않기 때문에 고생을 좀 했다.
일단 상단 네비게이션바 아래에 있는 썸네일 이미지를 만들고 UISlider를 투명으로 놓은다음 그 UISlider의 배경을 썸네일로
넣어주고 UISlider가 이동하는 점과 AVPlayer 와 싱크를 맞춰주면 될 것 같다.
우선 썸네일을 생성하기 위해 AVURLAsset에 재생하려는 동영상의 파일 URL을 넣는다.
- (id)init
{
self = [super init];
if (self) {
_url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"mp4"]];
_asset = [AVURLAsset URLAssetWithURL:_url options:nil];
[self thumbCreate];
}
return self;
}
썸네일 생성
- (void)thumbCreate {
NSMutableArray *imageArr = [[NSMutableArray alloc]init];
_imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:_asset];
// 썸네일 이미지 생성할때 4개의 이미지를 생성
Float64 durationSeconds = CMTimeGetSeconds([_asset duration]);
CMTime firstThird = CMTimeMakeWithSeconds(durationSeconds/3.0, 600);
CMTime secondThird = CMTimeMakeWithSeconds(durationSeconds*2.0/3.0, 600);
CMTime end = CMTimeMakeWithSeconds(durationSeconds, 600);
NSArray *times = [NSArray arrayWithObjects:[NSValue valueWithCMTime:kCMTimeZero],
[NSValue valueWithCMTime:firstThird], [NSValue valueWithCMTime:secondThird],
[NSValue valueWithCMTime:end], nil];
// Async로 진행되는 썸네일 이미지 만드는 메소드
[_imageGenerator generateCGImagesAsynchronouslyForTimes:times
completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime
actualTime,
AVAssetImageGeneratorResult result, NSError
*error) {
NSString *requestedTimeString = (__bridge NSString *)
CMTimeCopyDescription (NULL, requestedTime);
NSString *actualTimeString = (__bridge NSString *)
CMTimeCopyDescription(NULL, actualTime);
NSLog(@"Requested: %@; actual %@", requestedTimeString,
actualTimeString);
// 이미지 배열에 비디오에서 추출한 이미지 넣기
_imageGenerator.maximumSize = CGSizeMake(66, 44);
[imageArr addObject:[UIImage imageWithCGImage:image]];
// 썸네일 이미지 만드는게 성공될 경우 여기로 호출
if (result == AVAssetImageGeneratorSucceeded) {
UIImageView *sliderImageView = [[UIImageView alloc]
initWithFrame: CGRectMake(0, 0, 320, 44)];
// 썸네일 이미지를 배열에 넣고 imageView에 넣는다.
for (NSInteger i = 0;i<[imageArr count];i++){
UIImageView *view = [[UIImageView alloc] initWithFrame:
CGRectMake(i*80, 0, 80, 44)];
[view setImage:[imageArr objectAtIndex:i]];
[sliderImageView addSubview:view];
}
[_sliderView addSubview:sliderImageView];
[_sliderView addSubview:_timeSlider];
}
if (result == AVAssetImageGeneratorFailed) {
NSLog(@"Failed with error: %@", [error
localizedDescription]);
}
if (result == AVAssetImageGeneratorCancelled) {
NSLog(@"Canceled");
}
}];
}
무조건 4개의 이미지를 만드는데 이 때 내가 보려는 동영상의 총 시간을 구하고 그 시간을 4등분 해서 각각 0, firstThird, SecondThird, end 로 구분하여 그 4개의 이미지를 생성하도록 했다.
슬라이더 설정
_sliderView = [[UIView alloc]initWithFrame:CGRectMake(0, 44, 320, 44)];
[_sliderView setBackgroundColor:[UIColor clearColor]];
{
_timeSlider = [[UISlider alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];
[_timeSlider setThumbTintColor:[UIColor clearColor]];
[_timeSlider setMaximumTrackImage:[UIImage imageNamed:@"slider.png"] forState:UIControlStateNormal];
[_timeSlider setMinimumTrackImage:[UIImage imageNamed:@"slider.png"] forState:UIControlStateNormal];
_timeSlider.value = 0;
[_sliderView addSubview:_timeSlider];
}
[self.view addSubview:_sliderView];
// avPlayer의 플레이타임과 slider의 타임의 싱크를 맞추기 위한 타이머
_sliderTimer = [NSTimer scheduledTimerWithTimeInterval:0.2
target:self
selector:@selector (updateSlider:)
userInfo:nil
repeats:YES];
슬라이더의 Maximum, Minimum의 트랙 이미지를 투명으로 놓고
그 뒤에 위에서 생성한 썸네일 이미지를 넣도록 한다.
-(void) timeSliderValueChanged: (id) sender {
CMTime newTime = CMTimeMakeWithSeconds(_timeSlider.value, 600);
[_avPlayer seekToTime: newTime];
// NSLog (@"seeking to %f", CMTimeGetSeconds(newTime));
}
// AVPlayer 와 Slider의 싱크를 맞춰주는 메소드
- (void) updateSlider :(id) sender {
_timeSlider.value = CMTimeGetSeconds(_avPlayer.currentTime);
}
애플에서 만든 비디오 플레이보다는 훨씬 못미치지만 일단 프로토타입으로 어느정도 느낌은 내 볼수 있었다.
AVFoundation 도 그렇게 어렵지 않았고 나름대로 재미있었다.
VideoPlayer 앱을 만들어서 배포해볼까(?) 라는 생각도 잠깐 해 볼 수 있었다.
소스코드 공개
'iOS' 카테고리의 다른 글
하위뷰 모두 제거 (0) | 2012.06.21 |
---|---|
UITabBarController Custom (0) | 2012.04.16 |
앱 - 앱 간 자료 전송 방법 2가지 (0) | 2012.04.03 |
iOS 전 기종(The new iPad 포함) 아이콘 사이즈 정의 (0) | 2012.03.15 |
APNS 사용 (0) | 2012.03.12 |