iOS直播推流SDK开发集成

1 概述

1.1 SDK简介

1.1.1 SDK业务简介

网易云通信直播源自网易多年视频技术沉淀,基于专业的跨平台视频编解码技术和大规模视频内容分发网络,提供稳定流畅、低延时、高并发的直播服务。

网易云直播推流SDK,用于支持在直播流程中,采集摄像头或自定义音视频数据,进行视频前处理,并进行编码推流到服务器。具有稳定、高效、功能全面的特点。

1.1.2 SDK技术简介

直播推流 SDK 由如下图所示的结构组成。 其中,实线框是直播的主要模块,包括音视频采集、处理、编码和打包发送。虚线框是辅助模块,关闭后不影响直播功能。

网络信息统计功能帮助开发者实现网络状况的实时监测,尤其在弱网络环境下,能够快速准确的探知网络可用带宽等信息,帮助开发者调整产品策略,改善产品的用户体验。

1.2 设备和系统要求:

1.3 功能特性

2 开发准备

2.1 准备工作

2.2 集成SDK

本文是根据官网的直播推流 Demo 来介绍 SDK 的集成,可在网易云官网下载最新的直播推流 iOS Demo,来查看更多的实现细节。

2.2.1 集成方式

直播 SDK 提供两种集成方式:您既可以通过 CocoaPods 自动集成我们的 SDK,也可以通过手动下载 SDK, 然后添加到您的项目中。

我们提供两个下载地址。分别为:

手动集成

直播推流 SDK 包含 demo、libs、docs 三个部分,在网易云信官网可以下载 Demo 和 SDK 包

libs
├── NMCLiveStreaming.framework
└── NMCVideoFilter.bundle

开发者将动态库和资源文件导入自己的工程即可。

自动集成

Podfile 文件中加入

直播完整版:

  pod 'NMCLiveStreaming'

或 直播 精简版

  pod 'NMCLiveStreaming_MINI'

安装

  pod install

如果无法安装 SDK 最新版本,运行以下命令更新本地的 CocoaPods 仓库列表

  pod repo update

3 API概览

