实现流程

更新时间: 2022/12/29 08:24:51

API 时序图

uml diagram

init与unInit,start与stop都要保持匹配使用。

实现方法

1 创建推流实例

SDK在初始化推流阶段,设置推流地址,配置推流参数。创建推流session 提供的接口有三种,您可以根据是否需要定制直播参数而选择。

API原型

  • 只设置直播推流的地址,创建直播推流对象,其它推流相关参数将采用默认配置:
objc/**
 *  初始化mediacapture
 *
 *  @param  liveStreamingURL 推流的url地址
 *
 *  @return LSMediaCapture
 */
-(instancetype)initLiveStream:(NSString *)liveStreamingURL 
  • 设置直播推流的地址,并支持设置直播中的视频相关参数:
objc/**
 初始化mediacapture
 
 @param liveStreamingURL 推流的url
 @param videoParaCtx 推流视频参数
 @return LSMediaCapture
 */
- (instancetype)initLiveStream:(NSString *)liveStreamingURL withVideoParaCtxConfiguration:(LSVideoParaCtxConfiguration *)videoParaCtx
  • 设置直播推流的地址,并支持设置直播中的音视频所有可配置参数:
objc/**
 初始化mediacapture
 
 @param liveStreamingURL 推流的url
 @param configuration 推流参数
 @return LSMediaCapture
 */
- (instancetype)initLiveStream:(NSString *)liveStreamingURL withLivestreamParaCtxConfiguration:(LSLiveStreamingParaCtxConfiguration *)configuration

参数说明

参数 类型 说明
liveStreamingURL NSString 推流地址
videoParaCtx LSVideoParaCtxConfiguration 视频参数
configuration LSLiveStreamingParaCtxConfiguration 音视频参数

示例

objcLSMediaCapture *mediaCapture = [[LSMediaCapture alloc]initLiveStream:url withLivestreamParaCtxConfiguration:streamparaCtx];

特殊说明

请通过如下代码检测初始化推流是否成功,避免因相关硬件读取失败,导致无法正常使用推流SDK。

objcif (mediaCapture == nil) {
        NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"初始化失败" forKey:NSLocalizedDescriptionKey];
        NSError *error = [NSError errorWithDomain:@"LSMediaCaptureErrorDomain" code:0 userInfo:userInfo];
    }

2 打开、暂停、恢复视频预览

API原型

objc/**
 *  打开视频预览
 *
 *  @param  preview 预览窗口
 */
-(void)startVideoPreview:(UIView*)preview
objc/**
 *  @warning 暂停视频预览。如果正在直播,则同时关闭视频预览以及视频推流
 *
 */
- (void)pauseVideoPreview
objc/**
 *  @warning 继续视频预览。如果正在直播,则开始视频推流
 *
 */
- (void)resumeVideoPreview

参数说明

参数 类型 说明
preview UIView 需要显示的预览画面

示例

objc[_mediaCapture startVideoPreview:localPreview];

特殊说明

支持直播过程中改变preview的大小。

3 开始或停止直播

API原型

objc/**
 *  开始直播
 *
 *  @param completionBlock 具体错误信息
 */
- (void)startLiveStream:(void(^)(NSError *error))completionBlock;
objc/**
 *  结束推流
 * @warning 只有直播真正开始后,也就是收到LSLiveStreamingStarted消息后,才可以关闭直播,error为nil的时候,说明直播结束,否则直播过程中发生错误
 */
- (void)stopLiveStream:(void(^)(NSError *error))completionBlock;

参数说明

参数 类型 说明
completionBlock void(^)(NSError *error) 开始和停止直播过程中发生的错误回调。nil表示正常。

示例

objc[_mediaCapture startLiveStream:^(NSError *error) {
                if (error != nil) {
                    //开始推流,出现错误,首先检查参数和网络是否正常,对应日志查看具体错误内容
                    [weakSelf showErrorInfo:error ];
                }
            }];
