本文详细说明iOS端推流SDK API、SDK的基本使用流程,以及相关功能的使用示例。

说明 如果您需要使用移动端进行推流,详细操作请参见推流、拉流与播流

iOS推流SDK特性

  • 支持RTMP推流协议。
  • 使用视频H.264编码以及音频AAC编码。
  • 支持码控、分辨率、显示模式等自定义配置。
  • 支持多种摄像头相关操作。
  • 支持实时美颜和自定义美颜效果调节。
  • 支持增、删动态贴纸实现动态水印效果。
  • 支持录屏直播。
  • 支持自定义YUV、PCM等外部音视频输入。
  • 支持多路混流功能。
  • 支持纯音视频推流以及后台推流。
  • 支持背景音乐及其相关操作。
  • 支持视频截图功能。
  • 支持自动重连、异常处理。
  • 支持音频3A算法。
  • 增加视频软编、硬编切换逻辑,提升编码模块稳定性。

功能限制

使用iOS推流SDK需注意以下限制:
  • 您只能在推流之前设置横竖屏模式,不支持在直播的过程中实时切换。
  • 在推流设定为横屏模式时,需设定界面为不允许自动旋转。
  • 在硬编模式下,考虑编码器兼容问题分辨率会使用16的倍数,如设定为540P,则输出的分辨率为544*960,在设置播放器视图大小时需按输出分辨率等比缩放,避免黑边等问题。

推流SDK使用流程

SDK的基本使用流程如下:

步骤 描述 操作指引及代码示例
一、注册SDK

配置License相关参数,注册推流SDK。若不调用注册函数,推流功能无法使用。

注册SDK
二、配置推流参数

完成推流基本配置、码率控制配置、分辨率自适应配置、美颜功能配置等。

配置推流参数
三、使用推流SDK推流

初始化SDK、注册推流回调、创建预览视图后可以开始推流。用户可以根据业务需求添加推流控制、设置背景音乐、摄像头、直播答题、外部音频、动态贴纸等。

说明

阿里云视频直播不允许同一时间向同一个推流URL进行多路推流(第二路推流会被拒绝)。

使用推流SDK推流
四、设置录屏推流(按需)

如需使用录屏推流,可以实现录屏推流相关的配置。

设置录屏推流

注册SDK

说明 注册SDK前,需要先完成License配置操作,请参见配置License

推流SDK升级到4.4.2及以后版本,接入一体化License服务。在使用推流功能前必须进行注册,否则无法使用推流SDK功能。

请在开始的位置调用注册License接口:
[AlivcLiveBase registerSDK];

通过AlivcLiveBase类,可以设置日志级别、设置本地日志路径、获取SDK版本等,接入方需要监控License回调AlivcLiveBaseObserver中的onLicenceCheck方法,确定提供的LicenseKey和LicenseFile是否校验通过。

配置推流参数

您可以使用AlivcLivePushConfig配置推流参数,每个参数有一个对应的默认值。关于默认值和参数范围,请参见V4.4.3接口说明(iOS)或注释。

