iOS 에서 영상 재생 의 기본 방법 요약

머리말
본 고 는 iOS 에서 가장 흔히 볼 수 있 는 영상 재생 방법 을 정리 하고 서로 다른 방법 이 모두 특징 을 가지 기 때문에 저 는 그들의 차이 점 을 정리 하고 개발 에서 적당 한 기술 방안 을 선택 하 는 데 편리 하 기 를 바 랍 니 다.
애플 은 MPMoviePlayer Controller,MPMoviePlayer View Controller,AVPlayer,AVPlayer View Controller 등 다양한 방법 을 제공 했다.주의해 야 할 것 은 상기 MPMoviePlayerController 와 MPMoviePlayerViewController 가 iOS 9.0 이후 버 려 졌 다 는 점 이다.그럼 에 도 불구 하고 이것 은 그들의 용법 을 정리 한 것 입 니 다.다음은 네 가지 재생 방식 의 차 이 를 간단하게 알 아 보 겠 습 니 다.

iOS 동 영상 재생.png
훈훈 한 알림:코드 가 더욱 직관 적 이 므 로 먼저 본문 Demo 를 첨부 합 니 다. ( 로 컬 다운로드
1.MPMoviePlayerController
1.동 영상 재생
MPMovie wPlayerController 는 NSObject 에 계승 되 어 동 영상 을 재생 하려 면 보기 컨트롤 러 의 View 에 비디오 View 를 추가 해 야 동 영상 을 표시 할 수 있 습 니 다.사용 절 차 는 다음 과 같 습 니 다.

   :  MediaPlayer  ,         PlayerController
#import <mediaplayer mediaplayer.h>

@property(nonatomic,strong)MPMoviePlayerController *playerController;

//   :      ,     
//      
NSString* localFilePath=[[NSBundle mainBundle]pathForResource:@"      " ofType:@"mp4"];
NSURL *localVideoUrl = [NSURL fileURLWithPath:localFilePath];
//      
NSString *webVideoPath = @"http://api.junqingguanchashi.net/yunpan/bd/c.php?vid=/junqing/1115.mp4";
NSURL *webVideoUrl = [NSURL URLWithString:webVideoPath];
self.playerController =[[MPMoviePlayerController alloc]initWithContentURL:webVideoUrl];

//   :  Frame    View        View 
self.playerController.view.frame = CGRectMake(0, 10, kDeviceWidth, 300);
[self.view addSubview: self.playerController.view];

//   :       
//        : ,  ,  ,  
self.playerController.controlStyle = MPMovieControlStyleDefault;
//        (   YES)
self.playerController.shouldAutoplay = NO;
//         ,        ,  Fill            
self.playerController.scalingMode = MPMovieScalingModeAspectFit;
//      
self.playerController.repeatMode = MPMovieRepeatModeOne;

//   :    
//      ,              
[ self.playerController prepareToPlay];
//    ,                 
//[ self.playerController play];

//   :        ,     ,    
- (void)dealloc{
 //       pop         ,      
 [self.playerController stop];
 self.playerController = nil;
 //          
 [[NSNotificationCenter defaultCenter] removeObserver:self];
}
2.동 영상 재생 관련 알림
MPMoviePlayer Controller 와 관련 된 영상 재생 의 많은 상태 통 제 는 알림 을 통 해 이 루어 집 니 다.특히 온라인 영상 을 재생 할 때 저 희 는 영상 로드 의 성공 여 부 를 감시 할 뿐만 아니 라 영상 캐 시 진도 등 도 모니터링 합 니 다.여기 서 자주 사용 하 는 알림 을 다음 과 같이 보 여 줍 니 다.

//       (          ,   SDK)
NSNotificationCenter *notificaionCenter = [NSNotificationCenter defaultCenter];
//          
[notificaionCenter addObserver:self
 selector:@selector(playerStateChanged:)
 name:MPMoviePlayerPlaybackStateDidChangeNotification
 object:nil];
//      
[notificaionCenter addObserver:self
 selector:@selector(playerFinished) name:MPMoviePlayerPlaybackDidFinishNotification
 object:nil];
//       
[notificaionCenter addObserver:self
 selector:@selector(palyerChangeFullScreen) name:MPMoviePlayerDidEnterFullscreenNotification
 object:nil];
//        
[notificaionCenter addObserver:self
 selector:@selector(playerCaptureFinished:) name:MPMoviePlayerThumbnailImageRequestDidFinishNotification
 object:nil];

#pragma mark -          
//      ,             
- (void)playerStateChanged:(NSNotification *)notificaion{
 switch (self.playerController.playbackState) {
 case MPMoviePlaybackStateStopped:{
 NSLog(@"    ");
 break;
 }
 case MPMoviePlaybackStatePlaying:{
 NSLog(@"       ");
 break;
 }
 case MPMoviePlaybackStatePaused:{
 NSLog(@"     ");
 break;
 }
 case MPMoviePlaybackStateInterrupted:{
 NSLog(@"     ");
 break;
 }
 case MPMoviePlaybackStateSeekingForward:{
 NSLog(@"     ");
 break;
 }
 case MPMoviePlaybackStateSeekingBackward:{
 NSLog(@"     ");
 break;
 }
 default:
 break;
 }
}

//      
- (void)playerFinished{
 NSLog(@"playerFinished:    ");
}

//         
- (void)palyerChangeFullScreen{
 NSLog(@"palyerChangeFullScreen:       ");
}

//       
- (void)playerCaptureFinished:(NSNotification *)notification{
 //       
 UIImage *image=notification.userInfo[MPMoviePlayerThumbnailImageKey];
 self.captureImgView.image = image;
}
3.캡 처 실현

//      ,      
_captureBtn = [[UIButton alloc] initWithFrame:CGRectMake(30, CGRectGetMaxY(self.playerController.view.frame) + 30, kDeviceWidth - 30 * 2, 50)];
_captureBtn.backgroundColor = [UIColor purpleColor];
[_captureBtn setTitle:@"      " forState: UIControlStateNormal];
[_captureBtn addTarget:self action:@selector(captureCurrentScreenImg) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_captureBtn];
//    ImgView         
_captureImgView = [[UIImageView alloc] initWithFrame:CGRectMake((kDeviceWidth - 150)/2, CGRectGetMaxY(_captureBtn.frame) + 20, 150, 150)];
 _captureImgView.contentMode = UIViewContentModeScaleAspectFit;
_captureImgView.backgroundColor = [UIColor grayColor];
[self.view addSubview:_captureImgView];

//      
- (void)captureCurrentScreenImg{
 [self.playerController requestThumbnailImagesAtTimes:@[@(self.playerController.currentPlaybackTime)] timeOption:MPMovieTimeOptionNearestKeyFrame];
}

//    :       ,         
- (void)playerCaptureFinished:(NSNotification *)notification{
 UIImage *image=notification.userInfo[MPMoviePlayerThumbnailImageKey];
 self.captureImgView.image = image;
}
2.MPMoviePlayerViewController
MPMovicePlayerViewController 는 전체 화면 에서 만 영상 을 재생 할 수 있 습 니 다.MPMoviePlayerController 형식 속성 을 포함 하 는 특수 보기 컨트롤 러 이기 때문에 모드 보기 팝 업 방식 으로 영상 을 표시 합 니 다.이 를 이해 하면 우 리 는 MPMovicePlayerViewController 를 사용 할 때 우 리 는 그의 MPMoviePlayerController 속성 을 통 해 많은 플레이어 의 속성 을 설정 할 수 있다 는 것 을 알 수 있다.구체 적 인 용법 은 MPMoviePlayerController 와 같 지만 많은 설명 에 불과 하 다.동 영상 을 재생 하 는 코드 예 는 다음 과 같다.

//   :      
//    
NSString* localFilePath=[[NSBundle mainBundle]pathForResource:@"      " ofType:@"mp4"];
NSURL *localVideoUrl = [NSURL fileURLWithPath:localFilePath];
//    
//NSString *webVideoPath = @"http://api.junqingguanchashi.net/yunpan/bd/c.php?vid=/junqing/1115.mp4";
//NSURL *webVideoUrl = [NSURL URLWithString:webVideoPath];

//   :       
MPMoviePlayerViewController *playerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:localVideoUrl];