objc[_mediaCapture stopLiveStream:^(NSError *error) {
                if (error == nil) {
                    dispatch_async(dispatch_get_main_queue(), ^(void){
                        _isLiving = NO;
                        [weakSelectView.startBtn setBackgroundImage:[UIImage imageNamed:@"restart"] forState:UIControlStateNormal];
                    });
                }
            }];

特殊说明

4 释放推流实例

反初始化:释放资源

API原型

objc/**
 反初始化:释放资源
 */
-(void)unInitLiveStream

参数说明

示例

objc[mediaCapture unInitLiveStream];
 mediaCapture = nil;

特殊说明

建议在调用unInitLiveStream之后,将mediaCapture实例对象置为空,用于完全释放资源

代码示例

  • 必须 SDK涉及到麦克风,摄像头的采集,需要事先打开使用权限,申请权限代码如下。
objc	- (BOOL)requestMediaCapturerAccessWithCompletionHandler:(void (^)(BOOL, NSError*))handler {
    AVAuthorizationStatus videoAuthorStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    AVAuthorizationStatus audioAuthorStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
    
    if (AVAuthorizationStatusAuthorized == videoAuthorStatus && AVAuthorizationStatusAuthorized == audioAuthorStatus) {
        handler(YES,nil);
    }else{
        if (AVAuthorizationStatusRestricted == videoAuthorStatus || AVAuthorizationStatusDenied == videoAuthorStatus) {
            NSString *errMsg = NSLocalizedString(@"此应用需要访问摄像头,请设置", @"此应用需要访问摄像头,请设置");
            NSDictionary *userInfo = @{NSLocalizedDescriptionKey:errMsg};
            NSError *error = [NSError errorWithDomain:@"访问权限" code:0 userInfo:userInfo];
            handler(NO,error);
            
            return NO;
        }
        
        if (AVAuthorizationStatusRestricted == audioAuthorStatus || AVAuthorizationStatusDenied == audioAuthorStatus) {
            NSString *errMsg = NSLocalizedString(@"此应用需要访问麦克风,请设置", @"此应用需要访问麦克风,请设置");
            NSDictionary *userInfo = @{NSLocalizedDescriptionKey:errMsg};
            NSError *error = [NSError errorWithDomain:@"访问权限" code:0 userInfo:userInfo];
            handler(NO,error);
            
            return NO;
        }
        
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
            if (granted) {
                [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
                    if (granted) {
                        handler(YES,nil);
                    }else{
                        NSString *errMsg = NSLocalizedString(@"不允许访问麦克风", @"不允许访问麦克风");
                        NSDictionary *userInfo = @{NSLocalizedDescriptionKey:errMsg};
                        NSError *error = [NSError errorWithDomain:@"访问权限" code:0 userInfo:userInfo];
                        handler(NO,error);
                    }
                }];
            }else{
                NSString *errMsg = NSLocalizedString(@"不允许访问摄像头", @"不允许访问摄像头");
                NSDictionary *userInfo = @{NSLocalizedDescriptionKey:errMsg};
                NSError *error = [NSError errorWithDomain:@"访问权限" code:0 userInfo:userInfo];
                handler(NO,error);
            }
        }];
        
    }
    return YES;
	}
	
  • 必须 初始化推流对象
