VLC集成与使用

作者: Pocket | 来源:发表于2016-07-04 01:59 被阅读7156次

VLC的集成和使用

VLC介绍

VLC Media Player (VideoLAN) 为 Windows、Linux、OS X、Android、iOS、Windows Phone等平台提供一个视频播放器、解码器。它可以播放来自网络、摄像头、磁盘、光驱的文件,支持包括MPEG 1/2/4, H264, VC-1, DivX, WMV, Vorbis, AC3, AAC等格式的解码。在 Windows 和 Linux 上的 VLC 是使用C++/Qt写成,提供了一致的用户体验。同时 VLC 还专门为 OS X 提供了原生版本,OS X 版的 VLC 的用户界面使用Cocoa框架编写,在 OS X 下拥有卓越的原生体验。

  • VLC还有一个非常好的功能——播放那些没有下载完整的视频文件。
  • VLC几乎覆盖所有媒体格式。

VLC集成

在iOS下,我们可以很方便的使用VLC,因为它经行了优秀的封装,源码中最核心的部分被封装成了独立的库(MoblieVLVKit.framework库),它是基于FFmpeg,Live555提供完整的媒体播放库,所以整一个库体积还是比较大(目前已经超过600M了),不过并不会太影响App的大小,经行App打包发布的是会自动超级压缩的。经过测试它比使用FFmpeg库仅仅是多7M左右的大小。

  • VLC cocoapods方式集成

VLC可以有多种的方式安装,目前最简单的方式就是cocoapods安装,以前需要下载源码后经行编译,编译后的还分模拟器版和真机版,最后还得使用lipo 命令经行合并,比较麻烦,这里我就不进行介绍了,因为没必要(喜欢折腾的可以自行搜索相关资料),最终编译得到的结果一样是MoblieVLCKit.framework库,即使项目不允许使用cocoapods,也可以建立空项目后使用cocoapods得到MoblieVLCKit.framework在经行移植。

  • 步骤
```objc
1.在podfile中写入:pod 'MobileVLCKit'
2.终端执行pod install即可(成功后会在项目里看到MoblieVLCKit.framework库)
3.添加依赖库:libz.tbd、libbz2.tbd、libiconv.tbd、libstdc++.6.0.9.tbd
```

VLC使用

