边下边播之 KTVHTTPCache + AVPlayerLayer or ZFPlayer/AVPlayer

KTVHTTPCache + AVPlayerLayer

  • 测试未发现问题
objectivec 复制代码
#import "AVPlayerVC.h"
#import "AVFoundation/AVFoundation.h"
#import "KTVHTTPCache/KTVHTTPCache.h"

@interface AVPlayerVC ()

@end

@implementation AVPlayerVC

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor redColor];
    
    // 1.启动本地代理服务器
    [KTVHTTPCache proxyStart:nil];
    // 视频链接
    NSString * urlStr = @"https://media.w3.org/2010/05/sintel/trailer.mp4?ss=2";
    // 设置URL映射
    NSArray *components = [urlStr componentsSeparatedByString:@"?"];
    [KTVHTTPCache encodeSetURLConverter:^NSURL *(NSURL *URL) {
        NSLog(@"URL Filter reviced URL Old : %@", URL);
        NSLog(@"URL Filter reviced URL New : %@", components[0]);
        return [NSURL URLWithString:components[0]];
    }];
    
    NSURL *videoURL = [NSURL URLWithString:urlStr];
    // 2.生成代理 URL
    NSURL *proxyURL = [KTVHTTPCache proxyURLWithOriginalURL:videoURL];
    
    AVPlayer *player = [AVPlayer playerWithURL:proxyURL];
    
    
    AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
    playerLayer.frame = CGRectMake(0, 0, 300, 160);
    [self.view.layer addSublayer:playerLayer];
    [player play];
    
}

@end
  • 但我懒得再去写一个自定义控制层,我想用ZFPlayer
  • 先把KTVHTTPCache 简单封装成个单例

KTVHTTPCache 封装

objectivec 复制代码
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface KTVHTTPCacheManager : NSObject

+ (instancetype)sharedManager;

///是否开启URL映射
@property (nonatomic ,assign)BOOL isConverter;
///获取视频链接
- (NSURL *)createProxyURL:(NSString *)urlStr;


///当前缓存 xxMB
- (NSString *)getAllCacheLength;
///清理所有缓存
- (void)clearAllCache;

@end

NS_ASSUME_NONNULL_END
objectivec 复制代码
#import "KTVHTTPCacheManager.h"
#import "KTVHTTPCache/KTVHTTPCache.h"

@implementation KTVHTTPCacheManager

+ (instancetype)sharedManager {
    static KTVHTTPCacheManager *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
        
        // 1.启动本地代理服务器
        NSError *error = nil;
        [KTVHTTPCache proxyStart:&error];
        if (error) {
            NSLog(@"Error starting proxy: %@", error);
        }
        
        // 缓存最大限制
        //[KTVHTTPCache cacheSetMaxCacheLength:1024*1024*500]; //500M
        [KTVHTTPCache cacheSetMaxCacheLength:1024LL*1024LL*1024LL*2LL]; //2G
        
    });
    return sharedInstance;
}



- (NSURL *)createProxyURL:(NSString *)urlStr{
    
    if (self.isConverter) {
        // 设置URL映射
        NSArray *components = [urlStr componentsSeparatedByString:@"?"];
        [KTVHTTPCache encodeSetURLConverter:^NSURL *(NSURL *URL) {
            return [NSURL URLWithString:components[0]];
        }];
    }
    
    NSURL *videoURL = [NSURL URLWithString:urlStr];
    // 2.生成代理 URL
    NSURL *proxyURL = [KTVHTTPCache proxyURLWithOriginalURL:videoURL bindToLocalhost:NO];
    return proxyURL;
}

- (NSString *)getAllCacheLength{
    long long int length = [KTVHTTPCache cacheTotalCacheLength];
    NSString * ll = [NSString stringWithFormat:@"%lld MB",length/1024/1024];
    return ll;
}

- (void)clearAllCache{
    [KTVHTTPCache cacheDeleteAllCaches];
}

@end

