美文网首页音视频首页推荐iOS Developer
iOS_VR视频播放(自定义视频播放器)

iOS_VR视频播放(自定义视频播放器)

作者: 小二同學 | 来源:发表于2018-03-15 11:22 被阅读55次

iOS VR模式视频播放,全景视频播放,同时还支持普通视频播放,并且自定义视频播放器,显示logo啊,隐藏进度条啊,拖动进度条啊,这些都可以自定义,腾讯视频上面有的功能都可以自己实现的。有点小激动...

VR模式视频播放.PNG
  • 有一个很好用的第三方VR播放器 SGPlayer
  • 集成步骤,GitHub上写的很详细了,我就不再重复写了,遇到什么问题的话,可以留言询问。这个播放器唯一不好的就是不支持模拟器,必须得用真机测试。模拟器会报错。
  • 导入成功之后,接下来就得开始准备搭建UI了。
  • 创建播放器View,并定义好frame。
// 播放器
_VRPlayer = [SGPlayer player];
// 开启 FFmpeg 硬解
 _VRPlayer.decoder.hardwareAccelerateEnableForFFmpeg = YES;
 [_VRPlayer registerPlayerNotificationTarget:self
                                    stateAction:@selector(stateAction:)
                                 progressAction:@selector(progressAction:)
                                 playableAction:@selector(playableAction:)
                                    errorAction:@selector(errorAction:)];
[_VRPlayer setViewTapAction:^(SGPlayer * _Nonnull player, SGPLFView * _Nonnull view) {
        NSLog(@"player display view did click!");
    }];
    
    _VRPlayer.view.frame = self.frame;
    [self addSubview:_VRPlayer.view];
  • _VRPlayer.view 就是一个View,我们可以在这上面添加任何东西,播放按钮,进度条,VR模式切换,title,还有手势,logo什么的
  • 这个方法控制视频全屏还是适应原来的尺寸
_VRPlayer.viewGravityMode = SGGravityModeResize;
  • VR模式和全景模式
_VRPlayer.displayMode = SGDisplayModeBox; // VR模式
_VRPlayer.displayMode = SGDisplayModeNormal; // 全景模式
  • 播放的话,直接传入url就行了
NSURL *vrVideo = [NSURL URLWithString:vrDetailModel.videoUrl];
[_VRPlayer replaceVideoWithURL:vrVideo videoType:SGVideoTypeVR];
  • 实现代理
  • 播放的状态,这里面有视频出现的各种状态,正在缓冲,准备播放,正在播放,播放完成,播放失败,我们可以根据相应的状态做事情。
#pragma 播放的状态
- (void)stateAction:(NSNotification *)notification
{
    SGState * state = [SGState stateFromUserInfo:notification.userInfo];
    
    //    NSString * text;
    switch (state.current) {
        case SGPlayerStateNone:
            //            text = @"None";
            break;
        case SGPlayerStateBuffering:
            //            text = @"Buffering...";
            
            if (self.playButton.selected) {
                [self Buffering];
            }
            break;
        case SGPlayerStateReadyToPlay:
            //            text = @"Prepare";
            /** 总时长 */
            self.allTime.text = [self timeStringFromSeconds:_VRPlayer.duration];
            [self Prepare];
            [_VRPlayer play];
            break;
        case SGPlayerStatePlaying:
            //            text = @"Playing";
            [self Prepare];
            break;
        case SGPlayerStateSuspend:
            //            text = @"Suspend";
            break;
        case SGPlayerStateFinished:
            //            text = @"Finished";
            if (_VRPattern.selected == YES) {
                [_VRPlayer play];
            }
            break;
        case SGPlayerStateFailed:
            //            text = @"Error";
            break;
    }
    //    self.stateLabel.text = text;
}
  • 播放进度,改变播放时间和进度条进度
- (void)progressAction:(NSNotification *)notification
{
    SGProgress * progress = [SGProgress progressFromUserInfo:notification.userInfo];
    
    if (!self.progressSilderTouching) {
        self.progressSilder.value = progress.percent;
    }
    self.playTime.text = [self timeStringFromSeconds:progress.current];
}
  • 缓冲进度
- (void)playableAction:(NSNotification *)notification
{
    SGPlayable * playable = [SGPlayable playableFromUserInfo:notification.userInfo];
    
    [UIView animateWithDuration:0.1 animations:^{
        
        _progressSilder.playableProgress = playable.percent;
    }];
    
    NSLog(@"playable time : %f", playable.current);
}
  • 这样就算是能播放了,剩下的还有进度条,横竖屏切换,3s之后隐藏控件
  • 自定义进度条,我选择的是UISlider,上一篇音乐播放器我用的是UILabel,视频的话因为是要拖动,直接用slider会好一些
  • 首先创建一个UISlider类
@interface VideoSlider : UISlider
/** 缓冲条进度 */
@property (assign,nonatomic) CGFloat playableProgress;
  • 然后对slider进行重绘,实现缓冲条进度方法
-(void)setPlayableProgress:(CGFloat)playableProgress{
    if (_playableProgress != playableProgress){
        _playableProgress = playableProgress;
        [self setNeedsDisplay];
    }
}

-(void)setFrame:(CGRect)frame{
    [super setFrame:frame];
    [self setNeedsDisplay];
}

-(void)setBounds:(CGRect)bounds{
    [super setBounds:bounds];
    [self setNeedsDisplay];
}
  • 这个可以根据需求改变进度条的高度和宽度还有颜色等等
