iOS开发攻城狮的集散地

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

2018-07-04  本文已影响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

上一篇下一篇

猜你喜欢

热点阅读