说明 如需在推流过程中实时修改参数,请参见AlivcLivePusher提供的属性和方法。
  1. 基本推流配置。

    在需要使用推流器的ViewController中引用头文件#import <AlivcLivePusher/AlivcLivePusher.h>,示例代码如下:

    AlivcLivePushConfig *config = [[AlivcLivePushConfig alloc] init];//初始化推流配置类,也可使用initWithResolution来初始化。
    config.resolution = AlivcLivePushResolution540P;//默认为540P,最大支持720P
    config.fps = AlivcLivePushFPS20; //建议用户使用20fps
    config.enableAutoBitrate = true; // 打开码率自适应,默认为true
    config.videoEncodeGop = AlivcLivePushVideoEncodeGOP_2;//默认值为2,关键帧间隔越大,延时越高。建议设置为1-2。
    config.connectRetryInterval = 2000; // 单位为毫秒,重连时长2s,重连间隔设置不小于1秒,建议使用默认值即可。
    config.previewMirror = false; // 默认为false,正常情况下都选择false即可。
    config.orientation = AlivcLivePushOrientationPortrait; // 默认为竖屏,可设置home键向左或向右横屏。
    说明
    • 综合手机性能和网络带宽要求,建议您将分辨率设置为540P(主流移动直播App基本都采用540P)。
    • 基本推流配置对应参数都有默认值,建议采用默认值,即您可以进行简单初始化,不做配置。
    • 关闭自适应码率后,码率将固定在初始码率,不会在设定的目标码率和最小码率之间自适应调整。如果网络情况不稳定,可能造成播放卡顿,请慎用。
  2. 配置码率控制。

    推流SDK提供以下码率控制模式,请根据实际需求修改参数值。

    码率控制模式 描述 示例代码
    AlivcLivePushQualityModeResolutionFirst 清晰度优先模式。SDK内部会对码率参数进行配置,优先保障推流视频的清晰度。
    config.qualityMode = AlivcLivePushQualityModeResolutionFirst;//默认为清晰度优先模式,可设置为流畅度优先模式和自定义模式。
    AlivcLivePushQualityModeFluencyFirst 流畅度优先模式。SDK内部会对码率参数进行配置,优先保障推流视频的流畅度。
    config.qualityMode = AlivcLivePushQualityModeFluencyFirst;//默认为流畅度优先模式,可设置为清晰度优先模式和自定义模式。
    AlivcLivePushQualityModeCustom 自定义模式。SDK会根据开发者设置的码率进行配置。设置为自定义模式时,需要自己定义初始码率、最小码率和目标码率。
    • 初始码率:开始直播时的码率。
    • 最小码率:当网络较差时,码率会逐步减低到最小码率,以减少视频的卡顿。
    • 目标码率:当网络较好时,码率会逐步提高到目标码率,以提高视频清晰度。
    config.qualityMode = AlivcLivePushQualityModeCustom//设置为自定义模式
    config.targetVideoBitrate = 1400; //目标码率1400kbps
    config.minVideoBitrate = 600; //最小码率600kbps
    config.initialVideoBitrate = 1000; //初始码率1000kbps
    说明
    • 选择清晰度优先或流畅度优先模式时,不需设置初始码率、最小码率和目标码率(initialVideoBitrate、minVideoBitrate、targetVideoBitrate)。推流SDK内部策略会自动保障在网络抖动情况下优先考虑视频清晰度或流畅度。
    • 选择自定义码率时,请参考阿里云推荐设置配置对应码率。推荐设置请参考下表内容。
    表 1. 自定义码率控制推荐设置(画质优先)
    分辨率 初始码率 initialVideoBitrate 最小码率 minVideoBitrate 目标码率 targetVideoBitrate
    360P 600 300 1000
    480P 800 300 1200
    540P 1000 600 1400
    720P 1500 600 2000
    1080P 1800 1200 2500
    表 2. 自定义码率控制推荐设置(流畅度优先)
    分辨率 初始码率 initialVideoBitrate 最小码率 minVideoBitrate 目标码率 targetVideoBitrate
    360P 400 200 600
    480P 600 300 800
    540P 800 300 1000
    720P 1000 300 1200
    1080P 1500 1200 2200
  3. 配置分辨率自适应。

    开启动态调整推流分辨率功能后,当网络较差时会自动降低分辨率以提高视频的流畅度和清晰度。示例代码如下:

    config.enableAutoResolution = YES; // 打开分辨率自适应,默认为NO
    注意
    • 某些播放器可能不支持动态分辨率,如果您需要使用分辨率自适应功能,建议使用阿里云播放器。
    • 分辨率自适应只有在清晰度优先或流畅度优先时才会生效(AlivcQualityModeEnum参数配置),自定义模式时无效。
  4. 配置美颜功能。

    阿里云推流SDK提供两种美颜模式:基础美颜和高级美颜。基础美颜支持美白、磨皮和红润。高级美颜支持基于面部识别的美白、磨皮、红润、大眼、小脸、瘦脸等功能。此功能由简介提供,使用示例代码如下:

    #pragma mark - "美颜类型和美颜参数API"/**
     * @brief 打开或者关闭某个美颜类型
     * @param type QueenBeautyType 类型的一个值
     * @param isOpen YES: 打开,NO:关闭
     *
     */
    - (void)setQueenBeautyType:(kQueenBeautyType)type enable:(BOOL)isOpen;
    /**
     * @brief 设置美颜参数
     * @param param 美颜参数类型,QueenBeautyParams中的一个
     * @param value 需要设置的数值,值的范围都是[0,1],小于0的置0,大于1的置1
     */
    - (void)setQueenBeautyParams:(kQueenBeautyParams)param
    value:(float)value;
    #pragma mark - "滤镜相关API"
    /**
     * @brief 设置滤镜图片,设置滤镜图片前需要将kQueenBeautyTypeLUT打开
     * @param imagePath 所要设置的滤镜图片的地址
     */
    - (void)setLutImagePath:(NSString *)imagePath;
    #pragma mark - "美型相关API"
    /**
     * @brief 设置美型类型,设置前需要将kQueenBeautyTypeFaceShape打开
     * @param faceShapeType 需要设置美型的类型,参考QueenBeautyFaceShapeType
     * @param value 需要设置的值
     */
    - (void)setFaceShape:(kQueenBeautyFaceShapeType)faceShapeType
    value:(float)value;
    #pragma mark - "美妆相关api"
    /**
     * @brief 设置美妆类型和图片素材路径,设置美妆需要将kQueenBeautyTypeMakeup打开
     * @param makeupType 美妆类型
     * @param imagePaths 美妆素材地址集合
     * @param blend 混合类型
     */
    - (void)setMakeupWithType:(kQueenBeautyMakeupType)makeupType
    paths:(NSArray<NSString *> *)imagePaths
    blendType:(kQueenBeautyBlend)blend;
    /**
     * @brief 设置美妆类型和图片素材路径
     * @param makeupType 美妆类型
     * @param imagePaths 美妆素材地址集合
     * @param blend 混合类型
     * @param fps 对应的帧率
     */
    - (void)setMakeupWithType:(kQueenBeautyMakeupType)makeupType
    paths:(NSArray<NSString *> *)imagePaths
    blendType:(kQueenBeautyBlend)blend fps:(int)fps;
    /**
     * @brief 设置美妆透明度,可指定性别
     * @param makeupType 美妆类型
     * @param isFeMale 是否是女性,女性:YES,男性:NO
     * @param alpha 妆容透明度
     */
    - (void)setMakeupAlphaWithType:(kQueenBeautyMakeupType)makeupType
    female:(BOOL)isFeMale alpha:(float)alpha;
    /**
     * @brief 设置美妆类型的混合类型
     * @param makeupType 美妆类型
     * @param blend 混合类型
     */
    - (void)setMakeupBlendWithType:(kQueenBeautyMakeupType)makeupType
    blendType:(kQueenBeautyBlend)blend;
    /**
     * @brief 清除所有美妆
     */
    - (void)resetAllMakeupType;
  5. 配置图片推流。

    为了更好的用户体验,SDK提供了后台图片推流和码率过低时进行图片推流的设置。当SDK退至后台时默认暂停推流视频,只推流音频,此时可以设置图片来进行图片推流和音频推流。例如,在图片上提醒用户主播离开片刻,稍后回来。示例代码如下:

    config.pauseImg = [UIImage imageNamed:@"图片.png"];//设置用户后台推流的图片

    另外,当网络较差时您可以根据自己的需求设置推流一张静态图片。设置图片后,SDK检测到当前码率较低时,会推流此图片,避免视频流卡顿。示例代码如下:

    config.networkPoorImg = [UIImage imageNamed:@"图片.png"];//设置网络较差时推流
  6. 配置水印。
    推流SDK提供了添加水印功能,并且最多支持添加多个水印,水印图片必须为PNG格式图片。示例代码如下:
    NSString *watermarkBundlePath = [[NSBundle mainBundle] pathForResource:
    [NSString stringWithFormat:@"watermark"] ofType:@"png"];//设置水印图片路径
    [config addWatermarkWithPath: watermarkBundlePath
          watermarkCoordX:0.1
          watermarkCoordY:0.1
          watermarkWidth:0.3];//添加水印
    说明
    • coordX、coordY、width为相对值,例如watermarkCoordX:0.1表示水印的x值为推流画面x轴的10%位置,如果推流分辨率为540*960,则水印x值为54。
    • 水印图片的高度,按照水印图片的真实宽高与输入的width值等比缩放。
    • 要实现文字水印,可以先将文字转换为图片,再使用此接口添加水印。
    • 为了保障水印显示的清晰度与边缘平滑,请您尽量使用和水印输出尺寸相同大小的水印源图片。如输出视频分辨率544*940,水印显示的w是0.1f,则尽量使用水印源图片宽度在544*0.1f=54.4左右。
  7. 配置预览显示模式。
    推流SDK支持三种预览模式,预览显示模式不影响推流。
    • ALIVC_LIVE_PUSHER_PREVIEW_SCALE_FILL :预览显示时,铺满窗口。当视频比例和窗口比例不一致时,预览会有变形。
    • ALIVC_LIVE_PUSHER_PREVIEW_ASPECT_FIT:预览显示时,保持视频比例。当视频比例与窗口比例不一致时,预览会有黑边。(默认)
    • ALIVC_LIVE_PUSHER_PREVIEW_ASPECT_FILL:预览显示时,剪切视频以适配窗口比例。当视频比例和窗口比例不一致时,预览会裁剪视频。

    示例代码如下:

    mAlivcLivePushConfig.setPreviewDisplayMode(AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_ASPECT_FIT);
    说明
    • 三种模式可以在AlivcLivePushConfig中设置,也可以在预览中和推流中通过API setpreviewDisplayMode进行动态设置。
    • 本设置只对预览显示生效,实际推出的视频流的分辨率和AlivcLivePushConfig中预设置的分辨率一致,并不会因为更改预览显示模式而变化。预览显示模式是为了适配不同尺寸的手机,您可以自由选择预览效果。

