AVFoundation | 封裝一個好用的視訊播放器

FBY展菲發表於2018-04-08

一:簡介

AVFoundation是蘋果在iOS和OS X系統中用於處理基於時間的媒體資料的Objective-C框架. 供使用者來開發媒體型別的應用程式。

video.png

上圖是iOS系統下媒體應用的結構層. AVKit框架用於簡化媒體應用的建立過程,如果你只需要看電影,那麼使用這個就可以了, UKit可以支援簡單的錄製功能 . 而更多功能需要低層級框架支援.下面簡單介紹下AVFoundation內最主要的支撐框架和其提供的功能。

  • CoreAudio : 處理所有音訊事件.是由多個框架整合在一起的總稱,為音訊和MIDI內容的錄製,播放和處理提供相應介面.設定可以針對音訊訊號進行完全控制,並通過Audio Units來構建一些複雜的音訊處理.有興趣的可以單獨瞭解一下這個框架。

  • CoreMedia: 是AVFoundation所用到低層級媒體管道的一部分.提供音訊樣本和視訊幀處理所需的低層級資料型別和介面。

  • CoreAnimation: 動畫相關框架, 封裝了支援OpenGL和OpenGL ES功能的ObjC各種類. AVFoundation可以利用CoreAnimation讓開發者能夠在視訊的編輯和播放過程中新增動畫和圖片效果。

下面我就和大家詳細的分享一下,如何使用AVFoundation來實現一個好用的視訊播放器。如果好用或者對你有所幫助,不要忘了關注點個贊呦!!!

二:實現思路分析

  1. 視訊控制介面實現

  2. 用於視訊顯示的View建立

  3. 視訊資料下載器FBYVideoDownload建立

  4. 播放、暫停、橫豎屏操作方法實現

  5. 監聽播放進度

  6. 控制儲存緩衝範圍

  7. 拖動滑塊,控制快進快退

  8. 定義臨時檔案路徑

  9. 定義快取資料夾路徑

  10. 發起視訊路徑網路請求方法

  11. 播放結束設定

  12. 前後視訊播放控制

三:實現原始碼分析

根據實現思路分析,一步步進行編碼實現:

1. 視訊控制介面實現

- (FBYVideoPlayerView *)videoPlayControl{
    if (!_videoPlayControl) {
        _videoPlayControl = [[FBYVideoPlayerView alloc] initWithFrame:self.backgroundView.bounds];
        [self.backgroundView addSubview:_videoPlayControl];
        
    }
    return _videoPlayControl;
}
複製程式碼

2. 用於視訊顯示的View建立

- (UIView *)videoShowView{
    if (!_videoShowView) {
        _videoShowView = [[UIView alloc] init];
        _videoShowView.layer.masksToBounds = YES;
        [self.backgroundView addSubview:_videoShowView];
    }
    return _videoShowView;
}
複製程式碼

3. 視訊資料下載器FBYVideoDownload建立

@property(nonatomic, weak) id <FBYVideoDownloadDelegate> delegate;

//定義初始化方法 傳入videoUrl引數(NSString)
- (instancetype)initWithURL:(NSString *)videoUrl withDelegate:(id)delegate;

//開始下載
- (void)start;
//暫停
- (void)suspend;
//關閉
- (void)cancel;
複製程式碼

4. 播放、暫停、橫豎屏操作方法實現

        //全屏
        [_videoPlayControl setFullScreenButtonClick_block:^{
            if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(videoPlayerDidFullScreenButtonClick)]) {
                [weakSelf.delegate videoPlayerDidFullScreenButtonClick];
            }
        }];
        //播放/暫停
        [_videoPlayControl setPlayButtonClick_block:^(BOOL play) {
            if (play) {
                [weakSelf.player play];
            }else{
                [weakSelf.player pause];
            }
            weakSelf.playButtonState = !weakSelf.playButtonState;
        }];
複製程式碼

5. 監聽播放進度

self.timeObserve = [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
        CGFloat current = CMTimeGetSeconds(time);
        CGFloat total = CMTimeGetSeconds(weakSelf.currentPlayerItem.duration);
        CGFloat progress = current / total;
        
        weakSelf.videoPlayControl.currentTime = current;
        weakSelf.videoPlayControl.playValue = progress;
        
        if (weakSelf.isCanToGetLocalTime) {
            weakSelf.localTime = [weakSelf getLocalTime];
        }
        NSInteger timeNow = [weakSelf getLocalTime];
        if (timeNow - weakSelf.localTime > 1.5) {
            [weakSelf.videoPlayControl videoPlayerDidBeginPlay];
            weakSelf.isCanToGetLocalTime = YES;
        }
    }];