objc    LSLiveStreamingParaCtxConfiguration *paraCtx = [LSLiveStreamingParaCtxConfiguration defaultLiveStreamingConfiguration];//直播推流参数
     
    paraCtx.eHaraWareEncType             = LS_HRD_AV;
    paraCtx.eOutFormatType               = LS_OUT_FMT_RTMP;
    paraCtx.eOutStreamType               = LS_HAVE_AV; //这里可以设置推音视频流/音频流/视频流,如果只推送视频流,则不支持伴奏播放音乐
    
    //视频相关参数
    paraCtx.sLSVideoParaCtx.interfaceOrientation       = LS_CAMERA_ORIENTATION_PORTRAIT;//摄像头的方向,可以选择横屏或者竖屏
    paraCtx.sLSVideoParaCtx.cameraPosition             = LS_CAMERA_POSITION_FRONT;//前后摄像头
    paraCtx.sLSVideoParaCtx.bitrate                    = 640000; //码率
    paraCtx.sLSVideoParaCtx.fps                        = 24;     //帧率
    paraCtx.sLSVideoParaCtx.videoStreamingQuality      = LS_VIDEO_QUALITY_HIGH; //分辨率
    
    paraCtx.sLSVideoParaCtx.isCameraZoomPinchGestureOn = YES; //打开摄像头zoom功能
    paraCtx.sLSVideoParaCtx.isCameraFlashEnabled       = YES; //打开摄像头flash功能
    paraCtx.sLSVideoParaCtx.isVideoWaterMarkEnabled    = YES; //开启水印
    paraCtx.sLSVideoParaCtx.videoRenderMode            = LS_VIDEO_RENDER_MODE_SCALE_16x9;//设置为16:9模式 //对端接收的图像将以16:9比例绘制
    paraCtx.sLSVideoParaCtx.isVideoFilterOn            = YES;  //开启美颜
    paraCtx.sLSVideoParaCtx.filterType                 = LS_GPUIMAGE_ZIRAN;//默认使用这种滤镜
    paraCtx.sLSVideoParaCtx.isQosOn                    = YES;  // 开启码率自适应调整功能
    paraCtx.sLSVideoParaCtx.isFrontCameraMirroredPreView               = YES; //是否镜像前置摄像头预览
    paraCtx.sLSVideoParaCtx.isFrontCameraMirroredCode                  = NO; //是否镜像前置摄像头编码

    
    //音频相关参数
    paraCtx.sLSAudioParaCtx.bitrate       = 64000;
    paraCtx.sLSAudioParaCtx.frameSize     = 2048;
    paraCtx.sLSAudioParaCtx.numOfChannels = 1;
    paraCtx.sLSAudioParaCtx.samplerate    = 44100;
     
    
    NSString* _streamUrl = @"rtmp:pxxxxx" ;//初始化阶段允许 此字段为nil
    
    LSMediaCapture* _mediaCapture;
    
    _mediaCapture = [[LSMediaCapture alloc]initLiveStream:_streamUrl withLivestreamParaCtxConfiguration:paraCtx]; //初始化推流

  • 可调用非必须 打开视频预览
objc    [_mediaCapture startVideoPreview:self.localPreview];
  • 可调用非必须 开启直播之前可以重新设置推流地址,当然也可以继续使用初始化推流阶段的推流地址。
objc     _mediaCapture.pushUrl = @"rtmp://pxxx";
  • 可调用非必须 开启直播之前可以重新设置视频相关参数
objc     [_mediaCapture setBitrate:150000 fps:30 cameraOrientation:LS_CAMERA_ORIENTATION_PORTRAIT];//视频的码率,帧率,以及视频的方向横屏或者竖屏
     
     //如果摄像头方向发生变化了,想要camera的预览画面跟着旋转,则在调用一次开启预览
     [_mediaCapture startVideoPreview:self.localPreview];
  • 可调用非必须 注册mediacapture的notification监听,获取直播过程中的各种状态信息,不是必须
objc    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onStartLiveStream:) name:LS_LiveStreaming_Started object:nil]; //直播开始通知
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onFinishedLiveStream:) name:LS_LiveStreaming_Finished object:nil]; // 直播结束通知
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onBadNetworking:) name:LS_LiveStreaming_Bad object:nil]; //直播过程中网络差通知
  • 必须 设置获取直播过程中的错误回调
objc     __weak MediaCaptureViewController *weakSelf = self;
     _mediaCapture.onLiveStreamError = ^(NSError* error)
     {
         if (error != nil) {
            [weakSelf LiveStreamErrorInterrup];
          }
     };
  • 可调用非必须 显示统计信息