- (void)drawRect:(CGRect)rect{
    [super drawRect:rect];
    CGContextRef c = UIGraphicsGetCurrentContext();
    
    [[[UIColor whiteColor] colorWithAlphaComponent:0.7] set];
    
    CGRect r = [self trackRectForBounds:self.bounds];
    r = CGRectInset(r, 0, 0);
    UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:r cornerRadius:r.size.height/2.0];
    CGContextAddPath(c, bezierPath.CGPath);
    CGContextSetLineWidth(c, 0);
    CGContextStrokePath(c);
    CGContextAddPath(c, bezierPath.CGPath);
    CGContextClip(c);
    CGContextFillRect(c, CGRectMake(r.origin.x, r.origin.y, r.size.width * _playableProgress, r.size.height));
}
  • 然后把进度条放上去看看有没有起作用
_progressSilder = [[VideoSlider alloc] init];
[_progressSilder addTarget:self action:@selector(progressTouchDown:) forControlEvents:UIControlEventTouchDown];
[_progressSilder addTarget:self action:@selector(progressTouchUp:) forControlEvents:UIControlEventTouchUpInside];
[_progressSilder addTarget:self action:@selector(progressTouchUp:) forControlEvents:UIControlEventTouchCancel];
[_progressSilder addTarget:self action:@selector(progressTouchUp:) forControlEvents:UIControlEventTouchUpOutside];
    
    /*  修改进度条的样式  */
[_progressSilder setThumbImage:[UIImage imageNamed:@"VR滑块"] forState:UIControlStateNormal];
_progressSilder.layer.masksToBounds = YES;
_progressSilder.layer.cornerRadius = 3*WidthJust;
_progressSilder.minimumTrackTintColor = UIColorFromRGB(0Xff9b24);
_progressSilder.maximumTrackTintColor = [[UIColor whiteColor] colorWithAlphaComponent:0.4];
  • 实现拖动方法,改变播放时间和视频播放进度
- (void)progressTouchDown:(id)sender
{
    self.progressSilderTouching = YES;
}

- (void)progressTouchUp:(id)sender
{
    self.progressSilderTouching = NO;
    [_VRPlayer seekToTime:_VRPlayer.duration * self.progressSilder.value];
    self.playTime.text = [self timeStringFromSeconds:self.progressSilder.value];
}
  • 3s之后隐藏控件,在页面一进来就给一个3s倒计时,或者在播放开始的时候给倒计时,这个根据需求
self.timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(hideProgress) userInfo:nil repeats:YES];
  • 然后实现方法
- (void)hideProgress{
    self.progressBar.hidden = YES;
}
  • 还有就是点击视频背景的时候隐藏进度条,或者显示进度条,先给视频背景定义一个手势,然后改变进度条显示状态,然后再改变定时器,先置空,再重新开始3s倒计时
#pragma 单击隐藏播放条
- (void)hideProessBar:(UIGestureRecognizer *)tap {
    [self.timer invalidate];
    self.timer = nil;
    // 3S之后隐藏进度条
    self.timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(hideProgress) userInfo:nil repeats:YES];
    _progressBar.hidden = !_progressBar.hidden;
}
  • 进度条这样就算是完了,有木有很简单
  • 横竖屏切换,首先在APPdelegate里面定义一个全局变量,是否支持横屏,因为只有视频页面需要支持横屏,别的页面不需要
// 是否支持横屏
@property (nonatomic,assign) NSInteger allowRotate;
  • 然后根据allowRotate的状态去设置设备的状态
#if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
#else
//此方法会在设备横竖屏变化的时候调用
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
#endif
{
    
    //   NSLog(@"方向  =============   %ld", _allowRotate);
    if (_allowRotate == 1) {
        return UIInterfaceOrientationMaskAll;
    }else{
        return (UIInterfaceOrientationMaskPortrait);
    }
}

// 返回是否支持设备自动旋转
- (BOOL)shouldAutorotate
{
    if (_allowRotate == 1) {
        return YES;
    }
    return NO;
}
  • 然后再去视频详情页,刚进入页面的时候,把允许横屏改为1,页面消失的时候改为0
//在视图出现的时候,将allowRotate改为1,
AppDelegate * delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
delegate.allowRotate = 1;
  • 根据这个方法判断横竖屏,改变UI
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
        //屏幕从竖屏变为横屏时执行
}else{}
}
  • 切换横竖屏,定义一个全局变量记录横竖屏的状态
// 变为横屏
    if (isPortrait) {
        
        if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
            [[UIDevice currentDevice] performSelector:@selector(setOrientation:) withObject:[NSNumber numberWithInteger:UIInterfaceOrientationLandscapeLeft]];
            isPortrait = false;
        }
    }else{
        if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
            SEL selector = NSSelectorFromString(@"setOrientation:");
            NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
            [invocation setSelector:selector];
            [invocation setTarget:[UIDevice currentDevice]];
            int val = UIDeviceOrientationPortrait;
            //从2开始是因为0 1 两个参数已经被selector和target占用
            [invocation setArgument:&val atIndex:2];
            [invocation invoke];
            isPortrait = true;
        }
    }
  • 我们播放器下面是一个tableview,横屏的时候把tableview隐藏,这样的话,就不会出现bug
  • 在视频播放view上横竖屏UI显示不一样,也可以根据上面判断横竖屏的方法改变控件的显示与否
横竖屏切换.gif
  • OK,就这么多吧,赶紧试试把。还有一个事,我的APP被拒了一个月了,因为2.1狗年大礼包,到现在还没过,一直在等,桑心。过了之后分享被拒心得。希望早点过吧,哈哈哈...

相关文章

网友评论

本文标题:iOS_VR视频播放(自定义视频播放器)

本文链接:https://www.haomeiwen.com/subject/qraqqftx.html