MoblieVLCKit为我们提供了很多功能接口,不过我们不需要全部了解,只需要懂得几个常用的API接口就可以轻轻松松的写出一个播放器出来。因为它支持定制化UI,所以有心的开发者可以结合漂亮的UI设计一套专属的播放器

  • MoblieVLCKit 常用API介绍
    • VLCMediaPlayer
      VCL对象,管理着播放的开始暂停等操作,有着几个代理方法可以经行状态和时间的监听回调
      
    • VLCMediaPlayer属性
      // 播放设置,比如设置播放路径是本地播放还是网络播放,以及播放的画面映射到哪个View
      
    @property (NS_NONATOMIC_IOSONLY, strong) VLCMedia *media;
    - VLCMediaPlayer方法
    ```objc
    // 开始播放
    -(BOOL)play;
    // 暂停播放
    - (void)pause;
    // 停止播放
    - (void)stop;
    /**
      *快进播放
      *interval:需要快进的秒数
    */
    - (void)jumpForward:(int)interval;
    /**
      *快退播放
      *interval:需要快退的秒数
    */
    - (void)jumpBackward:(int)interval;
    // 短时间的快退(10秒)
    - (void)shortJumpBackward;
    // 短时间的快进(10秒)
    - (void)shortJumpForward;
    /**
      * 以一定倍速播放
      * rate:倍速
    */
    - (void)fastForwardAtRate:(float)rate;
    
    • VLCMediaPlayer代理
      // 播放状态改变的回调
      - (void)mediaPlayerStateChanged:(NSNotification *)aNotification;
      // 播放时间改变的回调
      - (void)mediaPlayerTimeChanged:(NSNotification *)aNotification;
      
  • MoblieVLCKit使用demo

我就抛砖迎玉贴上自己写的一份播放器demo封装(有时间我在放进github)


效果预览

IMG_1717.jpg
  • VLCPlayer.h和VLCPlayer.m(VLC创建)

        //
    //  VLCPlayer.h
    //  VLCDemo
    //
    //  Created by pocket on 16/6/27.
    //  Copyright © 2016年 pocket. All rights reserved.
    //
    
    // VLC播放对象
    #import <Foundation/Foundation.h>
    #import <MobileVLCKit/MobileVLCKit.h>
    #import <UIKit/UIKit.h>
    
    @interface VLCPlayer : NSObject
    /**
     *  VCL对象
     */
    @property (nonatomic, strong) VLCMediaPlayer *player;
    /**
     *  根据路径初始化VCL对象
     *
     *  @param playView 播放承载View
     *  @param path     本地路径
     *
     *  @return VLCPlayer 类
     */
    - (id)initWithView:(UIView *)playView andMediaPath:(NSString *)path;
    /**
     *  根据URL初始化VCL对象
     *
     *  @param playView 播放承载View
     *  @param url      url路径
     *
     *  @return VLCPlayer 类
     */
    - (id)initWithView:(UIView *)playView andMediaURL:(NSURL *)url;
    
    /**
     *  开始播放
     */
    - (void)playMedia;
    /**
     *  暂停播放
     */
    - (void)stopPlaying;
    @end
    
        //
    //  VLCPlayer.m
    //  VLCDemo
    //
    //  Created by pocket on 16/6/27.
    //  Copyright © 2016年 pocket. All rights reserved.
    //
    
    #import "VLCPlayer.h"
    
    @implementation VLCPlayer
    
    - (id)initWithView:(UIView *)playView andMediaPath:(NSString *)path {
        self = [super init];
        if (self) {
            // 创建VCL对象
            _player = [[VLCMediaPlayer alloc] init];
            // 设置VCL播放界面的View
            _player.drawable = playView;
            // 设置需要加载的路径
            VLCMedia *media = [VLCMedia mediaWithPath:path];
            [_player setMedia:media];
        }
        return self;
    }
    
    - (id)initWithView:(UIView *)playView andMediaURL:(NSURL *)url {
        self = [super init];
        if (self) {
            _player = [[VLCMediaPlayer alloc] init];
            _player.drawable = playView;
            // 设置需要加载的url
            VLCMedia *media = [VLCMedia mediaWithURL:url];
            [_player setMedia:media];
        }
        return self;
    }
    
    // 播放
    - (void)playMedia {
        [_player play];
    }
    
    // 暂停
    - (void)stopPlaying {
        [_player stop];
    }
    @end
    
  • VLCViewController.h/VLCViewController.m(播放控制器)

    //  VLCViewController.h
    //  VLCDemo
    //
    //  Created by pocket on 16/6/27.
    //  Copyright © 2016年 pocket. All rights reserved.
    //
    
    // VLC播放控制器
    #import <UIKit/UIKit.h>
    #import "VLCPlayer.h"
    
    @interface VLCViewController : UIViewController
    /**
     *  文件名字
     */
    @property (nonatomic, strong) NSString *playName;
    /**
     *  文件路径(本地资源路径)
     */
    @property (nonatomic, strong) NSString *playPath;
    /**
     *  网络URL路径
     */
    @property (nonatomic, strong) NSURL *playURL;
    
    @property (nonatomic, strong) VLCPlayer *player;
    @end
    
    
    //  VLCViewController.m
    //  VLCDemo
    //
    //  Created by pocket on 16/6/27.
    //  Copyright © 2016年 pocket. All rights reserved.
    //
    #import "VLCViewController.h"
    #import <AVFoundation/AVFoundation.h>
    #import<MobileVLCKit/MobileVLCKit.h>
    #import "VLCPlayerView.h"
    @interface VLCViewController ()<VLCMediaPlayerDelegate>
    /**
     *  VLC承载视图
     */
    @property (nonatomic,strong) VLCPlayerView *vlcPlayerView;
    /**
     *  是否本地路径
     */
    @property (nonatomic,assign) BOOL isLocal;
    /**
     *  视频总时间(秒)
     */
    @property (nonatomic,assign) int videoAllTime;
    /**
     *  当前播放时间(秒)
     */
    @property (nonatomic,assign) int videoCurrentTime;
    /**
     *  当前进度
     */
    @property (nonatomic,assign) float currentProgress;
    /**
     *  菊花加载
     */
    @property (nonatomic,strong) UIActivityIndicatorView *activityView;
    @end
    
    @implementation VLCViewController
    - (void)viewDidLoad {
      [super viewDidLoad];
    
      self.title = self.playName;
      self.videoAllTime = 0;
    
      [self tarnsformView];
      // 添加播放的承载View
      [self addVLCPalyerView];
      // 菊花
      self.activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
      self.activityView.center = self.vlcPlayerView.center;
      [self.activityView setHidesWhenStopped:YES]; // 旋转时隐藏
      [self.activityView startAnimating]; // 开始旋转
      [self.view addSubview:self.activityView];
      //视频播放
      if (_playPath) { // 本地
          _player = [[VLCPlayer alloc] initWithView:self.vlcPlayerView.playView andMediaPath:_playPath];
          _player.player.delegate = self;
          [_player playMedia]; // 播放
          self.isLocal = YES;
      }
      if (_playURL) { // 网络
          _player = [[VLCPlayer alloc] initWithView:self.vlcPlayerView.playView andMediaURL:_playURL];
          _player.player.delegate = self;
          [_player playMedia];
          self.isLocal = NO;
      }
    

}

  • (void)dealloc
    {
    [_player stopPlaying];
    _player = nil;
    }
+ (void)initialize
{
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];
    [session setActive:YES error:nil];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    [self addObserver];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];

    [self removeObserver];
}

#pragma mark - -- 屏幕旋转控制处理
// 这里采用假旋转,因为其他界面并不需要支持横屏(缺点是状态栏不支持转动,所以采取presentView方式最好)
- (void)tarnsformView
{
    // 旋转view
    self.view.transform = CGAffineTransformMakeRotation(M_PI/2); // 旋转90°
    CGRect frame = [UIScreen mainScreen].applicationFrame; // 获取当前屏幕大小
    // 重新设置所有view的frame
    self.view.bounds = CGRectMake(0, 0,frame.size.height + 20,frame.size.width);
    self.vlcPlayerView.frame = self.view.bounds;
}
// 隐藏状态栏显得和谐
- (BOOL)prefersStatusBarHidden
{
    return YES;
}

#pragma mark - -- 播放的承载View的设置
- (void)addVLCPalyerView
{
    //承载播放的视图初始化(自定义播放界面可在这里做UI定制)
    self.vlcPlayerView = [[VLCPlayerView alloc] initWithFrame:self.view.bounds];
    // 设置视频名称
    self.vlcPlayerView.videoName = self.playName;
    // 设置播放监听回调
    __weak typeof(self) weakSelf = self;
    self.vlcPlayerView.playBlock = ^(UIButton *playBtn){
        [weakSelf playClick:playBtn];
    };
    // 设置进度条监听回调
    self.vlcPlayerView.changeSliderBlock = ^(UISlider *sliderView){
        [weakSelf changeProgress:sliderView];
    };
    // 设置屏幕锁监听回调
    self.vlcPlayerView.lockBlock = ^(UIButton *lockBtn){
        // 屏幕锁操作逻辑
        // ...后续
    };
    // 设置返回按钮回调
    self.vlcPlayerView.backBlock = ^{
        // 关闭视图控制器
        [weakSelf.player stopPlaying];
        [weakSelf dismissViewControllerAnimated:YES completion:^{

        }];
    };

    // 左右滑动手势结束回调
    self.vlcPlayerView.endPanGesture = ^(float progress,int type){
        if (type == 4) { // 快退
            [weakSelf.player.player shortJumpBackward];
        } else if (type == 3) { // 快进
            [weakSelf.player.player shortJumpForward];
        }
    };

    [self.view addSubview:self.vlcPlayerView];
}
    #pragma mark - -- vlcPlayerView播放操作
// 播放(暂停)监听
- (void)playClick:(UIButton *)playBtn
{
    if ([_player.player isPlaying]) { // 正在播放
        [_player.player pause]; // 暂停
    } else {
        [_player.player play]; // 播放
    }
}

// 倍率速度播放(一般很少使用)
- (void)fastForwardAtRate:(float)rate
{
    [_player.player fastForwardAtRate:rate];
}
// 进度条拖拽
- (void)changeProgress:(UISlider *)sliderView
{
    if (!_player.player.isPlaying) { // 防止暂停状态拖动(拖动触发播放)
        [self.vlcPlayerView changePlayBtnState:YES];
        [_player.player play];
    }
    // 根据拖动比例计算开始到播放节点的总秒数
    int allSec = (int)(self.videoAllTime * sliderView.value);
    // 根据当前播放秒数计算需要seek的秒数
    int sec = abs(allSec - self.videoCurrentTime);
    // 如果为获取到时间信息
    if (sec == 0 && allSec == 0) {
        [[AlertViewManager shareInstance] showPromptText:self.view context:CustomLocalizedString(@"未获取到视频总时间,请尝试手势快进", nil) minSize:CGSizeMake(60,44) afterDelay:2.0];
        return;
    }
    NSLog(@"sec:%d",sec);
    if (sec==0) { // 刚好等于视频总时间
        [_player.player stop];
        return;
    }
    if (self.currentProgress<=sliderView.value) { // 快进滑动
        [_player.player jumpForward:sec]; // 快进播放
    } else {
        [_player.player jumpBackward:sec]; // 快退播放
    }

}

#pragma  mark - -- vlcPlayerView时间和进度刷新
- (void)updateTime
{
    // 设置剩余时间
    self.vlcPlayerView.remainingTime = [[_player.player remainingTime] stringValue];
    // 设置当前时间
    self.vlcPlayerView.currentTime = [[_player.player time] stringValue];
    // 设置当前进度
    self.vlcPlayerView.sliderValue = [_player.player position];
}

#pragma mark - -- KVO监听
// 添加监听
- (void)addObserver
{
    // 监听VLC对象属性(时间和播放)
    [_player.player addObserver:self forKeyPath:@"remainingTime" options:0 context:nil];
    [_player.player addObserver:self forKeyPath:@"isPlaying" options:0 context:nil];
}

// 移除监听
- (void)removeObserver
{
    [_player.player removeObserver:self forKeyPath:@"remainingTime"];
    [_player.player removeObserver:self forKeyPath:@"isPlaying"];
}

// kvo监听回调
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {

    // 可以在这里设置显示的时间和进度
    // position:VLCMediaPlayer对象中的进度比例,可用此值设置播放进度
//    NSLog(@"[_player.player position]:%lf",[_player.player position]);
    // remainingTime:VLCMediaPlayer对象中的剩余时间,stringValue可以转化为时间格式字符串
//    NSLog(@"[[_player.player remainingTime] stringValue]:%@",[[_player.player remainingTime] stringValue]);
    // time:VLCMediaPlayer对象中的当前时间
//    NSLog(@"[[_player.player time] stringValue]:%@", [[_player.player time] stringValue]);

//    NSLog(@"剩余的分钟:%@",[[_player.player remainingTime] minuteStringValue]);
//    NSLog(@"播放的分钟:%@",[[_player.player time] minuteStringValue]);
    // 记录当前进度
    self.currentProgress = [_player.player position];
    // 根据分钟计算播放的秒数(这里不够严格,还得加上秒数)
    self.videoCurrentTime = [[[_player.player time] minuteStringValue] intValue] * 60;
    // 根据剩余时间和已经播放的计算总秒数(这里不够严格,还得加上秒数)
    self.videoAllTime = [[[_player.player remainingTime] minuteStringValue] intValue]*60 + self.videoCurrentTime;

    // 有时候获取不到时间(个人想法是结合定时器和进度比例计算总时间等)
    // ...

    // 刷新最新时间和播放进度
    [self updateTime];
    // 停止菊花加载
    if (self.activityView.isAnimating) {
        [self.activityView stopAnimating];
    }
}

#pragma mark - 监听程序进入前台和后台
#pragma mark - VLCMediaPlayerDelegate
// 播放状态改变的回调
- (void)mediaPlayerStateChanged:(NSNotification *)aNotification
{
    /**
     *  VLCMediaPlayerStateStopped,        //< Player has stopped
     VLCMediaPlayerStateOpening,        //< Stream is opening
     VLCMediaPlayerStateBuffering,      //< Stream is buffering
     VLCMediaPlayerStateEnded,          //< Stream has ended
     VLCMediaPlayerStateError,          //< Player has generated an error
     VLCMediaPlayerStatePlaying,        //< Stream is playing
     VLCMediaPlayerStatePaused          //< Stream is paused
     */
    NSLog(@"mediaPlayerStateChanged");
    NSLog(@"状态:%ld",(long)_player.player.state);
    switch ((int)_player.player.state) {
        case VLCMediaPlayerStateStopped: // 停止播放(播放完毕或手动stop)
        {
            [_player.player stop]; // 手动调用一次停止(一遍再次点击播放)
            [self.vlcPlayerView changePlayBtnState:NO];
            if (self.activityView.isAnimating) {
                [self.activityView stopAnimating];
            }
        }
            break;
        case VLCMediaPlayerStateBuffering: // 播放中缓冲状态
        {
            // 显示菊花
            if (!self.activityView.isAnimating) {
                [self.activityView startAnimating];
            }
        }
            break;
        case VLCMediaPlayerStatePlaying: // 被暂停后开始播放
        {
            if (self.activityView.isAnimating) {
                [self.activityView stopAnimating];
            }
        }
            break;
        case VLCMediaPlayerStatePaused:  // 播放后被暂停
        {
            if (self.activityView.isAnimating) {
                [self.activityView stopAnimating];
            }
        }
            break;

    }
}

// 播放时间改变的回调
- (void)mediaPlayerTimeChanged:(NSNotification *)aNotification
{
//    NSLog(@"mediaPlayerTimeChanged");
}

@end

```
  • VLCPlayerView.h/VLCPlayerView.m(播放View设计)

    //
    //  VLCPlayerView.h
    //  VLCDemo
    //
    //  Created by pocket on 16/6/28.
    //  Copyright © 2016年 pocket. All rights reserved.
    //
    
    // VLC播放界面
    #import <UIKit/UIKit.h>
    
    @interface VLCPlayerView : UIView
    /**
     *  承载视频的View
     */
    @property (nonatomic,strong) UIView *playView;
    /**
     *  视频名称
     */
    @property (nonatomic,copy) NSString *videoName;
    /**
     *  剩余时间
     */
    @property (nonatomic,copy) NSString *remainingTime;
    /**
     *  当前时间
     */
    @property (nonatomic,copy) NSString *currentTime;
    /**
     *  当前进度
     */
    @property (nonatomic,assign) float sliderValue;
    /**
     *  返回按钮监听回调
     */
    @property (nonatomic,copy) void (^backBlock)(void);
    /**
     *  屏幕锁监听回调
     */
    @property (nonatomic,copy) void (^lockBlock)(UIButton *lockBtn);
    /**
     *  播放(暂停)监听回调
     */
    @property (nonatomic,copy) void (^playBlock)(UIButton *playBtn);
    /**
     *  进度条监听回调
     */
    @property (nonatomic,copy) void (^changeSliderBlock)(UISlider *sliderView);
    /**
     *  拖动结束监听(progress:幅度,type: 3:右 ,4:左)
     */
    @property (nonatomic,copy) void (^endPanGesture)(float progress,int type);
    /**
     *  变更播放(暂停)按钮状态
     */
    - (void)changePlayBtnState:(BOOL)select;
    @end
    
    
    //
    //  VLCPlayerView.m
    //  VLCDemo
    //
    //  Created by pocket on 16/6/28.
    //  Copyright © 2016年 pocket. All rights reserved.
    //
    
    #import "VLCPlayerView.h"
    #import "CustomSlider.h"
    
    #define titleFontSize 15.0
    #define titleColor [UIColor whiteColor]
    #define backgroundViewColor RGB(0, 0, 0, 0.6)
    #define space 15.0
    #define alphaDef 0.5
    #define viewHeight 60.0
    #define gestureMinimumTranslation 20.0
    // 定义滑动手势类型
    typedef enum {
        PlayerMoveDirectionNone = 0,
        PlayerMoveDirectionUp,
        PlayerMoveDirectionDown,
        PlayerMoveDirectionRight,
        PlayerMoveDirectionLeft
    }PlayerMoveDirection;
    
    @interface VLCPlayerView()
    /*********************顶部栏*************************************/
    @property (nonatomic,strong) UIView *topView; // 顶部view
    @property (nonatomic,strong) UIButton *backBtn; // 返回按钮
    @property (nonatomic,strong) UILabel *nameLabel; // 名字
    
    /*********************底部栏*************************************/
    @property (nonatomic,strong) UIView *bottomView;// 底部View
    // 开始播放(暂停)按钮
    @property (nonatomic,strong) UIButton *playBtn;
    @property (nonatomic,strong) CustomSlider *sliderView; // 滑动条
    // 当前时间标签
    @property (nonatomic,strong) UILabel *currentTimeLabel;
    // 结束时间标签
    @property (nonatomic,strong) UILabel *endTimeLabel;
    
    /*********************快进/快退显示********************************/
    @property (nonatomic,strong) UIView *baseView;// 快进/快退底View
    @property (nonatomic,strong) UIButton *changeBtn;
    @property (nonatomic,strong) UILabel *progressTitle;
    @property (nonatomic,strong) UIProgressView *progressView;
    
    // 屏幕锁
    @property (nonatomic,strong) UIButton *lockBtn;
    
    // sliderView是否正在滑动
    @property (nonatomic,assign) BOOL isSliding;
    
    // 滑动手势类型
    @property (nonatomic,assign) PlayerMoveDirection moveDirection;
    // 开始拖动的位置
    @property (nonatomic,assign) CGPoint beginPoint;
    // 当前拖动的位置
    @property (nonatomic,assign) CGPoint currentPoint;
    @end
    
    @implementation VLCPlayerView
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        if (self = [super initWithFrame:frame]) {
            [self setUI];
            // 添加手势
            [self addGesture];
    
            // 5秒后自动隐藏
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                if (self.topView.alpha>0.0) {
                    [self oneGestureClick];
                }
            });
        }
    
        return self;
    }
    
    - (void)setUI
    {
        // 承载视频view
        self.playView = [[UIView alloc] init];
        self.playView.backgroundColor = [UIColor blackColor];
        [self addSubview:self.playView];
    
        // 顶部View
        self.topView = [[UIView alloc] init];
        self.topView.backgroundColor = backgroundViewColor;
        [self addSubview:self.topView];
        // 名字
        self.nameLabel = [[UILabel alloc] init];
        self.nameLabel.textColor = titleColor;
        self.nameLabel.textAlignment = NSTextAlignmentCenter;
        self.nameLabel.font = [UIFont systemFontOfSize:titleFontSize];
        [self.topView addSubview:self.nameLabel];
        // 返回按钮
        self.backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [self.backBtn setImage:[UIImage imageNamed:@"ic_jt_bf"] forState:UIControlStateNormal];
        [self.backBtn addTarget:self action:@selector(backClick) forControlEvents:UIControlEventTouchUpInside];
        [self.topView addSubview:self.backBtn];
    
        // 底部view
        self.bottomView = [[UIView alloc] init];
        self.bottomView.backgroundColor = backgroundViewColor;
        [self addSubview:self.bottomView];
        // 暂停
        self.playBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        self.playBtn.selected = YES;
        [self.playBtn setImage:[UIImage imageNamed:@"ic_bf_zt"] forState:UIControlStateSelected];
        [self.playBtn setImage:[UIImage imageNamed:@"ic_bf_zt"] forState:UIControlStateNormal];
        [self.playBtn setAdjustsImageWhenHighlighted:NO]; // 设置无高亮状态
        [self.playBtn addTarget:self action:@selector(playBtnClick) forControlEvents:UIControlEventTouchUpInside];
        [self.bottomView addSubview:self.playBtn];
        // 当前标签
        self.currentTimeLabel = [[UILabel alloc] init];
        self.currentTimeLabel.textColor = titleColor;
        self.currentTimeLabel.text = @"--:--";
        self.currentTimeLabel.textAlignment = NSTextAlignmentLeft;
        self.currentTimeLabel.font = [UIFont systemFontOfSize:titleFontSize];
        [self.bottomView addSubview:self.currentTimeLabel];
        // 结束标签
        self.endTimeLabel = [[UILabel alloc] init];
        self.endTimeLabel.textColor = titleColor;
        self.endTimeLabel.text = @"--:--";
        self.endTimeLabel.textAlignment = NSTextAlignmentRight;
        self.endTimeLabel.font = [UIFont systemFontOfSize:titleFontSize];
        [self.bottomView addSubview:self.endTimeLabel];
        // 滑动条
        self.sliderView = [[CustomSlider alloc] init];
        self.sliderView.minimumTrackTintColor = TedcallStorageProgressColor; // 设置滑动过的颜色
        self.sliderView.maximumTrackTintColor = [UIColor grayColor]; // 设置总长度颜色
        self.sliderView.thumbTintColor = RGB(255, 255, 255, 0.7); // 设置滑块颜色
        [self.sliderView addTarget:self action:@selector(slideringListening) forControlEvents:UIControlEventValueChanged];
        [self.sliderView addTarget:self action:@selector(sliderChange) forControlEvents:UIControlEventTouchUpInside];
        [self.bottomView addSubview:self.sliderView];
    
        // 快进/快退view
        self.baseView = [[UIView alloc] init];
        self.baseView.backgroundColor = backgroundViewColor;
        self.baseView.layer.cornerRadius = 8.0;
        self.baseView.layer.masksToBounds = YES;
        self.baseView.alpha = 0.0;
        [self addSubview:self.baseView];
    
        self.changeBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [self.changeBtn setImage:[UIImage imageNamed:@"ic_kj_bf"] forState:UIControlStateNormal];
        [self.changeBtn setImage:[UIImage imageNamed:@"ic_kt_bf"] forState:UIControlStateSelected];
        [self.baseView addSubview:self.changeBtn];
    
        self.progressTitle = [[UILabel alloc] init];
        self.progressTitle.textColor = titleColor;
        self.progressTitle.textAlignment = NSTextAlignmentCenter;
        self.progressTitle.font = [UIFont systemFontOfSize:titleFontSize];
    //    self.progressTitle.text = @"30秒";
        [self.baseView addSubview:self.progressTitle];
    
        self.progressView = [[UIProgressView alloc] init];
        self.progressView.trackTintColor = [UIColor clearColor];
        self.progressView.progressTintColor = TedcallStorageProgressColor;
        [self.progressView setProgress:0.0];
        [self.baseView addSubview:self.progressView];
    
        // 屏幕锁
        self.lockBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [self.lockBtn setImage:[UIImage imageNamed:@"ic_sp_bf"] forState:UIControlStateNormal];
        [self.lockBtn setImage:[UIImage imageNamed:@"ic_ks_bf"] forState:UIControlStateSelected];
        [self.lockBtn addTarget:self action:@selector(lockClick) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:self.lockBtn];
    }
    
    - (void)setVideoName:(NSString *)videoName
    {
        _videoName = videoName;
        self.nameLabel.text = videoName;
    }
    
    - (void)setCurrentTime:(NSString *)currentTime
    {
        _currentTime = currentTime;
        self.currentTimeLabel.text = currentTime;
    }
    
    - (void)setRemainingTime:(NSString *)remainingTime
    {
        _remainingTime = remainingTime;
        self.endTimeLabel.text = remainingTime;
    }
    
    - (void)setSliderValue:(float)sliderValue
    {
        _sliderValue = sliderValue;
        if (!self.isSliding) { // 防止滑动过程中的手动设值
            [self .sliderView setValue:sliderValue animated:YES];
        }
    }
    
    // 返回按钮监听
    - (void)backClick
    {
        if (self.backBlock) {
            self.backBlock(); // block返回回调
        }
    }
    
    // 播放(暂停)监听
    - (void)playBtnClick
    {
        NSLog(@"twoGesture");
        self.playBtn.selected = !self.playBtn.selected;
        [self changePlayBtnState:self.playBtn.selected];
        if (self.playBlock) {
            self.playBlock(self.playBtn);
        }
    }
    
    // 屏幕锁监听
    - (void)lockClick
    {
        self.lockBtn.selected = !self.lockBtn.selected;
        if (self.lockBtn.selected) {
            self.playView.userInteractionEnabled = NO;
            [UIView transitionWithView:self.lockBtn duration:1.0 options:0 animations:^{
                self.topView.alpha = 0.0;
                self.bottomView.alpha = 0.0;
                self.lockBtn.alpha = 0.0;
            } completion:^(BOOL finished) {
    
            }];
        } else {
            self.topView.alpha = 1.0;
            self.bottomView.alpha = 1.0;
            self.playView.userInteractionEnabled = YES;
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [UIView transitionWithView:self.lockBtn duration:1.0 options:0 animations:^{
                    self.topView.alpha = 0.0;
                    self.bottomView.alpha = 0.0;
                    self.lockBtn.alpha = 0.0;
                } completion:^(BOOL finished) {
    
                }];
            });
        }
    }
    
    - (void)changePlayBtnState:(BOOL)select
    {
        self.playBtn.selected = select;
        if (select) {
            [self.playBtn setImage:[UIImage imageNamed:@"ic_bf_zt"] forState:UIControlStateNormal];
        } else {
            [self.playBtn setImage:[UIImage imageNamed:@"ic_bf_ks"] forState:UIControlStateNormal];
        }
    }
    
    // 滑动结束监听
    - (void)sliderChange
    {
    //    NSLog(@"滑动结束");
        self.isSliding = NO;
        if (self.changeSliderBlock) {
            self.changeSliderBlock(self.sliderView);
        }
    }
    
    // 滑动监听
    - (void)slideringListening
    {
    //    NSLog(@"正在滑动");
        if (!self.isSliding) {
            self.isSliding = YES;
        }
    
    }
    
    - (void)layoutSubviews
    {
        [super layoutSubviews];
    
        CGFloat width = self.frame.size.width;
        CGFloat height = self.frame.size.height;
    
        // 承载视频View
        self.playView.frame = self.bounds;
    
        // 顶部view
        CGFloat topX = 0;
        CGFloat topY = 0;
        CGFloat topW = width;
        CGFloat topH = viewHeight - 10;
        self.topView.frame = CGRectMake(topX, topY, topW, topH);
        // 返回按钮
        CGFloat backW = 30.0;
        CGFloat backH = backW;
        CGFloat backX = space;
        CGFloat backY = (topH - backH)/2;
        self.backBtn.frame = CGRectMake(backX, backY, backW, backH);
        // 视频名称
        CGFloat nameX = space + CGRectGetMaxX(self.backBtn.frame);
        CGFloat nameH = 20.0;
        CGFloat nameW = width - 2*nameX;
        CGFloat nameY = (topH - nameH)/2;
        self.nameLabel.frame = CGRectMake(nameX, nameY, nameW, nameH);
        // 底部view
        CGFloat bottomX = 0;
        CGFloat bottomY = height - viewHeight;
        CGFloat bottomW = width;
        CGFloat bottomH = viewHeight;
        self.bottomView.frame = CGRectMake(bottomX, bottomY, bottomW, bottomH);
        // 播放(暂停)按钮
        CGFloat playW = 40.0;
        CGFloat playH = playW;
        CGFloat playX = space;
        CGFloat playY = (viewHeight - playH)/2;
        self.playBtn.frame = CGRectMake(playX, playY, playW, playH);
        // 滑动条
        CGFloat sliderX = space + CGRectGetMaxY(self.playBtn.frame);
        CGFloat sliderH = 6;
        CGFloat sliderW = width - sliderX - space;
        CGFloat sliderY = playY + playH/2 - 4;
        self.sliderView.frame = CGRectMake(sliderX, sliderY, sliderW, sliderH);
        // 当前标签
        CGFloat currentX = sliderX;
        CGFloat currentY = CGRectGetMaxY(self.sliderView.frame);
        CGFloat currentH = 20.0;
        CGFloat currentW = sliderW/2;
        self.currentTimeLabel.frame = CGRectMake(currentX, currentY, currentW, currentH);
        // 结束标签
        CGFloat endW = currentW;
        CGFloat endX = CGRectGetMaxX(self.sliderView.frame) - endW;
        CGFloat endY = currentY;
        CGFloat endH = currentH;
        self.endTimeLabel.frame = CGRectMake(endX, endY, endW, endH);
    
        // 快进/快退view
        CGFloat baseW = 140.0;
        CGFloat baseH = 74.0;
        CGFloat baseY = CGRectGetMaxY(self.topView.frame) + 20.0;
        CGFloat baseX = (width - baseW)/2;
        self.baseView.frame = CGRectMake(baseX, baseY, baseW, baseH);
    
        CGFloat changeW = 30.0;
        CGFloat changeH = 20.0;
        CGFloat changeX = (baseW - changeW)/2;
        CGFloat changeY = 8.0;
        self.changeBtn.frame = CGRectMake(changeX, changeY, changeW, changeH);
    
        CGFloat titleY = 8.0 + CGRectGetMaxY(self.changeBtn.frame);
        CGFloat titleX = 0;
        CGFloat titleW = baseW;
        CGFloat titleH = 20.0;
        self.progressTitle.frame = CGRectMake(titleX, titleY, titleW, titleH);
    
        CGFloat progressX = 3.0;
        CGFloat progressY = 8.0 + CGRectGetMaxY(self.progressTitle.frame);
        CGFloat progressW = baseW - 2*progressX;
        CGFloat progressH = 0.0;
        self.progressView.frame = CGRectMake(progressX, progressY, progressW, progressH);
    
        // 屏幕锁
        CGFloat lockX = space;
        CGFloat lockW = 50.0;
        CGFloat lockH = 50.0;
        CGFloat lockY = (height - lockH)/2;
        self.lockBtn.frame = CGRectMake(lockX, lockY, lockW, lockH);
    }
    #pragma mark - -- 手势操作
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        NSLog(@"touchesBegan");
        if (self.lockBtn.selected) { // 锁屏状态
            [UIView transitionWithView:self.lockBtn duration:1.0 options:0 animations:^{
                self.lockBtn.alpha = 1.0;
            } completion:^(BOOL finished) {
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    if (self.lockBtn.selected) {
                        [UIView transitionWithView:self.lockBtn duration:1.0 options:0 animations:^{
                            self.lockBtn.alpha = 0.0;
                        } completion:^(BOOL finished) {
    
                        }];
                    }
                });
            }];
        }
    }
    // 添加手势处理
    - (void)addGesture
    {
        // 单点
        UITapGestureRecognizer *oneGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(oneGestureClick)];
        oneGesture.numberOfTapsRequired = 1; // 单击
        oneGesture.numberOfTouchesRequired = 1; // 单指单击
        [self.playView addGestureRecognizer:oneGesture];
    
        // 双击
        UITapGestureRecognizer *twoGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(playBtnClick)];
        twoGesture.numberOfTapsRequired = 2; // 双击
        twoGesture.numberOfTouchesRequired = 1; // 单指双击
        [self.playView addGestureRecognizer:twoGesture];
    
        // 长按
        UILongPressGestureRecognizer *longGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longGestureClick:)];
        longGesture.minimumPressDuration = 3.0; // 长按3秒触发
        [self.playView addGestureRecognizer:longGesture];
    
        // 拖动
        UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureClick:)];
        [self.playView addGestureRecognizer:panGesture];
    
        //解决拖动和长按手势之间的冲突
        [longGesture requireGestureRecognizerToFail:panGesture];
        // 解决单击和双击手势的冲突
        [oneGesture requireGestureRecognizerToFail:twoGesture];
    }
    // 单击手势监听
    - (void)oneGestureClick
    {
        NSLog(@"oneGestureClick");
        if (self.topView.alpha<=0.0) { // 显示
            // 动画显示
            [UIView transitionWithView:self.topView duration:1.0 options:0 animations:^{
                self.topView.alpha = 1.0;
                self.bottomView.alpha = 1.0;
                self.lockBtn.alpha = 1.0;
            } completion:^(BOOL finished) {
                // 5秒后自动隐藏
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    if (self.topView.alpha>0.0) {
                        [self oneGestureClick];
                    }
                });
            }];
        } else {
            // 动画隐藏
            [UIView transitionWithView:self.topView duration:1.0 options:0 animations:^{
                self.topView.alpha = 0.0;
                self.bottomView.alpha = 0.0;
                self.lockBtn.alpha = 0.0;
            } completion:^(BOOL finished) {
    
            }];
        }
    }
    
    // 长按监听
    - (void)longGestureClick:(UILongPressGestureRecognizer *)longGesture
    {
        // 长按手势会调用多次监听方法,先判断手势状态
        if (longGesture.state == UIGestureRecognizerStateBegan) {
            NSLog(@"长按开始");
        }
    }
    
    // 拖动监听
    - (void)panGestureClick:(UIPanGestureRecognizer *)panGesture
    {
        CGPoint translation = [panGesture translationInView:self.playView]; // 取得相对位置的偏移点(相对位置为手指第一次在屏幕的点)
        NSLog(@"translation:%@",NSStringFromCGPoint(translation));
        if (panGesture.state == UIGestureRecognizerStateBegan){
            NSLog (@"滑动开始");
            self.beginPoint = translation;
            self.currentPoint = translation;
        }else if (panGesture.state == UIGestureRecognizerStateChanged){
            self.moveDirection = [self determineCameraDirectionIfNeeded:translation];
            switch (self.moveDirection) {
                case PlayerMoveDirectionDown:
                    NSLog(@"PlayerMoveDirectionDown");
                    break;
                case PlayerMoveDirectionUp:
                    NSLog(@"PlayerMoveDirectionUp");
                    break;
                case PlayerMoveDirectionRight:
                {
                    NSLog(@"PlayerMoveDirectionRight");
                    self.changeBtn.selected = NO;
                    self.progressTitle.text = CustomLocalizedString(@"快进", nil);
                    if (self.baseView.alpha == 0.0) {
                        self.baseView.alpha = 1.0;
                    }
                }
                    break;
                case PlayerMoveDirectionLeft:
                {
                    NSLog(@"PlayerMoveDirectionLeft");
                    self.changeBtn.selected = YES;
                    self.progressTitle.text = CustomLocalizedString(@"快退", nil);
                    if (self.baseView.alpha == 0.0) {
                        self.baseView.alpha = 1.0;
                    }
                }
                    break;
                default :
                    break;
            }
            self.currentPoint = translation; // 刷新当前位置
    
        }else if (panGesture.state == UIGestureRecognizerStateEnded){
            NSLog (@"滑动结束");
            [UIView transitionWithView:self.baseView duration:1.0 options:0 animations:^{
                self.baseView.alpha = 0.0;
            } completion:^(BOOL finished) {
    
            }];
            if (self.endPanGesture) {
                self.endPanGesture(0.5,self.moveDirection);
            }
        }
    }
    
    - (PlayerMoveDirection) determineCameraDirectionIfNeeded:(CGPoint)translation
    {
        // 设定一个幅度使拖动在不够水平(略微有点偏差)的方向上的处理,上下一般不处理
        if (translation.x > self.currentPoint.x && (fabs(translation.y - self.currentPoint.y) <= gestureMinimumTranslation)){ // 说明水平向右拖动了
            return PlayerMoveDirectionRight;
        }else if(translation.x < self.currentPoint.x && (fabs(translation.y - self.currentPoint.y) <= gestureMinimumTranslation)){ // 说明水平向左
            return PlayerMoveDirectionLeft;
        }else if (translation.x == self.currentPoint.x && translation.y > self.currentPoint.y) { // 向下
            return PlayerMoveDirectionDown;
        } else if (translation.x == self.currentPoint.x && translation.y < self.currentPoint.y) { // 向上
            return PlayerMoveDirectionUp;
        } else{
            return PlayerMoveDirectionNone;
        }
    }
    
    - (void)updateFastImage:(int)type
    {
        if (type == 4) { // 左
    
        } else if (type == 3) { // 右
    
        }
    }
    
    @end
    
    
  • CustomSlider.h/CustomSlider.m(自定义滑块)

    //
    //  CustomSlider.h
    //  TedcallStorage
    //
    //  Created by  tedcall on 16/6/28.
    //  Copyright © 2016年 pocket. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface CustomSlider : UISlider
    
    @end
    
    
    //
    //  CustomSlider.m
    //  TedcallStorage
    //
    //  Created by  tedcall on 16/6/28.
    //  Copyright © 2016年 pocket. All rights reserved.
    //
    
    #import "CustomSlider.h"
    
    @implementation CustomSlider
    
    - (void)drawRect:(CGRect)rect
    {
        UIImageView *imageView = nil;
        // 取得滑块View
        for (UIView *view in self.subviews) {
            if ([view isKindOfClass:[UIImageView class]]) {
                if (view.frame.size.width == view.frame.size.height) {
                    imageView = (UIImageView *)view;
                }
            }
        }
    
        if (imageView) { // 有值
            CGFloat redViewW = 8.0;
            CGFloat redViewH =redViewW;
            CGFloat redViewX = (imageView.frame.size.width - redViewW)/2;
            CGFloat redViewY = (imageView.frame.size.height - redViewH)/2;
            UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(redViewX, redViewY, redViewW, redViewH)];
            redView.backgroundColor = RGB(255, 255, 255, 0.7);
            redView.layer.cornerRadius = redViewW/2;
            redView.layer.masksToBounds = YES;
            [imageView addSubview:redView];
        }
    }
    
    // 重写进度条frame
    - (CGRect)trackRectForBounds:(CGRect)bounds {
        return CGRectMake(0,0,bounds.size.width,6.0);
    }
    
    // 解决两边空隙问题
    - (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value
    {
        rect.origin.x = rect.origin.x - 10 ;
        rect.size.width = rect.size.width +20;
        return CGRectInset ([super thumbRectForBounds:bounds trackRect:rect value:value], 10 , 10);
    }
    
    @end
    
    

VLC Demo

因为VLC库比较大所以github 上的demo里并不包含这个库以及测试时的视频。我另外提供了下载地址供需要的朋友自行下载。
demo地址:https://github.com/pocket-live/VLC-Demo
VLC库和测试资源下载地址:http://pan.baidu.com/s/1pLiBQKb

相关文章

网友评论

  • zhhehj:VLC rtsp监控有卡顿延迟怎么解决
  • 这小歌不错:你好,视频播放完后,拖动slider设置position,视频无变化你遇到过嘛?
  • Bana:你好,vlc 不能实时播放 h264 的编码格式吗
  • 豆哥笔记:只有声音 没有画面 楼主知道怎么解决吗
  • 07306af72d6e:在Xcode9 下面加入VLC报错。编译错误
  • 07306af72d6e:报错什么因素
  • 伊织随意写:自己写了个demo,使用play可以播放,但是使用 pause 和 stop后,没有暂停和停止,只是停顿了一下又继续播放了。不清楚为什么。
    用你的demo,就跑的好好地。
    伊织随意写:@Pocket 嗯,是代码不小心的问题。
    不过我发现我和你的demo中,mediaPlayerStateChanged 这个代理方法都走了,但是里面要打印的内容,没有打印出来,你运行时有没有这个问题?
    Pocket:@MelissaShu 好好检查一下代码就好了:blush:
  • c75e79a64f03:打包出现问题 The app references non-public symbols in ****: _locale_charset 是libconv.tbd中出现的“_locale_charset ”,是VLC引用了私有APi了吗?请问该如何解决。
    这个熊孩子不太冷:你好,你解决了吗
  • a076f21b5dc3:iOS11 播放不了
    a076f21b5dc3:avcodec decoder error: more than 5 seconds of late video -> dropping frame (computer too slow ?)
  • 颜思齐:终于找到你的博客啦,昨天看了好几个博客还是觉得你写的比较清晰明了,demo封的也不错,特意来评论感谢下。(framework太大了下了好久,自己编译半天没成功,一会研究下怎么编译取)
  • 62de48dd0dc0:你好,请问下,我在Android 7.0手机上运行为什么会出现黑框了?
  • LightReason:收藏下
  • 最后还是个农:请教下,播放url失败后VLC会有一个弹框提示,这个在哪去掉,找了半天,没有看到,求指教
    辣椒小鱼:请教下 这个弹框 vlc 怎么去掉???
    最后还是个农:@Pocket 好的,非常感谢:smile:
    Pocket:我有时间去看看啊,有可能是写库的人写进去的,没去掉,没找到怕是要自己编译了。
  • Pocket:统一回复需要demo的,demo和库的下载地址链接已经放到文章最底部了,请自行下载,下载完库后放进工程目录即可:blush: ,demo写的不好勿怪啊,只是作为参考。
    ZJS_Sky:谢谢了
  • c4badbcad3f3:复制楼主的 有声音但是图片卡着不动
  • 梅素内:楼主请问一下我是完全按照你上面的代码复制粘贴的,但是它有一个错误提示[[AlertViewManager shareInstance] showPromptText:self.view context:CustomLocalizedString(@"未获取到视频总时间,请尝试手势快进", nil) minSize:CGSizeMake(60,44) afterDelay:2.0];这句话中的AlertViewManager没有定义
  • ducks:https 的mp3 能播放吗 自建证书
  • 大斜的张:终端一直下载不动 MobileVLCKit 楼主能分享个VLCKit包吗
    ZJS_Sky:@ACFl_l 用pod 试试 pod 'MobileVLCKit'
    ACFl_l:你好,请问你拿到那VLC包了么,我这边也是下载不动,能分享一下么
  • PointOne:楼主 M3u8格式你能看么 我怎么看不了啊
  • 3e940d9945b3:我想问一下多个视频同时播放,各个的视频的声音怎么控制
  • feeb4f7688f8:你好,请问VLC能够获取 缓冲进度及缓冲速度吗?如果能,如何获取呢。查了好多资料。有的说API没有开放,有的就没说缓冲的事。
    5f3040a1cc26:请问一下你获取缓冲进度实现了吗,VLC好像没有这个接口啊,不知能否赐教,谢谢。。这都18年了,还是找不到获取缓冲进度的方法
  • 云画的跃光:請問這個錯誤是什麼?我是用服務器傳過來的rtsp流
    creating player instance using shared library
    [1cbb9c44] core generic error: option marq-color does not exist
    [1cbb9c44] core generic error: option marq-opacity does not exist
    [1cbb9c44] core generic error: option marq-position does not exist
    [1cbb9c44] core generic error: option marq-refresh does not exist
    [1cbb9c44] core generic error: option marq-size does not exist
    [1cbb9c44] core generic error: option marq-timeout does not exist
    [1cbb9c44] core generic error: option marq-x does not exist
    [1cbb9c44] core generic error: option marq-y does not exist
    [1da3f064] live555 demux error: Failed to connect with rtsp://10.160.83.246:1935/G_LIVE/T0022
    [1cbbde04] core input error: open of `RTSP://10.160.83.246:1935/G_LIVE/T0022' failed
  • 云画的跃光:你好,我想請問下,從服務器得到的地址怎麼傳到播放器去
    62de48dd0dc0:你好,请问下,为什么我集成进去了画面预览在Android7.0下面会出现黑框了?
    云画的跃光:@Pocket rest://什麼的?但是我從服務器得到的是這個,在那裡報錯的是:rtsp:/,變成單斜杆了
    Pocket:@云画的跃光 具体得到的是什么协议的URL呢
  • 杰克道长:我播放网络视频时,为什么画面总会很卡?
    ZJS_Sky:@Pocket 延迟调高什么操作
    Pocket:@杰克道长 具体是什么格式的视频呢,有些格式如果碰到比较卡或者花屏需要稍微把延迟调高一些,使其得到足够的缓存在解码,这样就不容易掉帧。
  • 晓_我想去环游世界:好像不是支持很多格式 视频监控的一个地址rtsp://218.204.223.237:554/live/1/66251FC11353191F/e7ooqwcfbqjoo80j.sdp
    不知道是播放器的问题还是配置问题
    Pocket:@晓_我想去环游世界 后缀是sdp,不知道是什么格式的流,一般内部对格式判断是用文件路径后缀来决定解码器的类型。
  • 银千特iv:是不是进度条及一些时间的状态放delegate里面更新会好一点啊?
    Pocket:@银千特iv 你觉得好可以试着去增加几个代理方法,这个只是抛砖引玉。
  • iOSNoteByNiu:请问楼主,我在做视频的实时监控,VLC播放器与系统的播放器有什么区别吗
    Pocket:@veryGood 那得问你们后台用什么协议传输
    iOSNoteByNiu:@Pocket 哦,实现监控视频的实时播放时,后台给我的视频地址也是类似于以http开头的吗?就像这个http://flv2.bn.netease.com/tvmrepo/2016/11/7/Q/EC5FO5O7Q/SD/EC5FO5O7Q-mobile.mp4
    Pocket:@veryGood 系统的一般是硬解,不过支持的格式不算很多,VLC内部集成了FFMpeg和Live555,是软解,不过基本大部分格式都支持。
  • 晓_我想去环游世界:楼主可否给我一份VLC的静态库呢?990610967@qq.com
    Pocket:@晓_我想去环游世界 静态库有点大,不好发,你自己cocoapods也很快的
  • f324138e5762:请问楼主用这个打包后包的大小增加了多少?3M有没有?
    Pocket:@LimyronChin 整一个lib都几百M,打包后我也忘了增加具体多少M了,不过肯定不止3M吧,印象中打包后的app总大小可以接受。
  • bdb6bf9183c5:还有就是如果我在option这里把host和port设置了。那我启动的时候还用不用传uri
  • bdb6bf9183c5:我是这么设置的 options.add("--rtsp-tcp"); 另外这个文档我也都看过一遍都试过了,。设置port那个命令也试过。没起作用。不知道是option没添加进去还是本身就没用
  • bdb6bf9183c5:能加个qq么530400138,详细说下、 :smile:
  • bdb6bf9183c5:问下楼主。最近在做行车记录仪的对接。android的。一个是rtsp的一个是tcp的。试过vlc,tcp怎么也连接不上,后来改用ijkplayer,虽然2总方式都能播放但是延迟好长,10几秒的延迟。不知道楼主有什么解决办法?vlc 应该支持tcp的吧,应该是我代码设置不对的。所有2个问题:1:Vcl能实现tcp 播放视频流么?2:ijkplayer 怎么降低延迟。
    Pocket:不好意思,那个参数写错了,你改成--rtsp-tcp,vlc貌似一般都基于udp ,所以主动开启一下基于tcp方式
    bdb6bf9183c5:@Pocket rtsp-tcp 我试过。貌似不行。现在问题就是。流地址能够connnect,并且open,然后就没有然后了。我现在还是倾向于解决vlc显示tcp方式的视频流。各种方式也都试过了,技术有限,项目又急,楼主有时间能研究下不。
    Pocket:@mozzieC 支持tcp,记得在创建对象的时候有一个参数,传的字典,里面你设置对应的rtsp-tcp看看可不可以,延迟的话也有对应参数设置,ijk 里也有相应的设置,不过我没怎么去用这个库,你可以百度一下ijk 延迟问题参数设置,都是基于ffmpeg ,延迟参数应该长的差不多
  • FTC陳:你好,您这个有demo吗?
    Pocket:@ttdiOS 好,前段时间太忙,都没看简书,晚上回去把项目里的功能抽出来写个demo 放github 上:blush:
    ttdiOS:@Pocket 麻烦群主尽快出demo工程,【贴的代码很完整啊,复制一下就好了。】和完整的demo时2码事
    Pocket:@FTC晨 不好意思,有几天没光顾简书,我贴的代码很完整啊,复制一下就好了。
  • 失落柒夏: :sparkling_heart: 你好 我最近刚刚开始研究VLC直播 本身就是iOS小白 想请问能不能发一份Demo给我呢? 1042540668@qq.com 非常感谢~~
    ttdiOS:@JackLiaoSir vlc库需要自己去下载,内存太大,,,demo很简单
    Jack_Liao:@ttdiOS 🐶你好 我最近刚刚开始研究VLC直播 本身就是iOS小白 想请问能不能发一份Demo给我呢? 937902524@qq.com 非常感谢~~😂
    ttdiOS:你好 我最近刚刚开始研究VLC直播 本身就是iOS小白 想请问能不能发一份Demo给我呢? 1107214478@qq.com 非常感谢~~
  • coding_Liu:你好,我最近这在做关于直播的,请问 截屏的功能你了解吗 :stuck_out_tongue_winking_eye:
    afa38ae8399f:@Pocket 我最近也在做这个,您能否加我一下qq,一起研究下,1427945373
    coding_Liu:@Pocket 好,我试一下,我vlc基本上也已经做完了,加一下qq有问题可以相互讨论一下。952626944 :smile:
    Pocket:@听雨翎 截屏我没有真的去实现这个功能,不过我看VLC里有一个方法是保存当前视频的快照。你可以试一下。设置一下保存本地路径和快照宽高参数应该就可以理论上。- (void)saveVideoSnapshotAt: (NSString *)path withWidth:(int)width andHeight:(int)height;
  • uncleRX:顶一个

本文标题:VLC集成与使用

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