类别 API名称 功能
创建推流实例1 - (instancetype)initLiveStream:(NSString *)liveStreamingURL; 只需要设置推流地址的创建直播推流对象,其它推流相关参数将采用默认配置
创建推流实例2 - (instancetype)initLiveStream:(NSString )liveStreamingURL withVideoParaCtxConfiguration:(LSVideoParaCtxConfiguration )videoParaCtx; 不仅设置直播推流的地址,同时提供直播中视频相关参数设置
创建推流实例3 - (instancetype)initLiveStream:(NSString )liveStreamingURL withLivestreamParaCtxConfiguration:(LSLiveStreamingParaCtxConfiguration )configuration; 不仅设置直播推流地址,同时提供直播中所有可配置参数设置
销毁推流实例 -(void)unInitLiveStream; 反初始化:释放资源;建议在调用unInitLiveStream之后,将mediaCapture实例对象置为空,用于完全释放资源
打开视频预览 -(void)startVideoPreview:(UIView*)preview SDK提供视频预览功能,上层需要创建 UIView 对象,作为视频预览的窗口
暂停视频预览 - (void)pauseVideoPreview 画面不移除,暂停视频采集
继续视频预览 - (void)resumeVideoPreview 恢复视频采集
开始直播 - (void)startLiveStream:(void(^)(NSError *error))completionBlock 开始音视频推流,开始失败的具体消息由 NSError参数给出
结束推流 - (void)stopLiveStream:(void(^)(NSError *error))completionBlock 结束音视频推流,结束失败的具体消息由 NSError参数给出
中断视频推流 - (void)pauseVideoLiveStream 中断视频编码,最终不会发送
重启视频推流 - (void)resumeVideoLiveStream 恢复视频编码,最终发送
中断音频推流 - (BOOL)pauseAudioLiveStream 中断音频编码,最终不会发送
重启音频推流 - (BOOL)resumeAudioLiveStream 恢复音频编码,最终发送
更新自定义统计数据 - (void)updateCutomStatistics:(NSDictionary *)customDict 添加一些自定义的统计数据到网易云统计数据管理平台
检查是否正在直播 - (BOOL)checkIsLiving 获取当前直播状态
设置日志的level - (void)setTraceLevel:(LSMediaLog)logLevel 设置日志的级别
获取当前sdk的版本号 + (NSString*) getSDKVersionID 获取当前sdk的版本号
获取当前视频帧时间戳 -(uint64_t)currentSyncTimestamp 获取当前视频帧时间戳,对应syncTimestamp一起使用
获取当前时间戳 -(uint64_t)currentStreamTimestamp 获取当前时间戳,对应streamTimestampPassthrough一起使用
发送自定义数据 -(NSError )sendCustomData:(LSCustomDataObject )sendObject 发送自定义数据
开始录制并保存本地文件(mp4录制) - (BOOL)startRecord:(NSString *)recordFileName videoStreamingQuality:(LSVideoStreamingQuality)videoStreamingQuality videoBitrate:(NSInteger)bitrate 开启mp4录制
停止本地录制 - (BOOL)stopRecord 停止mp4录制
开始播放混音文件 - (BOOL)startPlayMusic:(NSString*)musicURL withEnableSignleFileLooped:(BOOL)enableLoop 支持是否循环播放
结束播放混音文件,释放播放文件 - (BOOL)stopPlayMusic 结束播放混音文件
恢复播放混音文件 - (BOOL)resumePlayMusic 恢复播放混音文件
中断播放混音文件 - (BOOL)pausePlayMusic 中断播放混音文件
设置混音强度 - (void)setMixIntensity:(int )value 设置混音强度
采集模块采集的视频数据回调 void (^externalCaptureSampleBufferCallback)(CMSampleBufferRef sampleBuffer) 采集数据回调给外部用户进行视频前处理
将外部前处理之后的视频数据发送给sdk -(void)externalInputSampleBuffer:(CMSampleBufferRef)sampleBuffer 用户将外部进行视频前处理好回送给SDK,进行编码发送
麦克风采集到的原始裸数据的回调 void (^externalCaptureAudioRawData)(AudioBufferList *bufferList,NSInteger inNumberFrames) 采集数据回调给外部用户进行音频前处理,同步处理
将处理完的音频裸数据送回来 -(void)externalInputAudioBufferList:(AudioBufferList *)bufferList inNumberFrames:(NSInteger)inNumberFrames 用户将外部进行音频前处理好回送给SDK,进行编码发送
开始测速 -(void)startSpeedCalc:(NSString )url success:(void(^)(NSMutableArray array))success fail:(void(^)())fail 支持直播开始前测速,选择最优链路推流
结束测速 -(void)stopSpeedCalc 结束此次测速
测速之前设置测速次数和上传数据大小 -(void)setSpeedCacl:(NSInteger)count Capacity:(unsigned long long)capacity 支持设置测速次数和上传文件大小,建议不超过3次,文件大小不宜过大,否则等待时间较久
直播过程中发生错误的回调函数 void (^onLiveStreamError)(NSError *error) 直播过程中,由于各种网络原因引起直播发送错误或者直播断开的情况都会通过该回调通知用户
得到直播过程中的统计信息 void (^onStatisticInfoGot)(LSStatisticsObject* statistics) 直播过程中,实时显示推流的具体信息指标
flash摄像头 BOOL flash 打开或者关闭摄像头flash
摄像头变焦功能属性:最大拉伸值 CGFloat maxZoomScale iphone4s以及之前的版本,videoMaxZoomFactor=1;不支持拉伸
摄像头变焦功能属性:拉伸值 CGFloat zoomScale 1,maxZoomScale] iphone4s以及之前的版本,videoMaxZoomFactor=1;不支持拉伸
摄像头变焦功能属性:拉伸值变化回调block void (^onZoomScaleValueChanged)(CGFloat value) 调整摄像头变焦,实时回调对应的值给用户,用以调整相应的UI
切换前后摄像头 - (LSCameraPosition)switchCamera:(LSSwitchModuleVideoCameraPositionBlock)cameraPostionBlock 前后摄像头切换成功回调告诉用户
切换分辨率 - (BOOL)switchVideoStreamingQuality:(LSVideoStreamingQuality)videoResolution block:(LSVideoStreamingQualityBlock)videoResolutionBlock 支持直播过程中切换分辨率,切换分辨率,水印将自动清除,需要外部根据分辨率,再次设置水印大小
直播推流之前设置如下参数 - (void)setBitrate:(int)bitrate fps:(int)fps cameraOrientation:(LSCameraOrientation) cameraOrientation 直播开始推流之前可以再次设置帧率、码率、采集方向
切换本地预览镜像 -(BOOL)changeIsFrontPreViewMirrored 针对主播,本地观察预览画面左右镜像
切换编码镜像 -(BOOL)changeIsFrontCodeMirrored 针对拉流端观众,拉流观察画面左右镜像
获取视频截图 - (void)snapShotWithCompletionBlock:(LSFrameCaptureCompletionBlock)completionBlock 可以实时截取当前画面的一张图片
设置滤镜类型 - (void)setFilterType:(LSGpuImageFilterType)filterType 设置滤镜类型:黑白、自然、粉嫩、怀旧
设置磨皮强度 - (void)setSmoothFilterIntensity:(float)value 设置人脸的磨皮效果【0-1】
设置美白强度 - (void)setWhiteningFilterIntensity:(float)value 设置美白强度【0-1】
调节曝光度 -(void)adjustExposure:(CGFloat)exposure 调整画面的曝光度(-10.0 - 10.0 ,默认为0.0)
添加涂鸦 - (void)addGraffiti:(UIImage*)image rect:(CGRect)rect location:(LSWaterMarkLocation)location 每次设置一张图片,从而实现涂鸦的一个动态变化,类似可以做一个画板
添加静态视频水印 - (void) addWaterMark: (UIImage*) image rect: (CGRect) rect location: (LSWaterMarkLocation) location 静态水印一般用作视频版权logo显示
关闭本地预览静态水印 - (void)closePreviewWaterMark:(BOOL)isClosed 可以关闭本地预览静态水印,但是拉流端还是存在的
添加动态视频水印 - (void) addDynamicWaterMarks: (NSArray*) imageArray fpsCount: (unsigned int)count loop: (BOOL)looped rect: (CGRect) rect location: (LSWaterMarkLocation) location 动态水印一般用作视频广告推广显示
关闭本地预览动态水印 - (void)closePreviewDynamicWaterMark:(BOOL)isClosed 可以关闭本地预览动态水印,但是拉流端还是存在的
清除水印 - (void)cleanWaterMark 清除之前添加的所有涂鸦、静态水印、动态水印

总体参数介绍

音视频参数介绍

音频参数说明LSAudioParaCtxConfiguration

参数 类型 说明
samplerate NSInteger 音频的样本采集率:默认44100
numOfChannels NSInteger 音频采集的通道数:单声道,双声道,默认单声道
frameSize NSInteger 音频采集的帧大小:默认2048
bitrate NSInteger 音频编码码率:默认64k:64000
isUseExternalCapture BOOL 是否使用外部音频采集,默认不开启
isUseAudioPreProcess BOOL 是否进行音频前处理,默认开启