//   :       
//  moviePlayer         ( MPMoviePlayerController  )
playerViewController.moviePlayer.scalingMode = MPMovieScalingModeFill;

//   :        
[self presentViewController:playerViewController animated:YES completion:nil];
3.AVPlayer
AVPlayer 는 상기 두 가지 방식 에 비해 영상 재생 기능 이 더욱 강하 고 사용 도 유연 하 다.왜냐하면 이것 은 밑바닥 에 더욱 가 깝 기 때문이다.그러나 AVPlayer 자 체 는 동 영상 을 직접 표시 할 수 없습니다.재생 층 AVPlayer Layer 를 만 들 고 다른 보기 Layer 에 추가 해 야 표시 할 수 있 습 니 다.
1.AVPlayer 를 사용 할 때 알 아야 할 상용 클래스
  • AVAsset:멀티미디어 정 보 를 얻 는 데 사용 되 는 추상 적 인 유형 이지 만 직접 사용 할 수 없다
  • AVURLASset:AVAsset 의 하위 클래스 는 하나의 URL 경로 에 따라 미디어 정 보 를 포함 하 는 AVURLASset 대상 을 만 들 수 있 습 니 다
  • AVPlayerItem:한 미디어 자원 관리 대상 은 영상의 기본 정보 와 상 태 를 관리 하 는 데 사용 되 고 하나의 AVPlayerItem 은 하나의 영상 자원 에 대응 합 니 다
  • AVPlayer:영상 재생,일시 정지,시간 제어 등 을 담당 합 니 다
  • AVPlayerLayer:동 영상 을 표시 하 는 그래 픽 을 담당 합 니 다.이 속성 을 설정 하지 않 으 면 동 영상 은 소리 만 있 고 이미지 가 없습니다
  • 2.AVPlayer 사용 절차
    
    //   :  AVFoundation  ,       
    #import <AVFoundation/AVFoundation.h>
    @property (nonatomic,strong)AVPlayer *player;//     
    @property (nonatomic,strong)AVPlayerItem *currentPlayerItem;
    
    //   :      URL
    //      
    NSString* localFilePath=[[NSBundle mainBundle]pathForResource:@"      " ofType:@"mp4"];
    NSURL *localVideoUrl = [NSURL fileURLWithPath:localFilePath];
    //      
    NSString *webVideoPath = @"http://api.junqingguanchashi.net/yunpan/bd/c.php?vid=/junqing/1129.mp4";
    NSURL *webVideoUrl = [NSURL URLWithString:webVideoPath];
    
    //   :     (    )
    //    URL         AVPlayer    AVPlayerItem
    //self.player = [AVPlayer playerWithURL:localVideoUrl];
    //self.player = [[AVPlayer alloc] initWithURL:localVideoUrl];
    //self.player = [AVPlayer playerWithPlayerItem:playerItem];
    AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:webVideoUrl];
    self.currentPlayerItem = playerItem;
    self.player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
    
    //   :       AVPlayerLayer,        ,       
    //contentView     View,        
    /*
     AVLayerVideoGravityResizeAspectFill     ,         
     AVLayerVideoGravityResizeAspect       
     AVLayerVideoGravityResize       
    */
    AVPlayerLayer *avLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
    avLayer.videoGravity = AVLayerVideoGravityResizeAspect;
    avLayer.frame = _containerView.bounds;
    [_containerView.layer addSublayer:avLayer];
    
    //   :  play  ,    
    //          
    //        AVPlayerItem status   AVPlayerStatusReadyToPlay       
    [self.player play];
    3.속성 관찰 추가
    AVPlayer Item 대상 이 동 영상 에 대응 하고 있 습 니 다.저 희 는 AVPlayer Item 을 통 해 동 영상 속성 을 가 져 와 야 합 니 다.그러나 AVPlayer Item 은 재생 이 가능 할 때 까지 비디오 자원 을 불 러 와 야 사용 할 수 있 는데 이것 은 네트워크 에 제 한 된 이유 이다.이 문 제 를 해결 하려 면 AVPlayer Item 의 status 속성 을 KVO 로 모니터링 해 야 합 니 다.AVPlayer Item Status Ready ToPlay 일 때 영상 관련 속성 을 얻 을 수 있 습 니 다.관련 코드 예 시 는 다음 과 같다.
    
    //1.     ,       
    //  Status  ,                
    [self.player.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    //  loadedTimeRanges,        ,       
    [self.player.currentItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
    
    //2.      
    - (void)observeValueForKeyPath:(NSString *)keyPath
      ofObject:(id)object
      change:(NSDictionary *)change
      context:(void *)context {
     AVPlayerItem *playerItem = (AVPlayerItem *)object;
     if ([keyPath isEqualToString:@"status"]) {
     //  playerItem status       
     AVPlayerStatus status = [[change objectForKey:@"new"] intValue];
     switch (status) {
     case AVPlayerStatusReadyToPlay:{
     //      
     CMTime duration = playerItem.duration; 
     //    :     (            )
     self.totalNeedPlayTimeLabel.text = [self formatTimeWithTimeInterVal:CMTimeGetSeconds(duration)];
     //         
     self.sliderView.enabled = YES;
     //    Loading  
     [self showaAtivityInDicatorView:NO];
     //      
     [self.player play];
     break;
     }
     case AVPlayerStatusFailed:{//      ,      
     [self showaAtivityInDicatorView:NO];//  Loading  
     self.playerInfoButton.hidden = NO; //        ,         
     [self.playerInfoButton setTitle:@"      ,        " forState: UIControlStateNormal];
     break;
     }
     case AVPlayerStatusUnknown:{
     NSLog(@"        :AVPlayerStatusUnknown");
     break;
     }
     default:
     break;
     }
     } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
     //          ,              
     NSArray *loadedTimeRanges = playerItem.loadedTimeRanges;
     //         
     CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];
     //          
     NSTimeInterval loadStartSeconds = CMTimeGetSeconds(timeRange.start);
     //       
     NSTimeInterval loadDurationSeconds = CMTimeGetSeconds(timeRange.duration);
     //           
     NSTimeInterval currentLoadTotalTime = loadStartSeconds + loadDurationSeconds;
     //NSLog(@"    :%f,    :%f,   :%f", loadStartSeconds, loadDurationSeconds, currentLoadTotalTime);
     //    :       
     _currentLoadTimeLabel.text = [self formatTimeWithTimeInterVal:currentLoadTotalTime];
     //    :      
     _totalNeedLoadTimeLabel.text = [self formatTimeWithTimeInterVal:CMTimeGetSeconds(self.player.currentItem.duration)];
     //    :       
     _progressView.progress = currentLoadTotalTime/CMTimeGetSeconds(self.player.currentItem.duration);
     }
    }
    
    //         
    - (NSString *)formatTimeWithTimeInterVal:(NSTimeInterval)timeInterVal{
     int minute = 0, hour = 0, secend = timeInterVal;
     minute = (secend % 3600)/60;
     hour = secend / 3600;
     secend = secend % 60;
     return [NSString stringWithFormat:@"%02d:%02d:%02d", hour, minute, secend];
    }
    4.현재 재생 시간 과 총 시간 가 져 오기
    그 전에 우 리 는 먼저 데이터 형식 을 알 아야 한다.즉,상기 작업 중의 CMTime 이다.AVPlayer 의 사용 에서 우 리 는 이 를 자주 사용 할 것 이다.사실은 CMTime 은 다음 과 같은 구조 체 이다.
    
     typedef struct{
     CMTimeValue value; //   
     CMTimeScale timescale; //   (       )
     CMTimeFlags flags;
     CMTimeEpoch epoch;
     } CMTi
    위의 작업 에서 우 리 는 AVPlayer Item 의 Duration 속성 이 바로 CMTime 형식의 데이터 라 는 것 을 보 았 다.따라서 동 영상 을 가 져 오 는 총 시간(초)은 duration.value/duration.timescale 이 필요 합 니 다.물론 시스템 도 우리 에 게 CMTimeGetSeconds 함 수 를 제공 하여 계산 하기에 더욱 편리 하 다.
    총 시간:duration.value=CMTimeGetSeconds(duration).
    동 영상 이 어느 위치 에 들 어 갈 때 도 CMTime 을 매개 변수 로 만들어 야 합 니 다.그러면 CMTime 의 생 성 방법 은 두 가지 가 있 습 니 다.
    
    //  1:
    CMTimeMakeWithSeconds(Flout64 seconds, int32_t scale)
    //  2:
    CMTimeMake(int64_t value, int32_t scale)
    // :                   float
    동 영상 을 가 져 오 는 총 시간 은 상기 코드 에 나타 나 는데 재생 상태 가 AVPlayer Status Ready ToPlay 로 바 뀌 었 을 때 가 져 온 것 입 니 다.
    
    //     , AVPlayerItem   AVPlayerStatusReadyToPlay   
    CMTime duration = self.player.currentItem.duration;
    CGFloat totalTime = CMTimeGetSeconds(duration);
    //  AVPlayer     
    CMTime cmTime = self.player.currentTime;
    CGFloat currentTime = CMTimeGetSeconds(cmTime);
    5.재생 진도 와 상태 리 셋
    현재 재생 시간 을 실시 간 으로 업데이트 합 니 다.이때 우 리 는 타 이 머 를 사용 할 필요 가 없습니다.왜냐하면 AVPlayer 가 이미 방법 을 제 공 했 기 때 문 입 니 다.
    addPeriodicTimeObserverForInterval: queue: usingBlock。재생 진도 가 바 뀌 었 을 때 방법 중의 리 셋 이 실 행 됩 니 다.우 리 는 여기에서 새로 고침 시간 을 조작 할 수 있 습 니 다.코드 예 시 는 다음 과 같 습 니 다.
    
    __weak __typeof(self) weakSelf = self;
    [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
     //       
     NSTimeInterval currentTime = CMTimeGetSeconds(time);
     //      
     NSTimeInterval totalTime = CMTimeGetSeconds(weakSelf.player.currentItem.duration);
     //         
     weakSelf.sliderView.value = currentTime/totalTime;
     //       : 00:00:00   
     weakSelf.currentTimeLabel.text = [weakSelf formatTimeWithTimeInterVal:currentTime];
     }];
    6.슬라이더 드래그 로 비디오 재생 진행 수정
    
    //UISlider     :    ,      
    - (IBAction)sliderViewChange:(id)sender {
     if(self.player.status == AVPlayerStatusReadyToPlay){
     NSTimeInterval playTime = self.sliderView.value * CMTimeGetSeconds(self.player.currentItem.duration);
     CMTime seekTime = CMTimeMake(playTime, 1);
     [self.player seekToTime:seekTime completionHandler:^(BOOL finished) {
     }];
     }
    }
    4.AVPlayerViewController
    AVPlayerViewController 는 iOS 8 에 추 가 된 비디오 프레임 워 크 AVKit 의 플레이어 클래스 입 니 다.iOS 9 가 앞의 두 가지 플레이어 류 를 버 리 는 이유 로 AVPlayerViewController 도 더욱 자주 사용 된다.AVPlayerViewController 는 재생 인터페이스 개발 에 적합 하 며 요구 가 높 지 않 은 응용 프로그램 입 니 다.AVPlayer 보다 사용 이 편리 하지만 원리 적 으로 는 AVPlayer ViewController 에 AVPlayer 대상 이 포함 되 어 있 습 니 다.
    AVPlayerViewController 는 동 영상 을 재생 하 는 두 가지 방식 이 있 습 니 다.
    첫 번 째:직접 팝 업 모드 보기 컨트롤 러 재생
    
    //  1:      
    NSString *webVideoPath = @"http://api.junqingguanchashi.net/yunpan/bd/c.php?vid=/junqing/1213.mp4";
    NSURL *webVideoUrl = [NSURL URLWithString:webVideoPath];
    //  2:  AVPlayer
    AVPlayer *avPlayer = [[AVPlayer alloc] initWithURL:webVideoUrl];
    //  3:  AVPlayer  AVPlayerViewController,       
    AVPlayerViewController *avPlayerVC =[[AVPlayerViewController alloc] init];
    avPlayerVC.player = avPlayer;
    [self presentViewController:avPlayerVC animated:YES completion:nil];
    두 번 째:AVPlayerViewController 의 View 를 부모 보기에 추가 하여 재생 합 니 다.
    이러한 방식 으로 재생 하 는 장점 은 재생 인터페이스의 원본 크기 를 지정 할 수 있다 는 것 이다.그러나 주의해 야 할 것 은 AVPlayerViewController 가 현재 보기 컨트롤 러 에 의 해 가지 고 있어 야 국부 변수 로 방출 되 는 것 을 방지 해 야 한 다 는 것 이다.이 조건 을 만족 시 키 기 위해 저 희 는 AVPlayerViewController 를 속성 으로 할 수도 있 고 addChildViewController 방법 으로 현재 보기 컨트롤 러 의 하위 보기 컨트롤 러 로 할 수도 있 습 니 다.예제 코드 는 다음 과 같 습 니 다.
    
    //  1:      
    NSString *webVideoPath = @"http://api.junqingguanchashi.net/yunpan/bd/c.php?vid=/junqing/1213.mp4";
    NSURL *webVideoUrl = [NSURL URLWithString:webVideoPath];
    //  2:  AVPlayer
    AVPlayer *avPlayer = [[AVPlayer alloc] initWithURL:webVideoUrl];
    //  3:  AVPlayer  AVPlayerViewController,       
    AVPlayerViewController *avPlayerVC =[[AVPlayerViewController alloc] init];
    avPlayerVC.player = avPlayer;
    //  4:         
    avPlayerVC.view.frame = CGRectMake(25, 0, 320, 300);
    //    :AVPlayerViewController           ,        
    //  1.AVPlayerViewController    
    //  2:  addChildViewController,AVPlayerViewController        
    [self addChildViewController:avPlayerVC];
    [self.view addSubview:avPlayerVC.view];
    마지막 요약:
    이상 은 iOS 영상 재생 의 기본 적 인 방법 이지 만 여기 서도 기본 적 인 재생 수요 만 제한 합 니 다.더 복잡 한 재생 기능 을 실현 하려 면 우리 가 계속 깊이 연구 해 야 할 것 이 많 습 니 다.화 이 팅!
    자,이상 이 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기