直播
iOS
产品介绍
简介
主要功能
产品优势
应用场景
使用限制
快速开始
推流端SDK
概述
更新日志
集成SDK
开发指南
实现流程
进阶功能
API 参考
播放器SDK
概览
更新日志
下载 SDK 和示例代码
跑通示例项目
集成SDK
开发指南
播放功能
播放控制
查询参数
数据回调
时间戳校对方案
外挂字幕
API 参考
最佳实践
OBS推流使用指南
服务协议

实现流程

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

API 时序图

uml diagram

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

实现方法

1 创建推流实例

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

API原型

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

参数说明

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

示例

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

特殊说明

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

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

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

API原型

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

参数说明

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

示例

[_mediaCapture startVideoPreview:localPreview];

特殊说明

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

3 开始或停止直播

API原型

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

参数说明

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

示例

[_mediaCapture startLiveStream:^(NSError *error) {
                if (error != nil) {
                    //开始推流,出现错误,首先检查参数和网络是否正常,对应日志查看具体错误内容
                    [weakSelf showErrorInfo:error ];
                }
            }];
[_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原型

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

参数说明

示例

[mediaCapture unInitLiveStream];
 mediaCapture = nil;

特殊说明

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

代码示例

  • 必须 SDK涉及到麦克风,摄像头的采集,需要事先打开使用权限,申请权限代码如下。
	- (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;
	}
	
  • 必须 初始化推流对象
    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]; //初始化推流

  • 可调用非必须 打开视频预览
    [_mediaCapture startVideoPreview:self.localPreview];
  • 可调用非必须 开启直播之前可以重新设置推流地址,当然也可以继续使用初始化推流阶段的推流地址。
     _mediaCapture.pushUrl = @"rtmp://pxxx";
  • 可调用非必须 开启直播之前可以重新设置视频相关参数
     [_mediaCapture setBitrate:150000 fps:30 cameraOrientation:LS_CAMERA_ORIENTATION_PORTRAIT];//视频的码率,帧率,以及视频的方向横屏或者竖屏
     
     //如果摄像头方向发生变化了,想要camera的预览画面跟着旋转,则在调用一次开启预览
     [_mediaCapture startVideoPreview:self.localPreview];
  • 可调用非必须 注册mediacapture的notification监听,获取直播过程中的各种状态信息,不是必须
    [[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]; //直播过程中网络差通知
  • 必须 设置获取直播过程中的错误回调
     __weak MediaCaptureViewController *weakSelf = self;
     _mediaCapture.onLiveStreamError = ^(NSError* error)
     {
         if (error != nil) {
            [weakSelf LiveStreamErrorInterrup];
          }
     };
  • 可调用非必须 显示统计信息
     //调用统计数据回调
     _mediaCapture.onStatisticInfoGot = ^(LSStatisticsObject* statistics)
     {
        if (statistics != nil) {
            dispatch_async(dispatch_get_main_queue(),^(void) {[weakSelf showStatInfo:statistics];});
        }
     };
  • 可调用非必须 添加水印
     UIImage* image = [UIImage imageNamed:[[[NSBundle mainBundle] bundlePath]stringByAppendingPathComponent:@"logo.png"]];
     [_mediaCapture addWaterMark:image rect:CGRectMake(20, 20, 60, 34) location:LS_WATERMARK_LOCATION_RIGHTUP];
  • 必须 开启直播
    [_mediaCapture startLiveStream:^(NSError *error) {
        if (error != nil) {
            [weakSelf showErrorInfo:error ];//直播出错可以将出错信息直接显示给用户,也可以封装成统一格式,告诉用户检查网络等情况,尝试重新开启直播
        }
    }];
  • 可调用非必须 直播开启准备工作已经完成,当收到“直播开始notification”,说明推流真的开始了,可以在收到这个notification后,做一些动作,不是必须。
	-(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全部释放,重新来一次初始化,开启直播操作
	-(void)LiveStreamErrorInterrup{
    [_mediaCapture stopLiveStream:^(NSError *error) {
      if (error == nil) {
         NSLog(@"直播结束了");
      }else{
         NSLog(@"结束直播发生错误");//调用 stopLiveStream()
      }
    }];
    }
  • 必须 关闭推流
    __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