视频参数说明LSVideoParaCtxConfiguration

参数 类型 说明
fps NSInteger 视频的帧率.(0~30],默认为20
bitrate NSInteger 码率,默认为500000
videoStreamingQuality LSVideoStreamingQuality 视频分辨率,默认高清
cameraPosition LSCameraPosition 视频采集前后摄像头,默认前置
interfaceOrientation LSCameraOrientation 视频采集方向,默认竖屏
videoRenderMode LSVideoRenderScaleMode 视频显示端比例,默认16:9
isCameraFlashEnabled BOOL 是否开启摄像头flash功能,默认开启
isCameraZoomPinchGestureOn BOOL 是否需要打开摄像头收视响应变焦功能,默认开启
isFrontCameraMirroredPreView BOOL 是否镜像前置摄像头预览.(针对本地预览),默认开启
isFrontCameraMirroredCode BOOL 是否镜像前置摄像头编码.(针对拉流端),默认不开启
isVideoFilterOn BOOL 是否打开滤镜支持功能.默认开启
filterType LSGpuImageFilterType 滤镜类型,默认自然
isVideoWaterMarkEnabled BOOL 是否打开水印支持.默认开启
isQosOn BOOL 是否打开qos功能.默认开启
isOutputRGB BOOL 是否输出RGB数据.默认不开启
isUseExternalCapture BOOL 是否使用外部视频采集,默认不开启
isUseHwBFrame BOOL 是否使用硬件编码B帧,只在开启硬件编码的情况下才使用,默认开启

音视频参数说明LSLiveStreamingParaCtxConfiguration

参数 类型 说明
eHaraWareEncType LSHardWareEncEnable 是否开启硬件编码类型,默认开启
eOutStreamType LSOutputStreamType 推流类型:音视频,视频,音频,默认为音视频
eOutFormatType LSOutputFormatType 推流协议:RTMP,FLV.默认为RTMP
sLSVideoParaCtx LSVideoParaCtxConfiguration 推流视频相关参数
sLSAudioParaCtx LSAudioParaCtxConfiguration 推流音频相关参数
uploadLog BOOL 是否上传sdk日志,默认开启
syncTimestamp BOOL 同步时间戳透传开关,默认关闭,推流类型必须包含视频,同时需要网易云播放器支持
streamTimestampPassthrough BOOL 网易云透传时间戳,但完全透传功能需要联系网易云开通
syncTimestampBaseline BOOL 同步时间戳基准:true为从0开始的基准,false为相对机器开机时间基准,默认为true
privateConfig BOOL 私有化配置开关,默认关闭

统计信息参数说明LSStatisticsObject

参数 类型 说明
videoSendFrameRate unsigned int 视频发送帧率
videoSendBitRate unsigned int 视频发送码率
videoSendWidth unsigned int 视频发送分辨率的宽
videoSendHeight unsigned int 视频发送分辨率的高
videoSetFrameRate unsigned int 设置的视频帧率
videoSetBitRate unsigned int 设置的视频码率
videoSetWidth unsigned int 设置的分辨率宽
videoSetHeight unsigned int 设置的分辨率高
audioSendBitRate unsigned int 音频的发送码率
videoEncodeTime unsigned int 视频编码一帧的时间
videoMuxAndSendTime unsigned int 视频发送一帧的时间
audioEncodeTime unsigned int 音频编码一帧的时间
audioMuxAndSendTime unsigned int 音频发送一帧的时间
writeFrameTime unsigned int 如果卡顿累积了数据,则上报卡顿的平均耗时;否则上报非卡顿的平均耗时
type LS_QOSLVL_TYPE 网络状况类型
videoSendBufferQueueCount unsigned int 视频发送缓存队列当前大小
audioSendBufferQueueCount unsigned int 音频发送缓存队列当前大小

自定义数据对象参数说明LSCustomDataObject

参数 类型 说明
sendConetnt NSString 发送内容:长度控制在1600,默认为空
sendInterval NSInteger 发送间隔:表示隔interval帧发一帧自定义数据,最大50,默认为0;如果为0,表示逐帧发送;如果是1,表示隔一帧发送一次;如果是5,表示隔5帧发送一次
sendTotalCites NSInteger 发送总次数:最大500,默认为10

枚举值参数介绍

水印位置LSWaterMarkLocation参数说明

参数 说明
LS_WATERMARK_LOCATION_RECT 由rect的origin定位置
LS_WATERMARK_LOCATION_LEFTUP 左上角
LS_WATERMARK_LOCATION_LEFTDOWN 左下角
LS_WATERMARK_LOCATION_RIGHTUP 右上角
LS_WATERMARK_LOCATION_RIGHTDOWN 右下角
LS_WATERMARK_LOCATION_CENTER 中间

滤镜类型LSGpuImageFilterType参数说明

参数 说明
LS_GPUIMAGE_NORMAL 无滤镜
LS_GPUIMAGE_SEPIA 黑白
LS_GPUIMAGE_ZIRAN 自然
LS_GPUIMAGE_MEIYAN1 粉嫩
LS_GPUIMAGE_MEIYAN2 怀旧

摄像头采集方向LSCameraOrientation参数说明

参数 说明
LS_CAMERA_ORIENTATION_PORTRAIT 画面正向垂直
LS_CAMERA_ORIENTATION_UPDOWN 画面倒向
LS_CAMERA_ORIENTATION_RIGHT 画面向右
LS_CAMERA_ORIENTATION_LEFT 画面向左

视频分辨率LSVideoStreamingQuality参数说明

