美文网首页音视频首页推荐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