使用推流SDK推流

AlivcLivePusher为推流SDK的核心类,提供摄像头预览、推流回调、推流控制、推流过程中的参数调节等功能。通过下文操作步骤,您可以了解如何使用推流核心接口。

  1. 初始化。

    在配置好推流参数后,可以使用推流SDK的initWithConfig方法进行初始化。示例代码如下:

    self.livePusher = [[AlivcLivePusher alloc] initWithConfig:config];
    说明 AlivcLivePusher目前不支持多实例,所以一个init必须对应有一个destory。
  2. 注册推流回调。
    推流回调分为三种:
    • Info:主要做提示和状态检测使用。
    • Error:错误回调。
    • Network:主要为网络相关。
    注册delegate可接收对应的回调。示例代码如下:
    [self.livePusher setInfoDelegate:self];
    [self.livePusher setErrorDelegate:self];
    [self.livePusher setNetworkDelegate:self];
  3. 开始预览。

    livePusher对象初始化完成之后,可以进行开始预览操作。预览时需要传入摄像头预览的显示view(继承自UIView)。示例代码如下:

    [self.livePusher startPreview:self.view];
  4. 开始推流。

    预览成功后才可以开始推流,因此需监听AlivcLivePusherInfoDelegate的onPreviewStarted回调,在回调里面添加如下代码。

    [self.livePusher startPushWithURL:@"推流测试地址(rtmp://......)"];
    说明
    • 推流SDK同时提供了异步方法,可调用startPushWithURLAsync来实现。
    • 推流SDK支持RTMP的推流地址,阿里云推流地址获取请参见推流地址和播放地址
    • 使用正确的推流地址开始推流后,可用播放器(阿里云播放器、FFplay、VLC等)进行拉流测试,拉流地址获取请参见推流地址和播放地址
  5. 设置其他推流控制。

    推流控制主要包括开始推流、停止推流、停止预览、重新推流、暂停推流、恢复推流、销毁推流等操作,用户可以根据业务需求添加按钮进行操作。示例代码如下:

    /*正在推流状态下可调用暂停推流。暂停推流后,视频预览和视频推流保留在最后一帧,音频推流继续。*/
    [self.livePusher pause];
    /*暂停状态下可调用恢复推流。恢复推流后,音视频预览与推流恢复正常。*/
    [self.livePusher resume];
    /*推流状态下可调用停止推流,完成后推流停止。*/
    [self.livePusher stopPush];
    /*在预览状态下才可以调用停止预览,正在推流状态下,调用停止预览无效。预览停止后,预览画面定格在最后一帧。*/
    [self.livePusher stopPreview];
    /*推流状态下或者接收到所有Error相关回调状态下可调用重新推流,且Error状态下只可以调用此接口(或者reconnectPushAsync重连)或者调用destory销毁推流。完成后重新开始推流,重启ALivcLivePusher内部的一切资源,包括预览、推流等等restart。*/
    [self.livePusher restartPush];
    /*推流状态下或者接收到AlivcLivePusherNetworkDelegate相关的Error回调状态下可调用此接口, 且Error状态下只可以调用此接口(或者restartPush重新推流)或者调用destory销毁推流。完成后推流重连,重新链接推流RTMP。*/
    [self.livePusher reconnectPushAsync];
    /*销毁推流后,推流停止,预览停止,预览画面移除。AlivcLivePusher相关的一切资源销毁。*/
    [self.livePusher destory];
    self.livePusher = nil;
    /*获取推流状态。*/
    AlivcLivePushStatus status = [self.livePusher getLiveStatus];
  6. 美颜实时调整。

    推流SDK支持在推流时实时调整美颜参数,开启美颜开关,分别调整对应的参数值,此功能由智能美化特效提供,示例代码如下:

    [_queenEngine setQueenBeautyType:kQueenBeautyTypeSkinBuffing enable:YES];
    [_queenEngine setQueenBeautyType:kQueenBeautyTypeSkinWhiting enable:YES];
    [_queenEngine setQueenBeautyParams:kQueenBeautyParamsWhitening value:0.8f];
    [_queenEngine setQueenBeautyParams:kQueenBeautyParamsSharpen value:0.6f];
    [_queenEngine setQueenBeautyParams:kQueenBeautyParamsSkinBuffing value:0.6];
  7. 设置背景音乐。

    推流SDK提供了背景音乐播放、混音、降噪、耳返、静音等功能,背景音乐相关接口在开始预览之后才可调用。示例代码如下:

    /*开始播放背景音乐。*/
    [self.livePusher startBGMWithMusicPathAsync:musicPath];
    /*停止播放背景音乐。若当前正在播放BGM,并且需要切换歌曲,只需要调用开始播放背景音乐接口即可,无需停止当前正在播放的背景音乐。*/
    [self.livePusher stopBGMAsync];
    /*暂停播放背景音乐,背景音乐开始播放后才可调用此接口。*/
    [self.livePusher pauseBGM];
    /*恢复播放背景音乐,背景音乐暂停状态下才可调用此接口。*/
    [self.livePusher resumeBGM];
    /*开启循环播放音乐*/
    [self.livePusher setBGMLoop:true];
    /*设置降噪开关。打开降噪后,将对采集到的声音中非人声的部分进行过滤处理。可能存在对人声稍微抑制作用,建议让用户自由选择是否开启降噪功能,默认不使用*/
    [self.livePusher setAudioDenoise:true];
    /*设置耳返开关。耳返功能主要应用于KTV场景。打开耳返后,插入耳机将在耳机中听到主播说话声音。关闭后,插入耳机无法听到人声。未插入耳机的情况下,耳返不起作用。*/
    [self.livePusher setBGMEarsBack:true];
    /*混音设置,提供背景音乐和人声采集音量调整。*/
    [self.livePusher setBGMVolume:50];//设置背景音乐音量
    [self.livePusher setCaptureVolume:50];//设置人声采集音量
    /*设置静音。静音后音乐声音和人声输入都会静音。要单独设置音乐或人声静音可以通过混音音量设置接口来调整。*/
    [self.livePusher setMute:isMute?true:false];
  8. 摄像头相关操作。

    您只能在开始预览之后调用摄像头相关操作,包括推流状态、暂停状态、重连状态等,可操作摄像头切换、闪关灯、焦距、变焦和镜像设置等。未开始预览状态下调用如下接口无效。示例代码如下:

    /*切换前后摄像头*/
    [self.livePusher switchCamera];
    /*开启/关闭闪光灯,在前置摄像头时开启闪关灯无效*/
    [self.livePusher setFlash:false]; 
    /*焦距调整,即可实现采集画面的缩放功能。传入参数为正数,则放大焦距,传入参数为负数则缩小焦距。*/
    CGFloat max = [_livePusher getMaxZoom];
    [self.livePusher setZoom:MIN(1.0, max)]; 
    /*手动对焦。手动聚焦需要传入两个参数:1.point 对焦的点(需要对焦的点的坐标);2.autoFocus 是否需要自动对焦,该参数仅对调用接口的该次对焦操作生效。后续是否自动对  焦沿用上述自动聚焦接口设置值。*/
    [self.livePusher focusCameraAtAdjustedPoint:CGPointMake(50, 50) autoFocus:true];
    /*设置是否自动对焦*/
    [self.livePusher setAutoFocus:false];
    /*镜像设置。镜像相关接口有两个,PushMirror推流镜像和PreviewMirror预览镜像。PushMirror设置仅对播放画面生效,PreviewMirror仅对预览画面生效,两者互不影响。*/
    [self.livePusher setPushMirror:false];
    [self.livePusher setPreviewMirror:false];
  9. 配置直播答题功能。

    直播答题功能可以通过在直播流里面插入SEI信息,播放器解析SEI来实现。在推流SDK里面提供了插入SEI的接口,在推流状态下,才能调用此接口。示例代码如下:

    /*
    msg: 需要插入流的SEI消息体,建议是JSON格式。阿里云播放器SDK可收到此SEI消息,解析后做具体展示。
    repeatCount:发送的帧数。为了保证SEI不被丢帧,需设置重复次数,如设置100,则在接下去的100帧均插入此SEI消息。播放器会对相同的SEI进行去重处理。
    delayTime:延时多少毫秒发送。
    KeyFrameOnly:是否只发关键帧。
    */
    [self.livePusher sendMessage:@"题目信息" repeatCount:100 delayTime:0 KeyFrameOnly:false];
  10. 配置外部音视频输入。

    推流SDK支持将外部的音视频源输入进行推流,比如推送一个音视频文件。

    1. 在推流配置里面进行外部音视频输入配置。
      示例代码如下:
      config.externMainStream = true;//开启允许外部流输入
      config.externVideoFormat = AlivcLivePushVideoFormatYUVNV21;//设置视频数据颜色格式定义,这里设置为YUVNV21,可根据需求设置为其他格式。
      config.externMainStream = AlivcLivePushAudioFormatS16;//设置音频数据位深度格式,这里设置为S16,可根据需求设置为其他格式
    2. 插入外部视频数据。
      示例代码如下:
      /*只支持外部视频yuv和rbg格式的连续buffer数据,才可以通过sendVideoData接口,发送视频数据buffer、长度、宽高、时间戳、旋转角度*/
      [self.livePusher sendVideoData:yuvData width:720 height:1280 size:dataSize pts:nowTime rotation:0];
      /*如果外部视频数据是CMSampleBufferRef格式,可以使用sendVideoSampleBuffer接口*/
      [self.livePusher sendVideoSampleBuffer:sampleBuffer]
      /*也可以将 CMSampleBufferRef格式转化为连续buffer后再传递给sendVideoData接口, 以下为转换的参考代码*/
      //获取samplebuffer长度
      - (int) getVideoSampleBufferSize:(CMSampleBufferRef)sampleBuffer {
      if(!sampleBuffer) {
          return 0;
      }
      int size = 0;
      CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
      CVPixelBufferLockBaseAddress(pixelBuffer, 0);
      if(CVPixelBufferIsPlanar(pixelBuffer)) {
         int count = (int)CVPixelBufferGetPlaneCount(pixelBuffer);
         for(int i=0; i<count; i++) {
             int height = (int)CVPixelBufferGetHeightOfPlane(pixelBuffer,i);
             int stride = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer,i);
             size += stride*height;
         }
      }else {
         int height = (int)CVPixelBufferGetHeight(pixelBuffer);
         int stride = (int)CVPixelBufferGetBytesPerRow(pixelBuffer);
         size += stride*height;
      }
      CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
      return size;
      }
      //将samplebuffer转化为连续buffer
      - (int) convertVideoSampleBuffer:(CMSampleBufferRef)sampleBuffer toNativeBuffer:(void*)nativeBuffer
      {
      if(!sampleBuffer || !nativeBuffer) {
         return -1;
      }
      CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
      CVPixelBufferLockBaseAddress(pixelBuffer, 0);
      int size = 0;
      if(CVPixelBufferIsPlanar(pixelBuffer)) {
         int count = (int)CVPixelBufferGetPlaneCount(pixelBuffer);
         for(int i=0; i<count; i++) {
             int height = (int)CVPixelBufferGetHeightOfPlane(pixelBuffer,i);
             int stride = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer,i);
             void *buffer = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, i);
             int8_t *dstPos = (int8_t*)nativeBuffer + size;
             memcpy(dstPos, buffer, stride*height);
             size += stride*height;
         }
      }else {
         int height = (int)CVPixelBufferGetHeight(pixelBuffer);
         int stride = (int)CVPixelBufferGetBytesPerRow(pixelBuffer);
         void *buffer = CVPixelBufferGetBaseAddress(pixelBuffer);
         size += stride*height;
         memcpy(nativeBuffer, buffer, size);
      }
      CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
      return 0;
      }
    3. 插入音频数据。
      示例代码如下:
      /*只支持外部pcm格式的连续buffer数据,sendPCMData,发送音频数据buffer、长度、时间戳*/
      [self.livePusher sendPCMData:pcmData size:size pts:nowTime];
  11. 动态贴纸。

    推流SDK实现了在直播流中添加动态贴纸效果,使用此功能可实现动态水印效果。

    1. 动态贴纸的制作可参考Demo提供的素材进行简单修改。自己制作动图贴纸的序列帧图片,并打开config.json文件自定义以下参数:
      "du": 2.04,//播放一遍动画持续的时间
      "n": "qizi",//动图的名称,制作动图时文件夹以动图名称命名,每一张图片以动图名称+序号命名,比如qizi0
      "c": 68.0,//动画帧数,即一个完整动画的图片数量
      "kerneframe": 51,//关键帧,即指定哪一张图片为关键帧,比如demo中指定第51帧为关键帧(需确保51帧是存在的)
      "frameArry": [
          {"time":0,"pic":0},
          {"time":0.03,"pic":1},
          {"time":0.06,"pic":2},
          ],
      //动画参数,上述参数即表示第0秒显示第一帧(qizi0),第0.03秒显示第二帧(qizi1)...以此规则填写所有帧的动画
      说明 其他字段可以直接使用demo提供的config.json文件中的内容,无需修改。
    2. 添加动态贴纸。
      示例代码如下:
      /**
      * 添加动态贴纸
      * @param path 贴纸文件路径,必须含config.json
      * @param x 显示起始x位置(0~1.0f)
      * @param y 显示起始y位置(0~1.0f)
      * @param w 显示宽度(0~1.0f)
      * @param h 显示高度(0~1.0f)
      * @return id 贴纸id,删除贴纸时需设置id
      */
      [self.livePusher addDynamicWaterMarkImageDataWithPath: "贴纸路径" x:0.2f y:0.2f w:0.2f h:0.2f];
    3. 删除动态贴纸。
      示例代码如下:
      [self.livePusher removeDynamicWaterMark:id];
  12. 调试工具。

    SDK提供UI调试工具DebugView。DebugView为可移动的全局悬浮窗,添加后始终悬浮在视图的最上层。内含推流日志查看、推流性能参数实时检测、推流主要性能折线图表等debug功能。

    说明 在您的release版本下,请勿调用添加DebugView的接口。
    示例代码如下:
    [AlivcLivePusher showDebugView];//打开调试工具
  13. 其他接口的使用。
    /*在自定义模式下,用户可以实时调整最小码率和目标码率。*/
    [self.livePusher setTargetVideoBitrate:800];
    [self.livePusher setMinVideoBitrate:200]
    /*获取是否正在推流的状态*/
    BOOL isPushing = [self.livePusher isPushing]; 
    /*获取推流地址*/
    NSString *pushURLString = [self.livePusher getPushURL];
    /*获取推流性能调试信息。推流性能参数具体参数和描述参考API文档或者接口注释。*/
    AlivcLivePushStatsInfo *info = [self.livePusher getLivePushStatusInfo];
    /*获取版本号。*/
    NSString *sdkVersion = [self.livePusher getSDKVersion];
    /*设置log级别,根据需求过滤想要的调试信息*/
    [self.livePusher setLogLevel:(AlivcLivePushLogLevelDebug)];

