KTVHTTPCache + AVPlayerLayer
#import "AVPlayerVC.h"
#import "AVFoundation/AVFoundation.h"
#import "KTVHTTPCache/KTVHTTPCache.h"
@interface AVPlayerVC ()
@end
@implementation AVPlayerVC
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
[KTVHTTPCache proxyStart:nil];
NSString * urlStr = @"https://media.w3.org/2010/05/sintel/trailer.mp4?ss=2";
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];
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 封装
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface KTVHTTPCacheManager : NSObject
+ (instancetype)sharedManager;
@property (nonatomic ,assign)BOOL isConverter;
- (NSURL *)createProxyURL:(NSString *)urlStr;
- (NSString *)getAllCacheLength;
- (void)clearAllCache;
@end
NS_ASSUME_NONNULL_END
#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];
NSError *error = nil;
[KTVHTTPCache proxyStart:&error];
if (error) {
NSLog(@"Error starting proxy: %@", error);
}
[KTVHTTPCache cacheSetMaxCacheLength:1024LL*1024LL*1024LL*2LL];
});
return sharedInstance;
}
- (NSURL *)createProxyURL:(NSString *)urlStr{
if (self.isConverter) {
NSArray *components = [urlStr componentsSeparatedByString:@"?"];
[KTVHTTPCache encodeSetURLConverter:^NSURL *(NSURL *URL) {
return [NSURL URLWithString:components[0]];
}];
}
NSURL *videoURL = [NSURL URLWithString:urlStr];
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
-
- 启动本地代理服务器,并设置URL映射
[KTVHTTPCacheManager sharedManager].isConverter = YES;
-
- 获取播放链接
NSURL *proxyURL = [[KTVHTTPCacheManager sharedManager] createProxyURL:@""];
-
- 然后把这个链接直接给ZFPlayer播放就行了
self.player.assetURL = proxyURL;
- 但是我遇到一个问题:
-
-
- 排查到卡住的时候播放状态已改变成正在播放了,但是未播放成功
-
- 我又不想去改 pod 中的源码,避免以后每次重新pod都要改
-
- 我的解决办法是,播放后延迟1秒,判断播放进度是否有回调,没有的话就重新调用一次播放
- 代码如下
//
@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