objc     //调用统计数据回调
     _mediaCapture.onStatisticInfoGot = ^(LSStatisticsObject* statistics)
     {
        if (statistics != nil) {
            dispatch_async(dispatch_get_main_queue(),^(void) {[weakSelf showStatInfo:statistics];});
        }
     };
  • 可调用非必须 添加水印
objc     UIImage* image = [UIImage imageNamed:[[[NSBundle mainBundle] bundlePath]stringByAppendingPathComponent:@"logo.png"]];
     [_mediaCapture addWaterMark:image rect:CGRectMake(20, 20, 60, 34) location:LS_WATERMARK_LOCATION_RIGHTUP];
  • 必须 开启直播
objc    [_mediaCapture startLiveStream:^(NSError *error) {
        if (error != nil) {
            [weakSelf showErrorInfo:error ];//直播出错可以将出错信息直接显示给用户,也可以封装成统一格式,告诉用户检查网络等情况,尝试重新开启直播
        }
    }];
  • 可调用非必须 直播开启准备工作已经完成,当收到“直播开始notification”,说明推流真的开始了,可以在收到这个notification后,做一些动作,不是必须。
objc	-(void)onStartLiveStream:(NSNotification*)notification
	{
	    NSLog(@"on start live stream");//只有收到直播开始的 信号,才可以关闭直播
	    
	    __weak MediaCaptureViewController *weakSelf = self;
	    dispatch_async(dispatch_get_main_queue(), ^(void){
	        _isLiving = YES;
	        weakSelf.showStatButton.enabled = YES;
	        
	        UIImage *startBtnImage = [UIImage imageNamed:@"pause0.png"];
	        [weakSelf.startButton setImage:startBtnImage  forState:UIControlStateNormal];
	        
	        //当直播开始时,获取当前最新的一张图片
	        [ weakSelf.mediaCapture snapShotWithCompletionBlock:^(UIImage *latestFrameImage) {
	            UIImageWriteToSavedPhotosAlbum(latestFrameImage, weakSelf, nil, nil);
	        }];
	    });
	}
  • 必须 当收到直播出错回调,需要关闭直播,您可以在关闭推流之后,重新开启直播,不需要将资源释放,当然也可以将资源mediacapture全部释放,重新来一次初始化,开启直播操作
objc	-(void)LiveStreamErrorInterrup{
    [_mediaCapture stopLiveStream:^(NSError *error) {
      if (error == nil) {
         NSLog(@"直播结束了");
      }else{
         NSLog(@"结束直播发生错误");//调用 stopLiveStream()
      }
    }];
    }
  • 必须 关闭推流
objc    __weak MediaCaptureViewController *weakSelf1 = self;
    [_mediaCapture stopLiveStream:^(NSError *error) {
       if (error == nil) {
           NSLog(@"直播结束了");
       }else{
          NSLog(@"结束直播发生错误");//调用 stopLiveStream()
       }
    }];
  • 至此,一次推流过程结束,如果您需要再次开启直播,可以直接 回到 开启直播动作,也可以将 _mediaCapture资源释放,重新从初始化推流 开始。

Demo接入Faceunity

  • Faceunity的github地址
  • Demo 已集成Faceunity相关功能,假设你需要在demo中演示相关功能,需要打开demo中的开关,并向Faceunity或者网易云信视频索要具体的证书秘钥。
  • 具体的操作如下图所示。

pic

  • 打开demo开关

pic

  • 填写具体的证书秘钥

pic

此文档是否对你有帮助?
有帮助
去反馈
  • API 时序图
  • 实现方法
  • 1 创建推流实例
  • API原型
  • 参数说明
  • 示例
  • 特殊说明
  • 2 打开、暂停、恢复视频预览
  • API原型
  • 参数说明
  • 示例
  • 特殊说明
  • 3 开始或停止直播
  • API原型
  • 参数说明
  • 示例
  • 特殊说明
  • 4 释放推流实例
  • API原型
  • 参数说明
  • 示例
  • 特殊说明
  • 代码示例
  • Demo接入Faceunity