参数 说明
LS_VIDEO_QUALITY_LOW 低清 352*288
LS_VIDEO_QUALITY_MEDIUM 标清 480*360
LS_VIDEO_QUALITY_HIGH 高清 640*480
LS_VIDEO_QUALITY_SUPER 超清 960*540
LS_VIDEO_QUALITY_SUPER_HIGH 超高清 (1280*720)

摄像头类型LSCameraPosition参数说明

参数 说明
LS_CAMERA_POSITION_BACK 后置摄像头
LS_CAMERA_POSITION_FRONT 前置摄像头

视频显示模式LSVideoRenderScaleMode参数说明

参数 说明
LS_VIDEO_RENDER_MODE_SCALE_NONE 采集多大分辨率,则显示多大分辨率
LS_VIDEO_RENDER_MODE_SCALE_16x9 无论采集多大分辨率,显示比例为16:9

硬件编码模式LSHardWareEncEnable参数说明

参数 说明
LS_HRD_NO 音视频都使用软件编码
LS_HRD_AUDIO 音频使用硬件编码,视频使用软件编码
LS_HRD_VIDEO 视频使用硬件编码,音频使用软件编码
LS_HRD_AV 音视频都使用硬件编码

推流协议LSOutputFormatType参数说明

参数 说明
LS_OUT_FMT_FLV flv协议
LS_OUT_FMT_RTMP rtmp协议

推流类型LSOutputStreamType参数说明

参数 说明
LS_HAVE_AUDIO 只推音频
LS_HAVE_VIDEO 只推视频
LS_HAVE_AV 音视频一起推

网络等级类型LS_QOSLVL_TYPE参数说明

参数 说明
LS_QOSLVL_HIGH 网络好
LS_QOSLVL_MIDDLE 网络一般
LS_QOSLVL_LOW 网络差

4 如何使用SDK API接口

4.1 创建推流实例

4.1.1 API介绍

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

4.1.2 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

4.1.3 参数说明

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

4.1.4 示例

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

4.1.5 特殊说明

由于相关硬件有可能读取失败的情况,导致无法正常使用推流SDK,所以有可能出现初始化失败的情况,因此需要检测是否初始化成功推流实例。

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

4.2 销毁推流实例

4.2.1 API介绍

4.2.2 API原型

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

4.2.3 参数说明

4.2.4 示例

[mediaCapture unInitLiveStream];
 mediaCapture = nil;

4.2.5 特殊说明

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

4.3 预览画面操作

4.3.1 API介绍

4.3.2 API原型

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

4.3.3 参数说明

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

4.3.4 示例

[_mediaCapture startVideoPreview:localPreview];

4.3.5 特殊说明

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

4.4 直播操作

4.4.1 API介绍

4.4.2 API原型

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

4.4.3 参数说明

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

4.4.4 示例