设置录屏推流

ReplayKit是iOS 9引入的支持屏幕录制功能。iOS 10在ReplayKit中新增了调用第三方App扩展来直播屏幕内容的功能。在iOS 10及以上系统中,使用推流SDK配合Extension录屏进程,可以实现录屏直播。

iOS为了保证系统运行流畅,给Extension录屏进程的资源相对较少,Extension录屏进程内存占用过大会被系统强杀退出。为了解决Extension录屏进程内存限制,推流SDK将录屏推流分成Extension录屏进程(Extension App)和主App进程(Host App)。Extension录屏进程负责抓取屏幕内容,并通过进程间通信将屏幕内容发送给主App进程。主App进程创建推流引擎AlivcLivePusher,并将屏幕数据推送到远端。由于在主App进程中完成整个推流过程,因此麦克风的采集和发送可以放到主App进程中进行,Extension录屏进程只负责屏幕内容采集。
注意 推流SDK Demo是通过App Group实现Extension录屏进程和主App进程之间的进程通信,并将该部分逻辑封装在了AlivcLibReplayKitExt.framework中。
iOS上实现屏幕推流,Extension录屏进程由系统在录屏需要的时候创建,并负责接收系统采集到屏幕图像。需要如下对接操作步骤:
  1. 创建App Group。
    需登录 Apple Developer,完成以下操作:
    1. 在Certificates, IDs & Profiles 页面中注册App Group,具体操作步骤可以参考注册App Group
    2. 回到Identifier页面,选择App IDs,然后单击您的App ID(主App进程与Extension录屏进程的 App ID需要进行同样的配置)启用App Group功能。具体操作步骤可以参考启用App Group
    3. 完成后重新下载对应的Provisioning Profile并配置到XCode中。
    操作正确完成后Extension录屏进程可以和主App进程之间进行进程通信。
    说明 创建App Group完成后需保存App Group Identifier值,作为后续步骤的输入内容。
  2. 创建Extension录屏进程。
    iOS推流SDK Demo中实现了支持录屏直播的App扩展AlivcLiveBroadcast和AlivcLiveBroadcastSetupUI。App中具体创建Extension录屏进程如下:
    1. 在现有工程选择New > Target…,选择Broadcast Upload Extension,如下图:录屏2
    2. 修改Product Name,勾选Include UI Extension,单击Finish创建直播扩展和直播UI,如下图:录屏步骤1
    3. 配置直播扩展Info.plist,在新创建的Target中,Xcode会默认创建名为SampleHandler的头文件和源文件,如下图:录屏3
      AlivcLibReplayKitExt.framework拖到工程中,使得Extension Target依赖它。1替换SampleHandler.m中的代码成如下代码(需将代码中的KAPP Group替换成上文第一步骤创建的App Group Identifier)。示例代码如下:
      
      #import "SampleHandler.h"
      #import <AlivcLibReplayKitExt/AlivcLibReplayKitExt.h>
      
      @implementation SampleHandler
      
      - (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *>
      *)setupInfo {
      
          //User has requested to start the broadcast. Setup info from the UI extension can
      be supplied but optional.
          [[AlivcReplayKitExt sharedInstance] setAppGroup:kAPPGROUP];
      }
      
      - (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {
          if (sampleBufferType != RPSampleBufferTypeAudioMic) {
              //声音由主App进程采集发送
              [[AlivcReplayKitExt sharedInstance] sendSampleBuffer:sampleBuffer withType:sampleBufferType];
          }
      }
      
      - (void)broadcastFinished {
      
          [[AlivcReplayKitExt sharedInstance] finishBroadcast];
      }
      @end
      
                                          
    在您的工程中,完成创建Broadcast Upload Extension的Target,在该Extension Target中集成为录屏扩展模块定制的AlivcLibReplayKitExt.framework
  3. 在录屏推流主App进程中集成直播SDK。
    在录屏推流主App进程中创建AlivcLivePushConfig、AlivcLivePusher对象,设置外置推流ExternMainStream为True, AudioFromExternal为False(该配置表示音频仍通过SDK内部采集),调用StartScreenCapture开始接受Extension App屏幕数据,开始和结束推流。具体可参考以下操作步骤:
    1. 录屏推流主App进程中加入AlivcLivePusher.framework、AlivcLibRtmp.framework、RtsSDK.framework和AlivcLibReplayKitExt.framework的依赖。3
    2. 初始化推流SDK,配置使用外部视频源。
      ExternMainStream设置为True, ExternVideoFormat设置为AlivcLivePushVideoFormatYUV420P,音频使用内部SDK采集AudioFromExternal设置为False,配置其他推流参数,请参见示例代码如下:
             self.pushConfig.externMainStream = true;
          self.pushConfig.externVideoFormat = AlivcLivePushVideoFormatYUV420P;
          self.pushConfig.audioSampleRate = 44100;
          self.pushConfig.audioChannel = 2;
          self.pushConfig.audioFromExternal = false;
          self.pushConfig.videoEncoderMode = AlivcLivePushVideoEncoderModeSoft;
          self.pushConfig.qualityMode = AlivcLivePushQualityModeCustom;
          self.pushConfig.targetVideoBitrate = 2500;
          self.pushConfig.minVideoBitrate = 2000;
          self.pushConfig.initialVideoBitrate = 2000;
          self.livePusher = [[AlivcLivePusher alloc] initWithConfig:self.pushConfig];
      
                                      
    3. 使用AlivcLivePusher来完成直播相关功能,调用如下函数:
      • 开始接受录屏数据。
        需将代码中的kAPPGroup替换成上文创建的App Group Identifier,示例代码如下:
        [self.livePusher startScreenCapture:kAPPGROUP];
      • 开始推流。
        示例代码如下:
        [self.livePusher startPushWithURL:self.pushUrl]
      • 结束推流。
        示例代码如下:
        
        [self.livePusher stopPush];
        [self.livePusher destory];
        self.livePusher = nil;

注意事项

  • 关于包大小:集成SDK后,IPA包增加大小约为3MB。
  • 适配机型。

    iPhone7及以上版本,iOS8.0及以上版本。

  • 关于历史版本升级说明。

    请先删除旧版本的推流SDK,再升级至最新版本的推流SDK。版本升级详情请参见V4.0.2升级至V4.1.0及以上迁移说明