IJKMediaFramework、LFLiveKit实现视频直播

视频直播

拉流:

从服务器获取视频直播流地址,播放直播 使用IJKMediaFramework.framework
使用:

    IJKFFOptions *options = [IJKFFOptions optionsByDefault];
    [options setPlayerOptionIntValue:1  forKey:@"videotoolbox"];
    // 帧速率(fps) (可以改,确认非标准桢率会导致音画不同步,所以只能设定为15或者29.97)
    [options setPlayerOptionIntValue:29.97 forKey:@"r"];
    // -vol——设置音量大小,256为标准音量。(要设置成两倍音量时则输入512,依此类推
    [options setPlayerOptionIntValue:512 forKey:@"vol"];
    IJKFFMoviePlayerController *moviePlayer = [[IJKFFMoviePlayerController alloc] initWithContentURLString:flv withOptions:options];
    moviePlayer.view.frame = self.contentView.bounds;
    // 填充fill
    moviePlayer.scalingMode = IJKMPMovieScalingModeAspectFill;
    // 设置自动播放(必须设置为NO, 防止自动播放, 才能更好的控制直播的状态)
    moviePlayer.shouldAutoplay = NO;
    // 默认不显示
    moviePlayer.shouldShowHudView = NO;
    
    [self.contentView insertSubview:moviePlayer.view atIndex:0];
    
    [moviePlayer prepareToPlay];
    
    self.moviePlayer = moviePlayer;

推流:

开始直播,视频采集和视频流处理与传输
直播采用L
LFLiveKit 支持的流类型
rtmp格式 、 tcp 传输flv格式

使用

开播逻辑

- (void)startLive {
    MPLiveModel *liveModel = [ZQGlobalObject sharedZQGlobalObject].liveModel;
    // 拼接推流地址 “url/流名”
    NSString *url = [NSString stringWithFormat:@"%@/%@", liveModel.rtmpUrl, liveModel.videoId];
    // 创建流对象
    LFLiveStreamInfo *stream = [LFLiveStreamInfo new];
    stream.url = url;
    // 推流对象开始推流
    [_session startLive:stream];
}

进出后台处理

#pragma mark 应用程序通知监听
- (void)applicationNotification:(NSNotification *)note {
    if (_session) {
        // 进入后台
        if (note.name == UIApplicationDidEnterBackgroundNotification) { // 进入后台
            NSLog(@"进入后台");
            [_controlView pauseLive];
        // 从后台回到直播间
        } else if (note.name == UIApplicationWillEnterForegroundNotification) {
            if (!_session.running) {
                _session.running = YES;
            }
            [self startLive];
        }
    }
}

退出直播间,释放对象

- (void)dealloc {
    if (_session) {
        _session.delegate = nil;
        _session = nil;
    }
    NSLog(@"退出直播间");
}

创建推流对象并设置播放参数

- (LFLiveSession *)session {
    if(!_session){
       
        _session = [[LFLiveSession alloc] initWithAudioConfiguration:[LFLiveAudioConfiguration defaultConfiguration] videoConfiguration:[LFLiveVideoConfiguration defaultConfigurationForQuality:LFLiveVideoQuality_Medium2 orientation:UIInterfaceOrientationPortrait] liveType:LFLiveRTMP];
        _session.delegate = self;
        _session.running = YES;
        _session.preView = _preview;
    }
    return _session;
}

创建推流要展示推流效果的视图对象

- (MPLiveControlView *)controlView {
    if (_controlView == nil) {
        _controlView = [[MPLiveControlView alloc] initWithFrame:self.view.frame];
        _controlView.delegate = self;
        _controlView.session = self.session;
    }
    return _controlView;
}

推流状态的回调

- (void)liveSession:(nullable LFLiveSession *)session liveStateDidChange:(LFLiveState)state{
    NSLog(@"liveStateDidChange: %ld", state);
    WS(weakSelf);
    dispatch_async(dispatch_get_main_queue(), ^{
        switch (state) {
            case LFLiveReady:
                [weakSelf.controlView setLiveState:MPLiveStateLoading];
                break;
            case LFLivePending:
                [weakSelf.controlView setLiveState:MPLiveStateLoading];
                break;
            case LFLiveStart:
                [weakSelf.controlView setLiveState:MPLiveStatePlay];
                break;
            case LFLiveError:
    //            _stateLabel.text = @"连接错误";
                break;
            case LFLiveStop:
                [weakSelf.controlView setLiveState:MPLiveStateStop];
                break;
            default:
                break;
        }
    });
}
- (void)liveSession:(nullable LFLiveSession *)session debugInfo:(nullable LFLiveDebug*)debugInfo{
    NSLog(@"debugInfo: %lf", debugInfo.dataFlow);
}
- (void)liveSession:(nullable LFLiveSession*)session errorCode:(LFLiveSocketErrorCode)errorCode{
    NSLog(@"errorCode: %ld", errorCode);
}

弹幕可以使用BarrageRenderer

简单使用:

_renderer = [[BarrageRenderer alloc] init];
// 设置弹幕的显示区域. 基于父控件的.
_renderer.canvasMargin = UIEdgeInsetsMake(ALinScreenHeight * 0.3, 10, 10, 10);
[self.contentView addSubview:_renderer.view];

弹幕配置

#pragma mark - 弹幕描述符生产方法
/// 生成精灵描述 - 过场文字弹幕
- (BarrageDescriptor *)walkTextSpriteDescriptorWithDirection:(NSInteger)direction
{
    BarrageDescriptor * descriptor = [[BarrageDescriptor alloc]init];
    descriptor.spriteName = NSStringFromClass([BarrageWalkTextSprite class]);
    descriptor.params[@"text"] = self.danMuText[arc4random_uniform((uint32_t)self.danMuText.count)];
    descriptor.params[@"textColor"] = Color(arc4random_uniform(256), arc4random_uniform(256), arc4random_uniform(256));
    descriptor.params[@"speed"] = @(100 * (double)random()/RAND_MAX+50);
    descriptor.params[@"direction"] = @(direction);
    descriptor.params[@"clickAction"] = ^{
        UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"弹幕被点击" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:nil];
        [alertView show];
    };
    return descriptor;
}
 
[_renderer start];

你可能感兴趣的:(IJKMediaFramework、LFLiveKit实现视频直播)