複製程式碼

6. 監聽播放器的狀態

[self.currentPlayerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
複製程式碼

7. 監聽當前的緩衝進度

[self.currentPlayerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
複製程式碼

8. 監聽到當前沒有緩衝資料

[self.currentPlayerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
複製程式碼

9. 控制儲存緩衝範圍

- (void)playForActivity{
    if (self.playButtonState) {
        [self.player play];
    }
    self.isBufferEmpty = NO;
    self.isPlaying = YES;
    [self.videoPlayControl videoPlayerDidBeginPlay];
}
複製程式碼

10. 拖動滑塊,控制快進快退

//拖動滑塊
[_videoPlayControl setSliderTouchEnd_block:^(CGFloat time) {
            [weakSelf seekToTimePlay:time];
        }];
        
//快進快退
[_videoPlayControl setFastFastForwardAndRewind_block:^(CGFloat time) {
            [weakSelf seekToTimePlay:time];
        }];
複製程式碼

11. 定義臨時檔案路徑

self.videoTempPath = [NSString tempFilePathWithFileName:videoName];
複製程式碼

12. 定義快取資料夾路徑

self.videoCachePath = [NSString cacheFilePathWithName:videoName];
複製程式碼

13. 發起視訊路徑網路請求方法

- (void)sendHttpRequst
{
    [_fileHandle seekToEndOfFile];
    NSURL *url = [NSURL URLWithString:_videoUrl];
    NSMutableURLRequest *requeset = [NSMutableURLRequest requestWithURL:url];
    
    //指定頭資訊  當前已下載的進度
    [requeset setValue:[NSString stringWithFormat:@"bytes=%ld-", _curruentLength] forHTTPHeaderField:@"Range"];
    
    //建立請求
    NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:requeset];
    self.dataTask = dataTask;
    
    //發起請求
    [self.dataTask resume];
}
複製程式碼

14. 播放結束設定

- (void)playerItemDidPlayToEnd:(NSNotification *)notification{
    //重新開始播放
    __weak typeof(self) weak_self = self;
    [self.player seekToTime:CMTimeMake(0, 1) completionHandler:^(BOOL finished) {
        __strong typeof(weak_self) strong_self = weak_self;
        if (!strong_self) return;
        [strong_self.player play];
    }];
}
複製程式碼

15. 前後視訊播放控制

//進入後臺
- (void)appDidEnterBackground{
    if (self.stopWhenAppDidEnterBackground) {
        [self pauseVideo];
    }
}
//進入前臺
- (void)appDidEnterForeground{
    [self playVideo];
}
複製程式碼

五:專案實際使用

1. 下載demo

下載demo,將demo中FBYVideoData資料夾引入專案中。

2. 在專案中引入FBYVideoPlayer並繼承FBYVideoPlayerDelegate代理

#import "FBYVideoPlayer.h"

@interface ViewController ()<FBYVideoPlayerDelegate>

@property (nonatomic ,strong) FBYVideoPlayer *videoPlayer;
@property (nonatomic ,strong) UIView *videoPlayBGView;
@property (nonatomic ,copy)   NSString*videoUrl;

@end
複製程式碼

3. 初始化建立基層view

self.videoPlayBGView = [[UIView alloc] initWithFrame:CGRectMake(0, 90, SCREEN_WIDTH, SCREEN_WIDTH * 0.6)];
self.videoPlayBGView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:self.videoPlayBGView];
複製程式碼

4. 初始化呼叫視訊播放方法

self.videoPlayer = [[FBYVideoPlayer alloc] init];
self.videoPlayer.delegate = self;
[self.videoPlayer playWithUrl:self.videoUrl showView:self.videoPlayBGView];
複製程式碼

5. 初始化呼叫視訊播放方法

self.videoPlayer = [[FBYVideoPlayer alloc] init];
self.videoPlayer.delegate = self;
[self.videoPlayer playWithUrl:self.videoUrl showView:self.videoPlayBGView];
複製程式碼

本篇文章demo原始碼:

關注 【網羅開發】微信公眾號,回覆【97】便可領取。 網羅天下方法,方便你我開發,更多iOS技術乾貨等待領取,所有文件會持續更新,歡迎關注一起成長!

希望可以幫助大家,如有問題可加QQ技術交流群: 668562416 如果哪裡有什麼不對或者不足的地方,還望讀者多多提意見或建議

如需轉載請聯絡我,經過授權方可轉載,謝謝

本篇已同步到個人部落格:FBY展菲


歡迎關注我的公眾號:網羅開發

AVFoundation | 封裝一個好用的視訊播放器

相關文章