KTVHTTPCache + ZFPlayer/AVPlayer

  • 使用KTVHTTPCacheManager
    1. 启动本地代理服务器,并设置URL映射
  • [KTVHTTPCacheManager sharedManager].isConverter = YES;
    1. 获取播放链接
  • NSURL *proxyURL = [[KTVHTTPCacheManager sharedManager] createProxyURL:@""];
    1. 然后把这个链接直接给ZFPlayer播放就行了
  • self.player.assetURL = proxyURL;
  • 但是我遇到一个问题:
    • 播放视频开始时经常会卡住
    • 排查到卡住的时候播放状态已改变成正在播放了,但是未播放成功
    • 我又不想去改 pod 中的源码,避免以后每次重新pod都要改
    • 我的解决办法是,播放后延迟1秒,判断播放进度是否有回调,没有的话就重新调用一次播放
  • 代码如下
ini 复制代码
#import "ZFPlayerVC.h"

#import <ZFPlayer/ZFAVPlayerManager.h>
//#import <ZFPlayer/ZFPlayerControlView.h>
#import "ZFKWPlayerControlView.h" //自定义控制层
#import <ZFPlayer/UIView+ZFFrame.h>
#import <ZFPlayer/UIImageView+ZFCache.h>
#import <ZFPlayer/ZFPlayerConst.h>
#import "ZFUtilities.h"

#import "KTVHTTPCacheManager.h"

@import AVKit;

@interface ZFPlayerVC ()
@property (nonatomic, strong) ZFPlayerController *player;
@property (nonatomic, strong) ZFAVPlayerManager *playerManager;
@property (nonatomic, strong) ZFKWPlayerControlView *controlView;
@property (nonatomic, strong) UIImageView *containerView;

@property (nonatomic, assign) NSTimeInterval currentTime;
@end

@implementation ZFPlayerVC

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.player.viewControllerDisappear = NO;
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    self.player.viewControllerDisappear = YES;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor whiteColor];

    self.currentTime = -1;
    [self.view addSubview:self.containerView];
    
    ZFAVPlayerManager *playerManager = [[ZFAVPlayerManager alloc] init];
    playerManager.shouldAutoPlay = YES;
    self.playerManager = playerManager;
    /// 播放器相关
    self.player = [ZFPlayerController playerWithPlayerManager:playerManager containerView:self.containerView];
    self.player.controlView = self.controlView;
    
    
    // 1.启动本地代理服务器
    [KTVHTTPCacheManager sharedManager].isConverter = YES;
    
    [self startPlay];

    
    __weak typeof(self) weakSelf = self;
    self.player.playerPrepareToPlay = ^(id<ZFPlayerMediaPlayback>  _Nonnull asset, NSURL * _Nonnull assetURL) {
        NSLog(@"playerPrepareToPlay");
    };
    self.player.playerReadyToPlay = ^(id<ZFPlayerMediaPlayback>  _Nonnull asset, NSURL * _Nonnull assetURL) {
        NSLog(@"playerReadyToPlay");
    };
    self.player.playerPlayTimeChanged = ^(id<ZFPlayerMediaPlayback>  _Nonnull asset, NSTimeInterval currentTime, NSTimeInterval duration) {
        weakSelf.currentTime = currentTime;
        NSLog(@"playerPlayTimeChanged \n🐯 %f🐯 %f🐯 %.2f%%",currentTime,duration,currentTime/duration);
    };
    self.player.playerBufferTimeChanged = ^(id<ZFPlayerMediaPlayback>  _Nonnull asset, NSTimeInterval bufferTime) {
        NSLog(@"playerBufferTimeChanged");
    };
    self.player.playerPlayStateChanged = ^(id<ZFPlayerMediaPlayback>  _Nonnull asset, ZFPlayerPlaybackState playState) {
        NSLog(@"playerPlayStateChanged %lu",(unsigned long)playState);
    };
    self.player.playerLoadStateChanged = ^(id<ZFPlayerMediaPlayback>  _Nonnull asset, ZFPlayerLoadState loadState) {
        NSLog(@"playerLoadStateChanged");
    };
    self.player.orientationDidChanged = ^(ZFPlayerController * _Nonnull player, BOOL isFullScreen) {
        /* // 使用YYTextView转屏失败
        for (UIWindow *window in [UIApplication sharedApplication].windows) {
            if ([window isKindOfClass:NSClassFromString(@"YYTextEffectWindow")]) {
                window.hidden = isFullScreen;
            }
        }
        */
    };
    /// 播放完成
    self.player.playerDidToEnd = ^(id  _Nonnull asset) {
        [weakSelf.player stop];
    };
    self.player.playerPlayFailed = ^(id<ZFPlayerMediaPlayback>  _Nonnull asset, id  _Nonnull error) {
        NSLog(@"playerPlayFailed");
    };
    self.player.presentationSizeChanged = ^(id<ZFPlayerMediaPlayback>  _Nonnull asset, CGSize size) {
        NSLog(@"presentationSizeChanged");
    };
    
    UIButton * btn  = [[UIButton alloc]initWithFrame:CGRectMake(0, 300, 100, 100)];
    btn.backgroundColor = [UIColor redColor];
    [btn addTarget:self action:@selector(startPlay) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
}