[_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.4.5 特殊说明

4.5 音视频推流操作

4.5.1 API介绍

4.5.2 API原型

/**
 *  重启开始视频推流
 *  @warning 需要先启动推流startLiveStreamWithError,开启音视频推流,才可以中断视频推流,重启视频推流,
 */
- (void)resumeVideoLiveStream;
/**
 *  中断视频推流
 *  @warning 需要先启动推流startLiveStreamWithError,开启音视频推流,才可以中断视频推流,重启视频推流,
 */
- (void)pauseVideoLiveStream;
/**
 *  中断音频推流,
 *  @warning:需要先启动推流startLiveStreamWithError,开启音视频推流,才可以中断音频推流,重启音频推流,
 */
- (BOOL)pauseAudioLiveStream;
/**
 *  重启音频推流,
 *  @warning:需要先启动推流startLiveStreamWithError,开启音视频推流,才可以中断音频推流,重启音频推流,
 */
- (BOOL)resumeAudioLiveStream;

4.5.3 参数说明

4.5.4 示例

- (void)videoBtnTapped:(UIButton *)sender {
    if (sender.isSelected) {
        [_mediaCapture pauseVideoLiveStream];
    }else {
        [_mediaCapture resumeVideoLiveStream];
    }
}
- (void)audioBtnTapped:(UIButton *)sender {
    if (sender.isSelected) {
        [_mediaCapture pauseAudioLiveStream];
    }else {
        [_mediaCapture resumeAudioLiveStream];
    }
}

4.5.5 特殊说明

这里的暂停音频流是发送静音帧

4.6 MP4录制操作

4.6.1 API介绍

4.6.2 API原型

/**
 开始录制并保存本地文件(mp4录制)

 @param recordFileName 本地录制的文件全路径
 @return 开启录制成功
 */
- (BOOL)startRecord:(NSString *)recordFileName;
/**
 *  停止本地录制
 */
- (BOOL)stopRecord;

4.6.3 参数说明

参数 类型 说明
recordFileName NSString 本地录制的文件全路径

4.6.4 示例

- (void)recordBtnTapped:(UIButton *)sender {
    if (sender.isSelected) {
        //以开始录制的时间作为时间戳,作为文件名后缀
        NSString *fileName = @"/vcloud_";
        NSDate *date = [NSDate date];
        NSTimeInterval sec = [date timeIntervalSinceNow];
        NSDate *currDate = [[NSDate alloc] initWithTimeIntervalSinceNow:sec];

        NSDateFormatter *df = [NSDateFormatter new];
        [df setDateFormat:@"yyyyMMddHHmmss"];
        NSString *dfStr = [df stringFromDate:currDate];
        fileName = [fileName stringByAppendingString:dfStr];
        fileName = [fileName stringByAppendingString:@".mp4"];

        //存储在Documents路径里
        NSArray *arr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsPath = arr[0];

        NSString *savePath = [documentsPath stringByAppendingString:fileName];

        BOOL isStrated = [_mediaCapture startRecord:savePath];
        if (isStrated) {
            _isRecording = YES;
        }
    }else {
        BOOL isStoped = [_mediaCapture stopRecord];
        if (isStoped) {
            _isRecording = NO;
        }
    }
}

4.6.5 特殊说明

4.7 混音相关操作

4.7.1 API介绍

4.7.2 API原型

/**
 *  开始播放混音文件
 *
 *  @param musicURL 音频文件地址/文件名
 *  @param enableLoop 当前音频文件是否单曲循环
 */
- (BOOL)startPlayMusic:(NSString*)musicURL withEnableSignleFileLooped:(BOOL)enableLoop;
/**
 *  结束播放混音文件,释放播放文件
 */
- (BOOL)stopPlayMusic;
/**
 *  继续播放混音文件
 */
- (BOOL)resumePlayMusic;
/**
 *  中断播放混音文件
 */
- (BOOL)pausePlayMusic;
/**
 *  设置混音强度
 *  @param value 混音强度范围【1-10】
 */
- (void)setMixIntensity:(int)value;

4.7.3 参数说明

参数 类型 说明
musicURL NSString 音频文件地址/文件名
enableLoop BOOL 前音频文件是否单曲循环
value int 混音强度范围【1-10】

4.7.4 示例

switch (item) {
                case 0://无伴音
                {
                    [_mediaCapture stopPlayMusic];//关闭音效
                }
                    break;
                case 1://伴音1
                {
                    NSString* musicFileURL = [[NSBundle mainBundle]pathForResource:@"lovest" ofType:@"mp3"];
                    if (musicFileURL == nil) {
                        NSLog(@"have not found music file");
                        return;
                    }
                    if (![_mediaCapture startPlayMusic:musicFileURL withEnableSignleFileLooped:YES]) {
                        NSLog(@"播放音乐文件失败");
                        return;
                    };

                    //从itunes music获取本地音乐作为伴音,该代码仅供参考,具体实现要考虑比较多细节
//                    [self convertMediaPickerController];
                }
                    break;
                case 2://伴音2
                {
                    NSString* musicFileURL = [[NSBundle mainBundle]pathForResource:@"lovest" ofType:@"wav"];
                    if (musicFileURL == nil) {
                        NSLog(@"have not found music file");
                        return;
                    }
                    if (![_mediaCapture startPlayMusic:musicFileURL withEnableSignleFileLooped:YES]) {
                        NSLog(@"播放音乐文件失败");
                        return;
                    };
                }
                    break;
                default:
                    [_mediaCapture stopPlayMusic];//关闭音效
                    break;
            }

4.7.5 特殊说明

4.8 音视频数据操作

4.8.1 API介绍

4.8.2 API原型

/**
 采集模块采集的视频数据回调,交由外部进行自定义前处理,处理完后通过externalInputSampleBuffer发送给sdk
 */
@property(nonatomic, copy) void (^externalCaptureSampleBufferCallback)(CMSampleBufferRef sampleBuffer);
/**
 将外部前处理之后的视频数据发送给sdk

 @param sampleBuffer 视频数据
 */
-(void)externalInputSampleBuffer:(CMSampleBufferRef)sampleBuffer;
/**
 *  麦克风采集到的原始裸数据的回调,交由外部进行自定义处理,同步处理
 *  param rawData 麦克风采集得到的裸数据,PCM格式
 */
@property (nonatomic,copy) void (^externalCaptureAudioRawData)(AudioBufferList *bufferList,NSInteger inNumberFrames);
/**
 用户可以通过这个接口,将第三方采集的音频数据送回来,数据的格式要保持不变,由视频云sdk推流出去

 @param bufferList 音频数据
 @param inNumberFrames frames数据
 */
-(void)externalInputAudioBufferList:(AudioBufferList *)bufferList inNumberFrames:(NSInteger)inNumberFrames;

4.8.3 参数说明

参数 类型 说明
sampleBuffer CMSampleBufferRef 视频帧
bufferList AudioBufferList * 音频帧
inNumberFrames NSInteger frames数据

4.8.4 示例

    _mediaCapture.externalCaptureSampleBufferCallback = ^(CMSampleBufferRef sampleBuffer)
    {
         //NSLog(@"做一些视频前处理操作");
         //然后塞给 推流sdk
        [weakSelf.mediaCapture externalInputSampleBuffer:sampleBuffer];
    };
    _mediaCapture.externalCaptureAudioRawData = ^(AudioBufferList *bufferList,NSInteger inNumberFrames) {
//        NSLog(@"做一些音频前处理操作");
        //同步操作
        if (!weakSelf.soundTouch) {
            weakSelf.soundTouch = [[NESoundTouch alloc] initWithSampleRate:streamparaCtx.sLSAudioParaCtx.samplerate pitchSemiTones:8];
        }
        [weakSelf.soundTouch processSound:bufferList->mBuffers[0].mData number:inNumberFrames];
    };

4.8.5 特殊说明

4.9 直播前测速操作

4.9.1 API介绍

4.9.2 API原型

/**
 开始测速
 */
-(void)startSpeedCalc:(NSString *)url success:(void(^)(NSMutableArray *array))success fail:(void(^)())fail;
/**
 结束测速
 */
-(void)stopSpeedCalc;
/**
 测速之前设置测速次数和上传数据大小

 @param count 测速次数(默认为1次),测速之后,取平均值返回结果
 @param capacity 上传数据大小(仅限于文件上传类型,经测试,NTS2不能超过500k(含500k)),单位是字节,500k=500*1024,默认为499k(控制最大不超过10M)
 */
-(void)setSpeedCacl:(NSInteger)count Capacity:(unsigned long long)capacity;

4.9.3 参数说明

参数 类型 说明
url NSString 测速地址
success void(^)(NSMutableArray *array) 测速成功返回的结果列表
fail void(^)() 测速失败错误回调
count NSInteger 测速次数(默认为1次),测速之后,取平均值返回结果
capacity unsigned long long 上传数据大小(仅限于文件上传类型,经测试,NTS2不能超过500k(含500k)),单位是字节,500k=500*1024,默认为499k(控制最大不超过10M)

4.9.4 示例

- (void)startSpeed:(id)sender
{
    //测速之前设置测速次数和上传数据大小500k(默认可以不设):接口android之后会统一
    [lsMedia setSpeedCacl:1 Capacity:499*1024];

    if ([self.urlText length] > 0 && [self.urlText hasPrefix:@"rtmp://"]) {
        [lsMedia startSpeedCalc:self.urlText success:^(NSMutableArray *array) {
            NSLog(@"\n success!!! \n");
            dispatch_async(dispatch_get_main_queue(), ^{
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"测速结果" message:[NSString  stringWithFormat:@"%@",array] delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
                [alert showAlertWithCompletionHandler:^(NSInteger i) {}];
            });
        } fail:^{
            NSLog(@"failed");
        }];
    }else{
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"推流地址不正确" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
        [alert showAlertWithCompletionHandler:^(NSInteger i) {
            if (i == 0) {
                NSLog(@"推流地址不正确");
            }
        }];
    }
}
- (void)stopSpeed:(id)sender
{
    [lsMedia stopSpeedCalc];
}

4.9.5 特殊说明

测速次数不建议超过3次,上传内容不宜过大,否则等待时间太久

4.10 摄像头操作

4.10.1 API介绍

4.10.2 API原型

/**
 *  flash摄像头
 *
 *  @return 打开或者关闭摄像头flash
 */
@property (nonatomic, assign)BOOL flash;
/**
 *  摄像头变焦功能属性:最大拉伸值,系统最大为:videoMaxZoomFactor
 *  @warning iphone4s以及之前的版本,videoMaxZoomFactor=1;不支持拉伸
 */
@property (nonatomic, assign, readonly) CGFloat maxZoomScale;
/**
 *  摄像头变焦功能属性:拉伸值,[1,maxZoomScale]
 *  @warning iphone4s以及之前的版本,videoMaxZoomFactor=1;不支持拉伸
 */
@property (nonatomic, assign) CGFloat zoomScale;
/**
 *  摄像头变焦功能属性:拉伸值变化回调block
 *
 *  摄像头响应uigesture事件,而改变了拉伸系数反馈
 *  @warning iphone4s以及之前的版本,videoMaxZoomFactor=1;不支持拉伸
 */
@property (nonatomic,copy) void (^onZoomScaleValueChanged)(CGFloat value);
/**
 *  切换前后摄像头
 *
 *  @return 当前摄像头的位置,前或者后
 */
- (LSCameraPosition)switchCamera:(LSSwitchModuleVideoCameraPositionBlock)cameraPostionBlock;
/**
 切换分辨率,支持直播过程中切换分辨率,切换分辨率,水印将自动清除,需要外部根据分辨率,再次设置水印大小

 @param videoResolution
 @param videoResolutionBlock
 */
- (void)switchVideoStreamingQuality:(LSVideoStreamingQuality)videoResolution block:(LSVideoStreamingQualityBlock)videoResolutionBlock;
/**
 直播推流之前设置如下参数

 @param bitrate 推流码率 default会按照分辨率设置
 @param fps 采集帧率 default = 15
 @param cameraOrientation 摄像头采集方向(一般不变)
 */
- (void)setBitrate:(int)bitrate
               fps:(int)fps
 cameraOrientation:(LSCameraOrientation) cameraOrientation;

4.10.3 参数说明

参数 类型 说明
flash BOOL 打开或者关闭摄像头flash
maxZoomScale CGFloat 摄像头变焦功能属性:最大拉伸值,系统最大为:videoMaxZoomFactor
zoomScale CGFloat 摄像头变焦功能属性:拉伸值,[1,maxZoomScale]
cameraPostionBlock LSSwitchModuleVideoCameraPositionBlock 当前摄像头的位置,前或者后
videoResolution LSVideoStreamingQuality 分辨率
videoResolutionBlock LSVideoStreamingQualityBlock 切换摄像头回调
bitrate int 推流码率
fps int 采集帧率
cameraOrientation LSCameraOrientation 摄像头采集方向(

4.10.4 示例

self.trackSliderView = [[NETrackingSliderView alloc] initWithView:paraCtx tag:^(SliderTag tag,CGFloat value) {
        if (tag == zoomTag) {
            _mediaCapture.zoomScale = value;
        }
    }];
 _isBackCameraPosition = [_mediaCapture switchCamera:^{
        NSLog(@"切换摄像头");
    }];
    [_mediaCapture switchVideoStreamingQuality:quality block:^(LSVideoStreamingQuality quality1) {
        [self addWaterMarkLayer:quality1];
        [self addDynamicWaterMark:quality1];
    }];

4.10.5 特殊说明

4.11 镜像相关操作

4.11.1 API介绍

4.11.2 API原型

/**
 切换本地预览镜像

 @return 当前是否镜像
 */
-(BOOL)changeIsFrontPreViewMirrored;
/**
 切换编码镜像(针对拉流端观众)

 @return 当前是否镜像
 */
-(BOOL)changeIsFrontCodeMirrored;

4.11.3 参数说明

4.11.4 示例

-(void)onActionPreviewMirror:(id)sender{
    [_mediaCapture changeIsFrontPreViewMirrored];
}
-(void)onActionCodeMirror:(id)sender{
    [_mediaCapture changeIsFrontCodeMirrored];
}

4.11.5 特殊说明

4.12 滤视频截图操作

4.12.1 API介绍

4.12.2 API原型

/**
 *  获取视频截图,
 *
 *  @param  LSFrameCaptureCompletionBlock 获取最新一幅视频图像的回调
 *
 */
- (void)snapShotWithCompletionBlock:(LSFrameCaptureCompletionBlock)completionBlock;

4.12.3 参数说明

参数 类型 说明
completionBlock LSFrameCaptureCompletionBlock 获取最新一幅视频图像的回调

4.12.4 示例

__weak MediaCaptureViewController *weakSelf = self;
[weakSelf.mediaCapture snapShotWithCompletionBlock:^(UIImage *latestFrameImage) {
    UIImageWriteToSavedPhotosAlbum(latestFrameImage, weakSelf, nil, nil);
}];

4.12.5 特殊说明

4.13 滤镜相关操作

4.13.1 API介绍

4.13.2 API原型

/**
 *  设置滤镜类型
 *
 *  @param filterType 滤镜类型,目前支持4种滤镜,参考 LSGpuImageFilterType 描述
 *
 */
- (void)setFilterType:(LSGpuImageFilterType)filterType;
/**
 设置磨皮强度【0-1】

 @param value 值
 */
- (void)setSmoothFilterIntensity:(float)value;
/**
 设置美白强度【0-1】

 @param value 值
 */
- (void)setWhiteningFilterIntensity:(float)value;
/**
 调节曝光度(-10.0 - 10.0 ,默认为0.0)

 @param exposure 曝光度
 */
-(void)adjustExposure:(CGFloat)exposure;

4.13.3 参数说明

参数 类型 说明
filterType LSGpuImageFilterType 滤镜类型
value float 磨皮强度【0-1】
value float 美白强度【0-1】
exposure CGFloat 曝光度(-10.0 - 10.0 ,默认为0.0)

4.13.4 示例

[_mediaCapture setFilterType:(LSGpuImageFilterType)type];
self.trackSliderView = [[NETrackingSliderView alloc] initWithView:paraCtx tag:^(SliderTag tag,CGFloat value) {
    if (tag == zoomTag) {
        _mediaCapture.zoomScale = value;
    }else if (tag == ContrastTag){
        [_mediaCapture setSmoothFilterIntensity:value];
    }else if (tag == WhiteTag){
        [_mediaCapture setWhiteningFilterIntensity:value];
    }else{
        [_mediaCapture adjustExposure:value];
    }
}];

4.13.5 特殊说明

4.14 水印相关操作

4.14.1 API介绍

4.14.2 API原型

/**
 添加涂鸦

 @param image 涂鸦静态图像
 @param rect 具体位置和大小(x,y根据location位置,计算具体的位置信息)
 @param location 位置
 */
- (void)addGraffiti:(UIImage*)image
               rect:(CGRect)rect
           location:(LSWaterMarkLocation)location;
/**
 添加静态视频水印

 @param image 静态图像
 @param rect 具体位置和大小(x,y根据location位置,计算具体的位置信息)
 @param location 位置
 */
- (void) addWaterMark: (UIImage*) image
                 rect: (CGRect) rect
             location: (LSWaterMarkLocation) location;
/**
 关闭本地预览静态水印
 */
- (void)closePreviewWaterMark:(BOOL)isClosed;
/**
 添加动态视频水印

 @param imageArray 动态图像数组
 @param count 播放速度的快慢:count代表count帧显示同一张图
 @param looped 是否循环,不循环就显示一次
 @param rect 具体位置和大小(x,y根据location位置,计算具体的位置信息)
 @param location 位置
 */
- (void) addDynamicWaterMarks: (NSArray*) imageArray
                     fpsCount: (unsigned int)count
                         loop: (BOOL)looped
                         rect: (CGRect) rect
                     location: (LSWaterMarkLocation) location;
/**
 关闭本地预览动态水印
 */
- (void)closePreviewDynamicWaterMark:(BOOL)isClosed;
/**
 清除水印
 */
- (void)cleanWaterMark;

4.14.3 参数说明

参数 类型 说明
image UIImage 图像
rect CGRect 具体位置和大小(x,y根据location位置,计算具体的位置信息)
location LSWaterMarkLocation 位置
isClosed BOOL 关闭水印
imageArray NSArray 动态图像数组
count unsigned int 放速度的快慢:count代表count帧显示同一张图
looped BOOL 是否循环,不循环就显示一次

4.14.4 示例

- (void)addWaterMarkLayer:(LSVideoStreamingQuality)quality {
    CGRect rect = CGRectZero;
    //自行根据产品定水印在不同分辨率下的大小
    switch (quality) {
        case LS_VIDEO_QUALITY_LOW:
            rect = CGRectMake(10, 10, 100*0.7*0.7*0.7, 54*0.7*0.7*0.7);
            break;
        case LS_VIDEO_QUALITY_MEDIUM:
            rect = CGRectMake(10, 10, 100*0.7*0.7, 54*0.7*0.7);
            break;
        case LS_VIDEO_QUALITY_HIGH:
            rect = CGRectMake(10, 10, 100*0.7, 54*0.7);
            break;
        case LS_VIDEO_QUALITY_SUPER:
            rect = CGRectMake(10, 10, 100, 54);
            break;
        default:
            rect = CGRectMake(10, 10, 100, 54);
            break;
    }
    //添加静态水印
    UIImage* image = [UIImage imageNamed:[[[NSBundle mainBundle] bundlePath]stringByAppendingPathComponent:@"logo.png"]];
    [_mediaCapture addWaterMark:image rect:rect location:LS_WATERMARK_LOCATION_RIGHTUP];
}
- (void)addDynamicWaterMark:(LSVideoStreamingQuality)quality {
    CGRect rect = CGRectZero;
    //自行根据产品定水印在不同分辨率下的大小
    switch (quality) {
        case LS_VIDEO_QUALITY_LOW:
            rect = CGRectMake(10, 10, 220*0.7*0.7*0.7, 80*0.7*0.7*0.7);
            break;
        case LS_VIDEO_QUALITY_MEDIUM:
            rect = CGRectMake(10, 10, 220*0.7*0.7, 80*0.7*0.7);
            break;
        case LS_VIDEO_QUALITY_HIGH:
            rect = CGRectMake(10, 10, 220*0.7, 80*0.7);
            break;
        case LS_VIDEO_QUALITY_SUPER:
            rect = CGRectMake(10, 10, 220, 80);
            break;
        default:
            rect = CGRectMake(10, 10, 220, 80);
            break;
    }

    //屏蔽动态水印oppo广告
    NSMutableArray *array = [NSMutableArray array];
    for (NSInteger i = 0; i < 23; i++) {
        NSString *str = [NSString stringWithFormat:@"water%@.png",[NSString stringWithFormat:@"%ld",(long)i]];
        UIImage* image = [UIImage imageNamed:[[[NSBundle mainBundle] bundlePath]stringByAppendingPathComponent:str]];
        [array addObject:image];
    }

    //图片数量少时,建议2帧一次显示,图片多时,建议1帧一次显示
    [_mediaCapture addDynamicWaterMarks:array
                               fpsCount:2
                                   loop:YES
                                   rect:rect
                               location:LS_WATERMARK_LOCATION_RIGHTDOWN];

}
switch (item) {
                case 0://无水印
                    paraCtx.isVideoWaterMarkEnabled = NO;
                    [_mediaCapture cleanWaterMark];
                    break;
                case 1://静态水印
                {
                    paraCtx.isVideoWaterMarkEnabled = YES;
                    [_mediaCapture cleanWaterMark];
                    [self addWaterMarkLayer:paraCtx.videoStreamingQuality];
                }
                    break;
                case 2:
                {
                    paraCtx.isVideoWaterMarkEnabled = YES;
                    [_mediaCapture cleanWaterMark];
                    [self addDynamicWaterMark:paraCtx.videoStreamingQuality];
                }
                    break;
                default:
                    break;
            }

4.14.5 特殊说明

4.15 直播辅助操作

4.15.1 API介绍

4.15.2 API原型

/**
 *  直播过程中发生错误的回调函数
 *
 *  @param error 具体错误信息
 */
@property (nonatomic,copy) void (^onLiveStreamError)(NSError *error);
/**
 *  得到直播过程中的统计信息
 *
 *  @param statistics 统计信息结构体
 *
 */
@property (nonatomic,copy) void (^onStatisticInfoGot)(LSStatisticsObject* statistics);
/**
 更新自定义统计数据

 @param customDict 自定义统计数据(key,value)
 */
- (void)updateCutomStatistics:(NSDictionary *)customDict;
/**
 检查是否正在直播

 @return bool值
 */
- (BOOL)checkIsLiving;
/**
 *  设置trace 的level
 *
 *  @param loglevl trace 信息的级别
 */
- (void)setTraceLevel:(LSMediaLog)logLevel;
/**
 *  获取当前sdk的版本号
 *
 */
+ (NSString*) getSDKVersionID;

4.15.3 参数说明

参数 类型 说明
customDict NSDictionary 自定义统计数据(key,value)
logLevel LSMediaLog 信息的级别

4.15.4 示例

_mediaCapture.onLiveStreamError = ^(NSError* error){
                if (error != nil) {
                    [weakSelf LiveStreamErrorInterrup];
                }
                [weakSelf.selectView.startBtn setBackgroundImage:[UIImage imageNamed:@"restart"] forState:UIControlStateNormal];
            };
_mediaCapture.onStatisticInfoGot = ^(LSStatisticsObject* statistics){
                if (statistics != nil) {
                    dispatch_async(dispatch_get_main_queue(),^(void){[weakSelf showStatInfo:statistics];});
                }
            };
[LSMediaCapture getSDKVersionID];
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict setObject:@"1111" forKey:@"uid"];
    [dict setObject:@"2222" forKey:@"appKey"];
    [_mediaCapture updateCutomStatistics:dict];

4.15.5 特殊说明

5 代码示例

    - (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;
    }
    LSVideoParaCtxConfiguration *paraCtx = [LSVideoParaCtxConfiguration defaultVideoConfiguration:LSVideoParamQuality_Super];//直播推流参数

    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.isFrontCameraMirroredPreView               = YES; //是否镜像前置摄像头预览
    paraCtx.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];
    [[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 ];//直播出错可以将出错信息直接显示给用户,也可以封装成统一格式,告诉用户检查网络等情况,尝试重新开启直播
        }
    }];
    -(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);
            }];
        });
    }
    -(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()
       }
    }];

6 Demo接入Faceunity

7 API说明

有关API的详细说明,可参见SDK包中docs,打开index.html查看,或者打开下面的在线文档。

网易云视频直播推流LiveStreaming iOS SDK API详细文档