iOS學習筆記26-視頻播放

來源:互聯網
上載者:User

iOS學習筆記26-視頻播放
一、視頻

在iOS中播放視頻可以使用兩個架構來實現:
1. MediaPlayer架構的MPMoviePlayerControllerMPMoviePlayerViewController
2. AVFoundation架構中的AVPlayer
3. AVKit架構的AVPlayerViewController【iOS8之後才有】

但在近兩年的WWDC上,MediaPlayer架構被iOS9標記為deprcated,意味著它已經不再被蘋果繼續維護,而且該框架組成度較高,不如AVFoundation靈活性高,所以這裡就講AVFoundationAVPlayer來實現播放視頻,AVPlayerViewController實際上就是對AVPlayer的封裝。

下面是兩個架構的應用所在層:

二、AVPlayer

AVPlayer存在於AVFoundation中,它更加接近於底層,所以靈活性極高。
AVPlayer本身並不能顯示視頻,如果AVPlayer要顯示必須建立一個播放器圖層AVPlayerLayer用於展示,該播放器圖層繼承於CALayer

AVPlayer視頻播放使用步驟:建立視頻資源地址URL,可以是網路URL 通過URL建立視頻內容對象 AVPlayerItem,一個視頻對應一個 AVPlayerItem 建立 AVPlayer視頻播放器對象,需要一個 AVPlayerItem進行初始化建立 AVPlayerLayer播放圖層對象,添加到顯示視圖上去播放器播放 play,播放器暫停 pause 添加通知中樞監聽視頻播放完成,使用KVO監聽播放內容的屬性變化進度條監聽是調用 AVPlayer的對象方法:
-(id)addPeriodicTimeObserverForInterval:(CMTime)interval/*監聽頻率*/                                      queue:(dispatch_queue_t)queue /*監聽GCD線程*/                                usingBlock:(void (^)(CMTime time))block;/*監聽回調*/
測試環境搭建:利用終端開啟Apache服務,使得手機可以通過網路訪問本機資源
下載視頻MP4到Apache的Web資來源目錄
預設的Apache的Web資來源目錄是 /Library/WebServer/Documents
查看本機伺服器的IP
別忘了進入info.plist設定HTTP網路解禁
下面是一個具體的項目:ViewController屬性
#import "ViewController.h"#import @interface ViewController ()@property (strong, nonatomic) AVPlayer *player;//視頻播放器@property (strong, nonatomic) AVPlayerLayer *playerLayer;//視頻播放圖層@property (strong, nonatomic) IBOutlet UIView *movieView;//播放[內容] 檢視@property (strong, nonatomic) IBOutlet UIProgressView *progressView;//進度條@property (strong, nonatomic) IBOutlet UISegmentedControl *segmentView;//選擇欄@property (strong, nonatomic) NSArray *playerItemArray;//視頻播放URL列表@end
1. 初始化AVPlayerItem視頻內容對象
/* 擷取播放內容對象,一個AVPlayerItem對應一個視頻檔案 */- (AVPlayerItem *)getPlayItemByNum:(NSInteger)num {    if (num >= self.playerItemArray.count) {        return nil;    }    //建立URL    NSString *urlStr = self.playerItemArray[num];    urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];    NSURL *url = [NSURL URLWithString:urlStr];    //建立播放內容對象    AVPlayerItem *item = [AVPlayerItem playerItemWithURL:url];    return item;}
2. 初始化AVPlayer視頻播放器對象
/* 初始化視頻播放器 */- (void)initAVPlayer {    //擷取播放內容    AVPlayerItem *item = [self getPlayItemByNum:0];    //建立視頻播放器    AVPlayer *player = [AVPlayer playerWithPlayerItem:item];    self.player = player;    //添加播放進度監聽    [self addProgressObserver];    //添加播放內容KVO監聽    [self addObserverToPlayerItem:item];    //添加通知中樞監聽播放完成    [self addNotificationToPlayerItem];}
3. 初始化AVPlayerLayer播放圖層對象
#pragma mark - 初始化/* 初始化播放器圖層對象 */- (void)initAVPlayerLayer {    //建立視頻播放器圖層對象    AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:self.player];    layer.frame = self.movieView.bounds;//尺寸大小    layer.videoGravity = AVLayerVideoGravityResizeAspect;//視頻填充模式    //添加進控制項圖層    [self.movieView.layer addSublayer:layer];    self.playerLayer = layer;    self.movieView.layer.masksToBounds = YES;}
4. 通知中樞監聽播放完成
#pragma mark - 通知中樞- (void)addNotificationToPlayerItem {    //添加通知中樞監聽視頻播放完成    [[NSNotificationCenter defaultCenter] addObserver:self                                             selector:@selector(playerDidFinished:)                                                 name:AVPlayerItemDidPlayToEndTimeNotification                                               object:self.player.currentItem];}- (void)removeNotificationFromPlayerItem {    //移除通知中樞的通知    [[NSNotificationCenter defaultCenter] removeObserver:self];}/* 播放完成後會調用 */- (void)playerDidFinished:(NSNotification *)notification {    //自動播放下一個視頻    NSInteger currentIndex = self.segmentView.selectedSegmentIndex;    self.segmentView.selectedSegmentIndex = (currentIndex + 1)%self.playerItemArray.count;    [self segmentValueChange:self.segmentView];}
5. KVO屬性監聽
#pragma mark - KVO監聽屬性/* 添加KVO,監聽播放狀態和緩衝載入狀況 */- (void)addObserverToPlayerItem:(AVPlayerItem *)item {    //監控狀態屬性    [item addObserver:self           forKeyPath:@"status"              options:NSKeyValueObservingOptionNew              context:nil];    //監控緩衝載入情況屬性    [item addObserver:self           forKeyPath:@"loadedTimeRanges"              options:NSKeyValueObservingOptionNew              context:nil];}/* 移除KVO */- (void)removeObserverFromPlayerItem:(AVPlayerItem *)item {    [item removeObserver:self forKeyPath:@"status"];    [item removeObserver:self forKeyPath:@"loadedTimeRanges"];}/* 屬性發生變化,KVO響應函數 */- (void)observeValueForKeyPath:(NSString *)keyPath                      ofObject:(id)object                        change:(NSDictionary *)change                       context:(void *)context{    AVPlayerItem *playerItem = (AVPlayerItem *)object;    if ([keyPath isEqualToString:@"status"]) {//狀態發生改變        AVPlayerStatus status = [[change objectForKey:@"new"] integerValue];        if (status == AVPlayerStatusReadyToPlay) {            NSLog(@"現正播放..,視頻總長度為:%.2f",CMTimeGetSeconds(playerItem.duration));        }    } else if ( [keyPath isEqualToString:@"loadedTimeRanges"] ) {//緩衝區域變化        NSArray *array = playerItem.loadedTimeRanges;        CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];//已緩衝範圍        float startSeconds = CMTimeGetSeconds(timeRange.start);        float durationSeconds = CMTimeGetSeconds(timeRange.duration);        NSTimeInterval totalBuffer = startSeconds + durationSeconds;//緩衝總長度        NSLog(@"共緩衝:%.2f",totalBuffer);    }}
6. 進度條監聽
#pragma mark - 進度監聽- (void)addProgressObserver {    AVPlayerItem *item = self.player.currentItem;    UIProgressView *progress = self.progressView;    //進度監聽    [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0)                                              queue:dispatch_get_main_queue()                                         usingBlock:^(CMTime time)     {         //CMTime是表示視頻時間資訊的結構體,包含視頻時間點、每秒畫面格數等資訊         //擷取當前播放至的秒數         float current = CMTimeGetSeconds(time);         //擷取視頻總播放秒數         float total = CMTimeGetSeconds(item.duration);         if (current) {             [progress setProgress:(current/total) animated:YES];         }     }];}
7. UI點擊事件以及視圖控制器載入
- (void)viewDidLoad {    [super viewDidLoad];    //屬性初始化    self.segmentView.selectedSegmentIndex = 0;    self.progressView.progress = 0;    self.playerItemArray = @[@"http://192.168.6.147/1.mp4",                             @"http://192.168.6.147/2.mp4",                             @"http://192.168.6.147/3.mp4"];    //視頻播放器初始化    [self initAVPlayer];    //視頻播放器顯示圖層初始化    [self initAVPlayerLayer];    //視頻開始播放    [self.player play];}- (void)dealloc {    //移除監聽和通知    [self removeObserverFromPlayerItem:self.player.currentItem];    [self removeNotificationFromPlayerItem];}#pragma mark UI點擊/* 點擊播放按鈕 */- (IBAction)playMovie:(UIButton *)sender {    sender.enabled = NO;    if ( self.player.rate == 0 ) {//播放速度為0,表示播放暫停        sender.titleLabel.text = @"暫停";        [self.player play];//啟動播放    } else if ( self.player.rate == 1.0 ) {//播放速度為1.0,表示現正播放        sender.titleLabel.text = @"播放";        [self.player pause];//暫停播放    }    sender.enabled = YES;}/* 選擇視頻播放清單 */- (IBAction)segmentValueChange:(UISegmentedControl *)sender {    //先移除對AVPlayerItem的所有監聽    [self removeNotificationFromPlayerItem];    [self removeObserverFromPlayerItem:self.player.currentItem];    //擷取新的播放內容    AVPlayerItem *playerItem = [self getPlayItemByNum:sender.selectedSegmentIndex];    //添加屬性監聽    [self addObserverToPlayerItem:playerItem];    //替換視頻內容    [self.player replaceCurrentItemWithPlayerItem:playerItem];    //添加播放完成監聽    [self addNotificationToPlayerItem];}

三、AVPlayerViewController

一個簡單的視頻播放器就這麼搞定了,感覺還是好麻煩,而且很多功能還沒有實現。
實際上在iOS8.0之後,蘋果為我們封裝了AVPlayer等視頻播放相關的類 ,形成了一個直接可以簡單使用的播放器控制器類,那就是AVPlayerViewController,下面來講下你就覺得有多爽,上面那一大堆,只需要下面的一小塊代碼就可以實現了。

使用步驟:匯入架構:
添加標頭檔:
#import #import 
建立 URL 建立 AVPlayer 建立 AVPlayerViewController

Over,一個功能十分齊全的播放器就好了

下面是全部代碼【/(ㄒoㄒ)/~~淚奔】:
#import "ViewController.h"#import #import @interface ViewController ()@property (strong, nonatomic) AVPlayerViewController *playerVC;@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    //建立URL    NSURL *url = [NSURL URLWithString:@"http://192.168.6.147/1.mp4"];    //直接建立AVPlayer,它內部也是先建立AVPlayerItem,這個只是快捷方法    AVPlayer *player = [AVPlayer playerWithURL:url];    //建立AVPlayerViewController控制器    AVPlayerViewController *playerVC = [[AVPlayerViewController alloc] init];    playerVC.player = player;    playerVC.view.frame = self.view.frame;    [self.view addSubview:playerVC.view];    self.playerVC = playerVC;    //調用控制器的屬性player的開始播放方法    [self.playerVC.player play];}@end

這酸爽不敢相信,不過這個是iOS9才有的,就是為了替代
MediaPlayer架構的MPMoviePlayerViewController而定製的非常方便的視頻播放濃ky"http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vc8YnIgLz4NCs7S08M8Y29kZT5BVlBsYXllcjwvY29kZT7QtLXEytPGtbKlt8XG97G7y6bBy7rDvLjKrsz1vdajrC8oqNJvqNIpL35+oaM8L3A+DQo8aDMgaWQ9"四擴充產生影片縮圖">四、擴充–產生影片縮圖

AVFoundation架構還提供了一個類AVAssetImageGenerator,用於擷取視頻。

應用情境:播放視頻時,拖動進度條時,可以顯示影片縮圖,查看視頻播放至哪個畫面了選擇某個視頻播放的時候,可以使用影片縮圖,點擊視頻縮放圖,進入真正的播放視頻介面一些有意思的視頻情境需要截屏留念的時候,可以使用影片縮圖具體使用步驟:建立 AVURLAsset對象,該對象主要用於擷取媒體資訊,包括視頻、聲音。根據 AVURLAsset建立 AVAssetImageGenerator對象使用對象方法 copyCGImageAtTime:獲得指定時間點的
-(CGImageRef)copyCGImageAtTime:(CMTime)requestedTime /* 要在視頻的哪個時間點產生縮圖 */                       actualTime:(CMTime *)actualTime /* 實際產生縮圖的媒體時間 */                            error:(NSError **)outError;/* 錯誤資訊 */
下面是實際代碼:
/* 擷取影片縮圖 */- (UIImage *)getThumbailImageRequestAtTimeSecond:(CGFloat)timeBySecond {    //視頻檔案URL地址    NSURL *url = [NSURL URLWithString:@"http://192.168.6.147/2.mp4"];    //建立媒體資訊對象AVURLAsset    AVURLAsset *urlAsset = [AVURLAsset assetWithURL:url];    //建立影片縮圖產生器對象AVAssetImageGenerator    AVAssetImageGenerator *imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:urlAsset];    //建立影片縮圖的時間,第一個參數是視頻第幾秒,第二個參數是每秒畫面格數    CMTime time = CMTimeMake(timeBySecond, 10);    CMTime actualTime;//實際產生影片縮圖的時間    NSError *error = nil;//錯誤資訊    //使用對象方法,產生影片縮圖,注意產生的是CGImageRef類型,如果要在UIImageView上顯示,需要轉為UIImage    CGImageRef cgImage = [imageGenerator copyCGImageAtTime:time                                                actualTime:&actualTime                                                     error:&error];    if (error) {        NSLog(@"截取影片縮圖發生錯誤,錯誤資訊:%@",error.localizedDescription);        return nil;    }    //CGImageRef轉UIImage對象    UIImage *image = [UIImage imageWithCGImage:cgImage];    //記得釋放CGImageRef    CGImageRelease(cgImage);    return image;}
 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.