ZFPlayer
作者对播放器的介绍:
Support customization of any player SDK and control layer(支持定制任何播放器SDK和控制层)
ZFPlayer demo 支持的播放器:
AVPlayer
ijkplayer
KSYPlayer【作者已移除】
拓展阿里播放器
pod ‘AliPlayerSDK_iOS’, ‘5.3.0’ #[核心库]
pod ‘AliPlayerSDK_iOS_ARTP’, ‘5.3.0’ #[按需索取]
pod ‘AliPlayerSDK_iOS_ARTC’, ‘5.3.0’ #[按需索取]
pod ‘RtsSDK’, ‘5.3.0’ #[按需索取]
1.按上述说明在podfile中添加需要的依赖库;
2.参考ZFPlayer的demo中ZFAVPlayerManager或者ZFIJKPlayerManager创建一个播放器管理类;
如:RKAliPlayerManager
3.遵循代理ZFPlayerMediaPlayback;
4.管理类详细代码:
RKAliPlayerManager.h
#import <Foundation/Foundation.h>
#import <ZFPlayer/ZFPlayerMediaPlayback.h>
#import <AliyunPlayer/AliyunPlayer.h>
@interface RKAliPlayerManager : NSObject<ZFPlayerMediaPlayback>
@property (nonatomic, strong, readonly) AVURLAsset *asset;
@property(nonatomic,strong,readonly)AliPlayer *player;
/// 视频请求头
@property (nonatomic, strong) NSDictionary *requestHeader;
@end
RKAliPlayerManager.m
#import "RKAliPlayerManager.h"
#import <ZFPlayer/ZFPlayer.h>
#import <ZFPlayer/ZFPlayerConst.h>
@interface RKAliPlayerManager()<AVPDelegate>
@property(nonatomic,strong)AliPlayer *player;
@property (nonatomic, assign) BOOL isReadyToPlay;
@property (nonatomic, strong) AVAssetImageGenerator *imageGenerator;
@property (nonatomic, strong) UIView *playerView;
@end
@implementation RKAliPlayerManager
@synthesize view = _view;
@synthesize currentTime = _currentTime;
@synthesize totalTime = _totalTime;
@synthesize playerPlayTimeChanged = _playerPlayTimeChanged;
@synthesize playerBufferTimeChanged = _playerBufferTimeChanged;
@synthesize playerDidToEnd = _playerDidToEnd;
@synthesize bufferTime = _bufferTime;
@synthesize playState = _playState;
@synthesize loadState = _loadState;
@synthesize assetURL = _assetURL;
@synthesize playerPrepareToPlay = _playerPrepareToPlay;
@synthesize playerReadyToPlay = _playerReadyToPlay;
@synthesize playerPlayStateChanged = _playerPlayStateChanged;
@synthesize playerLoadStateChanged = _playerLoadStateChanged;
@synthesize seekTime = _seekTime;
@synthesize muted = _muted;
@synthesize volume = _volume;
@synthesize presentationSize = _presentationSize;
@synthesize isPlaying = _isPlaying;
@synthesize rate = _rate;
@synthesize isPreparedToPlay = _isPreparedToPlay;
@synthesize shouldAutoPlay = _shouldAutoPlay;
@synthesize scalingMode = _scalingMode;
@synthesize playerPlayFailed = _playerPlayFailed;
@synthesize presentationSizeChanged = _presentationSizeChanged;
- (void)dealloc {
[self stop];
}
- (instancetype)init {
self = [super init];
if (self) {
_scalingMode = ZFPlayerScalingModeAspectFit;
_shouldAutoPlay = YES;
}
return self;
}
- (void)prepareToPlay {
if (!_assetURL) return;
_isPreparedToPlay = YES;
[self initializePlayer];
if (self.shouldAutoPlay) {
[self play];
}
self.loadState = ZFPlayerLoadStatePrepare;
if (self.playerPrepareToPlay) self.playerPrepareToPlay(self, self.assetURL);
}
- (void)reloadPlayer {
[self prepareToPlay];
}
- (void)play {
if (!_isPreparedToPlay) {
[self prepareToPlay];
} else {
[self.player start];
self.player.rate = self.rate;
_isPlaying = YES;
self.playState = ZFPlayerPlayStatePlaying;
}
}
- (void)pause {
[self.player pause];
_isPlaying = NO;
self.playState = ZFPlayerPlayStatePaused;
[_asset cancelLoading];
}
- (void)stop {
[_asset cancelLoading];
[self.player stop];
[self.player destroy];
self.player = nil;
_assetURL = nil;
self.presentationSize = CGSizeZero;
_isPlaying = NO;
_isPreparedToPlay = NO;
self->_currentTime = 0;
self->_totalTime = 0;
self->_bufferTime = 0;
self.isReadyToPlay = NO;
self.playState = ZFPlayerPlayStatePlayStopped;
}
- (void)replay {
@zf_weakify(self)
[self seekToTime:0 completionHandler:^(BOOL finished) {
@zf_strongify(self)
if (finished) {
[self play];
}
}];
}
- (void)seekToTime:(NSTimeInterval)time completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
if (self.player.duration > 0) {
self->_currentTime = time;
[self.player seekToTime:time seekMode:AVP_SEEKMODE_ACCURATE];
if (completionHandler) completionHandler(YES);
} else {
self.seekTime = time;
}
}
- (UIImage *)thumbnailImageAtCurrentTime {
/// 第二个参数存疑
CMTime expectedTime = CMTimeMake(_currentTime, self.rate);
CGImageRef cgImage = NULL;
self.imageGenerator.requestedTimeToleranceBefore = kCMTimeZero;
self.imageGenerator.requestedTimeToleranceAfter = kCMTimeZero;
cgImage = [self.imageGenerator copyCGImageAtTime:expectedTime actualTime:NULL error:NULL];
if (!cgImage) {
self.imageGenerator.requestedTimeToleranceBefore = kCMTimePositiveInfinity;
self.imageGenerator.requestedTimeToleranceAfter = kCMTimePositiveInfinity;
cgImage = [self.imageGenerator copyCGImageAtTime:expectedTime actualTime:NULL error:NULL];
}
UIImage *image = [UIImage imageWithCGImage:cgImage];
return image;
}
#pragma mark - private method
- (void)initializePlayer {
_asset = [AVURLAsset URLAssetWithURL:self.assetURL options:self.requestHeader];
_imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:_asset];
self.player = [[AliPlayer alloc] init];
self.player.scalingMode = AVP_SCALINGMODE_SCALEASPECTFIT;
self.player.rate = 1;
self.player.delegate = self;
self.player.autoPlay = self.shouldAutoPlay;
AVPUrlSource *playerSource = [[AVPUrlSource alloc]init];
playerSource.playerUrl = _assetURL;
[self.player setUrlSource:playerSource];
if ([_requestHeader valueForKey:@"referer"]) {
AVPConfig *config = [self.player getConfig];
config.referer = [_requestHeader valueForKey:@"referer"];
[self.player setConfig:config];
}
self.player.playerView = self.playerView;
[self.player prepare];
self.view.playerView = self.player.playerView;
self.scalingMode = self->_scalingMode;
}
- (UIView *)playerView {
if (!_playerView) {
_playerView = [[UIView alloc]init];
}
return _playerView;
}
#pragma mark - ali
-(void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType {
switch (eventType) {
case AVPEventPrepareDone: {
/// 准备完成事件
if (!self.isReadyToPlay) {
self.isReadyToPlay = YES;
self.loadState = ZFPlayerLoadStatePlaythroughOK;
if (self.playerReadyToPlay) self.playerReadyToPlay(self, self.assetURL);
}
if (self.seekTime) {
if (self.shouldAutoPlay) [self pause];
@zf_weakify(self)
[self seekToTime:self.seekTime completionHandler:^(BOOL finished) {
@zf_strongify(self)
if (finished) {
self->_currentTime = self.seekTime;
if (self.shouldAutoPlay) [self play];
}
}];
self.seekTime = 0;
} else {
if (self.shouldAutoPlay && self.isPlaying) [self play];
}
self.player.muted = self.muted;
}break;
case AVPEventFirstRenderedStart: {
///首帧显示事件
if (self.isPlaying) {
[self play];
self.muted = self.muted;
if (self.seekTime > 0) {
[self seekToTime:self.seekTime completionHandler:nil];
self.seekTime = 0; // 滞空, 防止下次播放出错
[self play];
}
}
if (self.playerReadyToPlay) self.playerReadyToPlay(self, self.assetURL);
//开启常亮状态
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
NSLog(@"AVPEventFirstRenderedStart--首帧回调");
}break;
case AVPEventAutoPlayStart:{
}break;;
case AVPEventCompletion: {
/// 播放完成事件
self.playState = ZFPlayerPlayStatePlayStopped;
if (self.playerDidToEnd){
self.playerDidToEnd(self);
}
}break;
/// 缓冲开始事件
case AVPEventLoadingStart: {
self.loadState = ZFPlayerLoadStatePrepare;
} break;
/// 缓冲完成事件
case AVPEventLoadingEnd: {
self.loadState = ZFPlayerLoadStatePlayable;
}break;
case AVPEventSeekEnd:{
/// 跳转完成事件
NSLog(@"seekDone");
} break;
case AVPEventLoopingStart:{
/// 循环播放开始事件
}break;
default:
break;
}
}
-(void)onPlayerEvent:(AliPlayer*)player eventWithString:(AVPEventWithString)eventWithString description:(NSString *)description {
[self showAliLogCode:(int)eventWithString andMsg:description];
//过滤EVENT_PLAYER_DIRECT_COMPONENT_MSG 打印信息
// if (eventWithString != EVENT_PLAYER_DIRECT_COMPONENT_MSG) {
//
// }
}
- (void)onError:(AliPlayer*)player errorModel:(AVPErrorModel *)errorModel; {
[self showAliLogCode:(int)errorModel.code andMsg:errorModel.description];
}
/**
@brief 播放器状态改变回调
*/
- (void)onPlayerStatusChanged:(AliPlayer*)player oldStatus:(AVPStatus)oldStatus newStatus:(AVPStatus)newStatus;{
if (newStatus == AVPStatusError) {
self.playState = ZFPlayerPlayStatePlayFailed;
if (self.playerPlayFailed) self.playerPlayFailed(self, @"参考onError:打印信息");
}
}
/**
@brief 视频缓冲进度回调
*/
- (void)onLoadingProgress:(AliPlayer*)player progress:(float)progress; {
}
/**
@brief 视频当前播放位置回调
*/
- (void)onCurrentPositionUpdate:(AliPlayer*)player position:(int64_t)position; {
self->_currentTime = position;
self->_totalTime = player.duration;
if (self.playerPlayTimeChanged) self.playerPlayTimeChanged(self, self.currentTime, self.totalTime);
}
/**
@brief 视频缓存位置回调
*/
- (void)onBufferedPositionUpdate:(AliPlayer*)player position:(int64_t)position; {
self->_bufferTime = player.bufferedPosition;//self.player.playableDuration;
if (self.playerBufferTimeChanged) self.playerBufferTimeChanged(self, self.bufferTime);
}
/**
@brief 视频大小变化回调
*/
- (void)onVideoSizeChanged:(AliPlayer*)player width:(int)width height:(int)height rotation:(int)rotation;{
self.presentationSize = CGSizeMake(width, height);
self.view.presentationSize = self.presentationSize;
if (self.presentationSizeChanged) {
self.presentationSizeChanged(self, self->_presentationSize);
}
}
-(void)showAliLogCode:(int)aliCode andMsg:(NSString *)aliMsg {
NSLog(@"rk_alilog:%d--%@",aliCode,aliMsg);
}
#pragma mark - ali
#pragma mark - getter
- (ZFPlayerView *)view {
if (!_view) {
_view = [[ZFPlayerView alloc] init];
}
return _view;
}
- (float)rate {
return _rate == 0 ?1:_rate;
}
#pragma mark - setter
- (void)setPlayState:(ZFPlayerPlaybackState)playState {
_playState = playState;
if (self.playerPlayStateChanged) self.playerPlayStateChanged(self, playState);
}
- (void)setLoadState:(ZFPlayerLoadState)loadState {
_loadState = loadState;
if (self.playerLoadStateChanged) self.playerLoadStateChanged(self, loadState);
}
- (void)setAssetURL:(NSURL *)assetURL {
if (self.player) [self stop];
_assetURL = assetURL;
[self prepareToPlay];
}
- (void)setRate:(float)rate {
_rate = rate;
if (self.player && fabsf(_player.rate) > 0.00001f) {
self.player.rate = rate;
}
}
- (void)setMuted:(BOOL)muted {
_muted = muted;
self.player.muted = _muted;
}
- (void)setScalingMode:(ZFPlayerScalingMode)scalingMode {
_scalingMode = scalingMode;
self.view.scalingMode = scalingMode;
switch (scalingMode) {
case ZFPlayerScalingModeNone:
self.player.scalingMode = AVP_SCALINGMODE_SCALEASPECTFIT;
break;
case ZFPlayerScalingModeAspectFit:
self.player.scalingMode = AVP_SCALINGMODE_SCALEASPECTFIT;
break;
case ZFPlayerScalingModeAspectFill:
self.player.scalingMode = AVP_SCALINGMODE_SCALEASPECTFILL;
break;
case ZFPlayerScalingModeFill:
self.player.scalingMode = AVP_SCALINGMODE_SCALETOFILL;
break;
default:
break;
}
}
- (void)setVolume:(float)volume {
_volume = MIN(MAX(0, volume), 1);
self.player.volume = volume;
}
@end
5.外部引用:
#import <ZFPlayer/ZFPlayer.h>
#import <ZFPlayer/ZFIJKPlayerManager.h>
#import "RKAliPlayerManager.h"
RKAliPlayerManager *playerManager = [[RKAliPlayerManager alloc]init];
NSMutableDictionary * headers = [NSMutableDictionary dictionary];
[headers setObject:h5url forKey:@"referer"];
playerManager.requestHeader = [NSDictionary dictionaryWithDictionary:headers];
...
...
注意
阿里播放器支持4中播放源:[示例中采用的AVPUrlSource
,可按需扩展]:
AVPVidStsSource播放【依赖阿里的云点播、云存储】
AVPVidAuthSource播放【依赖阿里的云点播、云存储】
AVPVidMpsSource播放【依赖阿里的云点播、云存储】
AVPUrlSource播放【可以播放任意云存储资源】