美文网首页iOS开发攻城狮的集散地
直播类app中拉流技术的实现[转]

直播类app中拉流技术的实现[转]

作者: 半岛夏天 | 来源:发表于2018-07-04 15:56 被阅读8次

    之前说过推流的实现 ,现在来说一下拉流的实现。demo下载地址:https://pan.baidu.com/s/1fU5SMyEDRAVaGBIBvYzbVw
    拉流的实现我们主要通过LFLiveKit,LFLiveKit支持H264和AAC编码,支持美颜和水印效果,传输协议是rtmp,支持弱网丢帧,记载网络环境差的情况下,为了保证视频的通常,会自动丢弃个别帧。
    先看一下LFLiveKit提供的Demo运行效果:(准备工具VLC软件)
    1.github上搜索LFLiveKit。
    2.打开下载后文件的LFLiveKitDemo工程(这里我们使用的是OC的Demo,不是swift),控制台中cd +这个工程的路径,然后pod install,之后便可运行在真机上。
    3.打开LFLivePreview.m文件,在这个文件的末尾会发现有这样一行代码: stream.url = @"rtmp://live.hkstv.hk.lxdns.com:1935/live/stream153”;并将这个网址复制到浏览器中打开,此时会自动打开VLC软件,点击playList中的网址,便可播放手机端的拉流视频。
    4.如果以上步骤执行无误,就说明手机端的拉流视频已经成功推送到服务器上,我们通过VLC可以获取到服务器上的推流视频。

    接下来看看如何将LFLiveKit继承到我们自己的项目中去。
    首先在podfile文件中添加pod ‘LFLiveKit’ ,然后 pod install。接下来就可以直接开始代码部分了。

    创建一个继承与UIView的LFLivePreview类,在LFLivePreview.h文件中对外提供两个方法,开始拉直播和关闭直播方法。

    @interface LFLivePreview : UIView
    - (void)startLive;
    - (void)stopLive;
    @end
    
    

    在LFLivePreview.m文件中,首先导入头文件#import "LFLiveSession.h”,并遵守LFLiveSessionDelegate协议,然后添加一个属性@property (nonatomic, strong) LFLiveSession *session;看一些这个属性的懒加载代码:

    - (LFLiveSession *)session {
        if (!_session) {
    
            /***   默认分辨率368 * 640  音频:44.1 iphone6以上48  双声道  方向竖屏 ***/
    
            LFLiveAudioConfiguration * audioConfiguration =[LFLiveAudioConfiguration defaultConfiguration];
    
            LFLiveVideoConfiguration * videoConfiguration = [LFLiveVideoConfiguration defaultConfiguration];
            //最新写法
             _session = [[LFLiveSession alloc]initWithAudioConfiguration:audioConfiguration videoConfiguration:videoConfiguration captureType:LFLiveCaptureDefaultMask];
    
           // _session = [[LFLiveSession alloc] initWithAudioConfiguration:audioConfiguration videoConfiguration:videoConfiguration liveType:LFLiveRTMP];
    
            _session.delegate = self;
            _session.showDebugInfo = NO;
            _session.preView = self;
    
        }
        return _session;
    }
    
    

    在初始化这个view的时候首先要实现音频和视频授权操作。

    - (void)requestAccessForVideo {
        __weak typeof(self) _self = self;
        AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
        switch (status) {
        case AVAuthorizationStatusNotDetermined: {
            // 许可对话没有出现,发起授权许可
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
                    if (granted) {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            [_self.session setRunning:YES];
                        });
                    }
                }];
            break;
        }
        case AVAuthorizationStatusAuthorized: {
            // 已经开启授权,可继续
            dispatch_async(dispatch_get_main_queue(), ^{
                [_self.session setRunning:YES];
            });
            break;
        }
        case AVAuthorizationStatusDenied:
        case AVAuthorizationStatusRestricted:
            // 用户明确地拒绝授权,或者相机设备无法访问
    
            break;
        default:
            break;
        }
    }
    
    
    - (void)requestAccessForAudio {
        AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
        switch (status) {
        case AVAuthorizationStatusNotDetermined: {
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
                }];
            break;
        }
        case AVAuthorizationStatusAuthorized: {
            break;
        }
        case AVAuthorizationStatusDenied:
        case AVAuthorizationStatusRestricted:
            break;
        default:
            break;
        }
    }
    
    

    开始直播

    - (void)startLive {
        LFLiveStreamInfo *stream = [LFLiveStreamInfo new];
         //这是直播的网址,直接复制LFLiveKit提供的这个地址
        stream.url = @"rtmp://live.hkstv.hk.lxdns.com:1935/live/stream153";
        [self.session startLive:stream];
    }
    
    - (void)startLive:(LFLiveStreamInfo *)streamInfo {
        if (!streamInfo) return;
        _streamInfo = streamInfo;
        _streamInfo.videoConfiguration = _videoConfiguration;
        _streamInfo.audioConfiguration = _audioConfiguration;
        [self.socket start];
    }
    
    

    停止直播

    - (void)stopLive {
        [self.session stopLive];
    }
    
    - (void)stopLive {
        self.uploading = NO;
        [self.socket stop];
        self.socket = nil;
    }
    
    

    美颜效果

    - (void)beautyBtnClick:(UIButton *)btn{
        self.session.beautyFace = !self.session.beautyFace;
        self.beautyButton.selected = !self.session.beautyFace;
    }
    
    

    镜头切换

    - (void)cameraBtnClick:(UIButton *)btn{
        AVCaptureDevicePosition devicePositon = self.session.captureDevicePosition;
        self.session.captureDevicePosition = (devicePositon == AVCaptureDevicePositionBack) ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack;
    }
    
    

    退出直播

    - (void)closeBtnClick:(UIButton *)btn{
        [self stopLive];
        [self.controller dismissViewControllerAnimated:YES completion:nil];
    }
    
    

    下面这个代理方法是监控直播状态的代理方法

    - (void)liveSession:(nullable LFLiveSession *)session liveStateDidChange:(LFLiveState)state {
        NSLog(@"liveStateDidChange: %ld", state);
        switch (state) {
        case LFLiveReady:
            _stateLabel.text = @"未连接";
            break;
        case LFLivePending:
            _stateLabel.text = @"连接中";
            break;
        case LFLiveStart:
            _stateLabel.text = @"已连接";
            break;
        case LFLiveError:
            _stateLabel.text = @"连接错误";
            break;
        case LFLiveStop:
            _stateLabel.text = @"未连接";
            break;
        default:
            break;
        }
    }
    
    

    外部直播控制器界面调用形式

    - (IBAction)startLive:(id)sender {
        UIView * back = [[UIView alloc] initWithFrame:self.view.bounds];
        back.backgroundColor = [UIColor blackColor];
        [self.view addSubview:back];
        LFLivePreview * liveView = [[LFLivePreview alloc] initWithFrame:self.view.bounds withController:self];
        [self.view addSubview:liveView];
        [liveView startLive];
    }
    
    

    原文链接:https://www.jianshu.com/p/4da61fb44441

    相关文章

      网友评论

        本文标题:直播类app中拉流技术的实现[转]

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