- (void)startPlay{
    self.currentTime = -1;
    NSString * urlStr = @"https://www.apple.com/105/media/us/iphone-x/2017/01df5b43-28e4-4848-bf20-490c34a926a7/films/feature/iphone-x-feature-tpl-cc-us-20170912_1280x720h.mp4";

//    NSString * urlStr = @"https://media.w3.org/2010/05/sintel/trailer.mp4?ss=3";
    
    NSURL *proxyURL = [[KTVHTTPCacheManager sharedManager] createProxyURL:urlStr];
    self.player.assetURL = proxyURL;
    self.player.assetURLs = @[proxyURL];
    [self.player playTheIndex:0];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if (self.currentTime == -1) {
            NSLog(@"//延迟执行");
            [self.player playTheIndex:0];
        }
    });
    
}

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    
    CGFloat x = 0;
    CGFloat y = CGRectGetMaxY(self.navigationController.navigationBar.frame);
    CGFloat w = CGRectGetWidth(self.view.frame);
    CGFloat h = w*9/16;
    self.containerView.frame = CGRectMake(x, y, w, h);
}


- (UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleDefault;
}

- (BOOL)prefersStatusBarHidden {
    return NO;
}

- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
    return UIStatusBarAnimationNone;
}

- (BOOL)shouldAutorotate {
    return NO;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

- (ZFKWPlayerControlView *)controlView {
    if (!_controlView) {
        _controlView = [ZFKWPlayerControlView new];
        _controlView.isCanSlider = YES;
        _controlView.fastViewAnimated = YES;
        _controlView.autoHiddenTimeInterval = 5;
        _controlView.autoFadeTimeInterval = 0.5;
        _controlView.prepareShowLoading = YES;
        _controlView.prepareShowControlView = NO;
        _controlView.showCustomStatusBar = YES;
    }
    return _controlView;
}

- (UIImageView *)containerView {
    if (!_containerView) {
        _containerView = [UIImageView new];
        _containerView.backgroundColor = [UIColor blackColor];
    }
    return _containerView;
}


@end
相关推荐
missmisslulu12 小时前
电容笔值得买吗?2024精选盘点推荐五大惊艳平替电容笔!
学习·ios·电脑·平板
GEEKVIP13 小时前
手机使用技巧:8 个 Android 锁屏移除工具 [解锁 Android]
android·macos·ios·智能手机·电脑·手机·iphone
GEEKVIP13 小时前
如何在 Windows 10 上恢复未保存/删除的 Word 文档
macos·ios·智能手机·电脑·word·笔记本电脑·iphone
奇客软件14 小时前
iPhone使用技巧:如何恢复变砖的 iPhone 或 iPad
数码相机·macos·ios·电脑·笔记本电脑·iphone·ipad
奇客软件2 天前
如何从相机的记忆棒(存储卡)中恢复丢失照片
深度学习·数码相机·ios·智能手机·电脑·笔记本电脑·iphone
GEEKVIP2 天前
如何修复变砖的手机并恢复丢失的数据
macos·ios·智能手机·word·手机·笔记本电脑·iphone
一丝晨光2 天前
继承、Lambda、Objective-C和Swift
开发语言·macos·ios·objective-c·swift·继承·lambda
GEEKVIP2 天前
iPhone/iPad技巧:如何解锁锁定的 iPhone 或 iPad
windows·macos·ios·智能手机·笔记本电脑·iphone·ipad
KWMax2 天前
RxSwift系列(二)操作符
ios·swift·rxswift
Mamong3 天前
Swift并发笔记
开发语言·ios·swift