功能说明

本文详细说明Flutter框架直播推流SDK基本使用流程,以及相关功能的使用示例。

Flutter框架直播推流SDK特性

  • 支持RTMP推流协议。

  • 支持基于UDP的ARTC协议推流。

  • 使用视频H.264编码以及音频AAC编码。

  • 支持码控、分辨率、显示模式等自定义配置。

  • 支持多种摄像头相关操作。

  • 支持实时美颜和自定义美颜效果调节。

  • 支持增、删动态贴纸实现动态水印效果。

  • 支持自定义YUV、PCM等外部音视频输入。

  • 支持纯音视频推流以及后台推流。

  • 支持背景音乐及其相关操作。

  • 支持视频截图功能。

  • 支持自动重连、异常处理。

  • 支持音频3A算法。

  • 增加视频软编、硬编切换逻辑,提升编码模块稳定性。

功能限制

Flutter框架直播推流SDK需注意以下限制:

  • 您只能在推流之前设置横竖屏模式,不支持在直播的过程中实时切换。

  • 在推流设定为横屏模式时,需设定界面为不允许自动旋转。

  • 在硬编模式下,考虑编码器兼容问题分辨率会使用16的倍数,如设定为540P,则输出的分辨率为544*960,在设置播放器视图大小时需按输出分辨率等比缩放,避免黑边等问题。

使用流程

基本使用流程如下:

步骤

描述

一、注册SDK

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

二、配置推流参数

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

三、进行推流

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

说明

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

注册SDK

Flutter框架直播推流SDK已接入一体化License服务,申请并配置License请参见直播推流SDK License集成指南

在使用推流功能前必须进行注册,否则无法使用直播推流SDK功能。

  1. 创建AlivcBase实例。

    /// 引入头文件
    import 'package:flutter_livepush_plugin/live_base.dart';
    
    AlivcBase alivcBase = AlivcBase.init();
  2. 注册SDK。

    重要

    在调用注册SDK方法前,需要提前配置License。

    alivcBase.registerSDK();
  3. 设置监听回调接口。

    alivcBase.setObserver();
  4. SDK Licence校验接口回调。

    alivcBase.setOnLicenceCheck((result, reason) {
        if (result == AlivcLiveLicenseCheckResultCode.success) {
          // 注册SDK成功
        }
    });
  5. 使用AlivcBase其它接口。

    /// 获取原生直播推流SDK版本号
    String sdkVersion = await AlivcBase.getSdkVersion();
    
    /// 启用控制台日志打印
    AlivcBase.setConsoleEnable(true);
    
    /// 设置log级别为Debug调试级别
    AlivcBase.setLogLevel(AlivcLivePushLogLevel.debug);
    /// 设置Log路径
    String logPath = "xxxx"; // xxxx为手机存放的路径
    int maxPartFileSizeInKB = 100 * 1024 * 1024; // 自定义设置
    AlivcBase.setLogPath(logPath, maxPartFileSizeInKB);

配置推流参数

  1. 创建AlivcLivePusher实例。

    /// 引入头文件
    import 'package:flutter_livepush_plugin/live_pusher.dart';
    import 'package:flutter_livepush_plugin/live_push_config.dart';
    
    AlivcLivePusher livePusher = AlivcLivePusher.init();
  2. 创建Config,将AlivcLivePusherConfig同AlivcLivePusher联系起来。

    livePusher.createConfig();
  3. 创建AlivcLivePusherConfig实例。

    AlivcLivePusherConfig pusherConfig = AlivcLivePusherConfig.init();
  4. 设置推流参数根据使用场景,自定义设置。

    基本推流配置对应参数都有默认值,建议采用默认值,即您可以进行简单初始化,不做配置。 示例代码如下:

    /// 设置分辨率为540P
    pusherConfig.setResolution(AlivcLivePushResolution.resolution_540P);
    /// 设置视频采集帧率为20fps。建议用户使用20fps
    pusherConfig.setFps(AlivcLivePushFPS.fps_20);
    /// 打开码率自适应,默认为true
    pusherConfig.setEnableAutoBitrate(true);
    /// 设置关键帧间隔。关键帧间隔越大,延时越高。建议设置为1-2
    pusherConfig.setVideoEncodeGop(AlivcLivePushVideoEncodeGOP.gop_2);
    /// 设置重连时长为2s。单位为毫秒,设置不小于1秒,建议使用默认值即可。
    pusherConfig.setConnectRetryInterval(2000);
    /// 设置预览镜像为关闭
    pusherConfig.setPreviewMirror(false);
    /// 设置推流方向为竖屏
    pusherConfig.setOrientation(AlivcLivePushOrientation.portrait);
  5. 配置码率控制。

    码率控制通过AlivcLivePushQualityMode枚举参数配置。直播推流SDK提供以下码率控制模式,请根据实际需求修改参数值。

    码率控制模式

    描述

    示例代码

    AlivcLivePushQualityMode.resolution_first

    清晰度优先模式。SDK内部会对码率参数进行配置,优先保障推流视频的清晰度。

    pusherConfig.setQualityMode(AlivcLivePushQualityMode.resolution_first);

    AlivcLivePushQualityMode.fluency_first

    流畅度优先模式。SDK内部会对码率参数进行配置,优先保障推流视频的流畅度。

    pusherConfig.setQualityMode(AlivcLivePushQualityMode.fluency_first);

    AlivcLivePushQualityMode.custom

    自定义模式。SDK会根据开发者设置的码率进行配置。设置为自定义模式时,您可以选择配置画质优先或者流畅度优先,并自行设定初始码率、最小码率和目标码率。

    • 初始码率:开始直播时的码率。

    • 最小码率:当网络较差时,码率会逐步减低到最小码率,以减少视频的卡顿。

    • 目标码率:当网络较好时,码率会逐步提高到目标码率,以提高视频清晰度。

    pusherConfig.setQualityMode(AlivcLivePushQualityMode.custom);

    说明
    • 选择清晰度优先或流畅度优先模式时,不需设置初始码率、最小码率和目标码率(setInitialVideoBitrate、setMinVideoBitrate、setTargetVideoBitrate)。直播推流SDK内部策略会自动保障在网络抖动情况下优先考虑视频清晰度或流畅度。

    • 选择自定义码率时,请参考阿里云推荐设置配置对应码率。推荐设置请参考下表内容。

    自定义码率控制推荐设置(画质优先)

    分辨率

    初始码率 initialVideoBitrate

    最小码率 minVideoBitrate

    目标码率 targetVideoBitrate

    360P

    600

    300

    1000

    480P

    800

    300

    1200

    540P

    1000

    600

    1400

    720P

    1500

    600

    2000

    1080P

    1800

    1200

    2500

    自定义码率控制推荐设置(流畅度优先)

    分辨率

    初始码率 initialVideoBitrate

    最小码率 minVideoBitrate

    目标码率 targetVideoBitrate

    360P

    400

    200

    600

    480P

    600

    300

    800

    540P

    800

    300

    1000

    720P

    1000

    300

    1200

    1080P

    1500

    1200

    2200

  6. 配置分辨率自适应。

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

    /// 设置打开分辨率自适应
    pusherConfig.setEnableAutoResolution(true);
    重要
    • 某些播放器可能不支持动态分辨率,如果您需要使用分辨率自适应功能,建议使用阿里云播放器。

    • 分辨率自适应只有在清晰度优先或流畅度优先时才会生效(AlivcLivePushQualityMode枚举参数配置),自定义模式时无效。

  7. 配置图片推流。

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

    /// 设置暂停图片
    String pauseImagePath = "xxxx"; // xxxx为手机存放的图片路径
    pusherConfig.setPauseImg(pauseImagePath);

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

    /// 设置网络差图片
    String networkPoorImagePath = "xxxx"; // xxxx为手机存放的图片路径
    pusherConfig.setNetworkPoorImg(networkPoorImagePath);
  8. 配置预览显示模式。

    直播推流SDK支持三种预览模式,预览显示模式不影响推流。

    • AlivcPusherPreviewDisplayMode.preview_scale_fill:预览显示时,铺满窗口。当视频比例和窗口比例不一致时,预览会有变形。

    • AlivcPusherPreviewDisplayMode.preview_aspect_fit:预览显示时,保持视频比例。当视频比例与窗口比例不一致时,预览会有黑边。

    • AlivcPusherPreviewDisplayMode.preview_aspect_fill:预览显示时,剪切视频以适配窗口比例。当视频比例和窗口比例不一致时,预览会裁剪视频。

    示例代码如下:

    /// 设置预览显示模式为保持视频比例
    pusherConfig.setPreviewDisplayMode(AlivcPusherPreviewDisplayMode.preview_aspect_fit);
  9. iOS系统下重置config。

    iOS系统下不再使用[AlivcLivePusherConfig时,建议主动调用下该方法,重置原生config对象,下次再创建时恢复为默认状态。

    建议在AlivcLivePusher已经调用destroy的情况下调用该方法。

    /// iOS系统下重置config
    livePusher.destroyConfigForIOS();

进行推流

  1. 创建推流引擎实例。

    livePusher.initLivePusher();
  2. 注册推流监听回调。

    /// 设置推流状态监听回调
    livePusher.setInfoDelegate();
    /// 设置推流错误监听回调
    livePusher.setErrorDelegate();
    /// 设置推流网络监听回调
    livePusher.setNetworkDelegate();
  3. 监听推流相关回调。

    /// 推流错误监听回调
    /// 系统错误回调
    livePusher.setOnSDKError((errorCode, errorDescription) {});
    /// 系统错误回调
    livePusher.setOnSystemError((errorCode, errorDescription) {});
    
    /// 推流状态监听回调
    /// 开始预览回调
    livePusher.setOnPreviewStarted(() {});
    /// 停止预览回调
    livePusher.setOnPreviewStoped(() {});
    /// 渲染第一帧回调
    livePusher.setOnFirstFramePreviewed(() {});
    /// 推流开始回调
    livePusher.setOnPushStarted(() {});
    /// 摄像头推流暂停回调
    livePusher.setOnPushPaused(() {});
    /// 摄像头推流恢复回调
    livePusher.setOnPushResumed(() {});
    /// 重新推流回调
    livePusher.setOnPushRestart(() {});
    /// 推流停止回调
    livePusher.setOnPushStoped(() {});
    
    /// 推流网络监听回调
    /// 推流链接失败
    livePusher.setOnConnectFail((errorCode, errorDescription) {});
    /// 网络恢复
    livePusher.setOnConnectRecovery(() {});
    /// 连接被断开
    livePusher.setOnConnectionLost(() {});
    /// 网络差回调
    livePusher.setOnNetworkPoor(() {});
    /// 重连失败回调
    livePusher.setOnReconnectError((errorCode, errorDescription) {});
    /// 重连开始回调
    livePusher.setOnReconnectStart(() {});
    /// 重连成功回调
    livePusher.setOnReconnectSuccess(() {});
  4. 创建推流预览视图。

    var x = 0.0; // 自定义数值
    var y = 0.0; // 自定义数值
    var width = MediaQuery.of(context).size.width; // 自定义数值
    var height = MediaQuery.of(context).size.height; // 自定义数值
    AlivcPusherPreview pusherPreviewView = AlivcPusherPreview(
          onCreated: _onPusherPreviewCreated,
          x: x,
          y: y,
          width: width,
          height: height);
      return Container(
            color: Colors.black,
            width: width,
            height: height,
            child: pusherPreviewView);
  5. 开始预览。

    /// 视图创建回调
    _onPusherPreviewCreated(id) {
         /// 开始预览
        livePusher.startPreview();
    }
    说明

    如果flutter工程设置的屏幕方向是竖屏,在设置推流方向setOrientation为横屏时,此时手动调用旋屏方法创建推流预览视图的时候,在视图创建回调调用开始预览startPreview方法之后,如果出现预览渲染画面没有铺满设置的预览视图大小,则建议在调用开始预览方法之前手动执行下延迟一段时间再调用,比如延迟100ms:

    Future.delayed(Duration(milliseconds: 100));

  6. 开始推流。预览成功后才可以开始推流。

    String pushURL = "推流测试地址(rtmp://......)"; 
    livePusher.startPushWithURL(pushURL);
  7. 设置其他推流控制。

    /// 暂停摄像头推流。可以调用[setPauseImg]后调用[pause]接口,从摄像头推流切换成静态图片推流,音频推流继续。
    livePusher.pause();
    /// 从静态图片推流切换成摄像头推流,音频推流继续
    livePusher.resume();
    /// 推流状态下可调用停止推流,完成后推流停止
    livePusher.stopPush();
    /// 在预览状态下才可以调用停止预览,正在推流状态下,调用停止预览无效。预览停止后,预览画面定格在最后一帧
    livePusher.stopPreview();
    /// 推流状态下或者接收到所有Error相关回调状态下可调用重新推流,且Error状态下只可以调用此接口(或者[reconnectPushAsync]重连)或者调用[destory]销毁推流。完成后重新开始推流,重启[AlivcLivePusher]内部的一切资源,包括预览、推流等等restart
    livePusher.restartPush();
    /// 推流状态下或者接收到[setNetworkDelegate]相关的Error回调状态下可调用此接口, 且Error状态下只可以调用此接口(或者[restartPush]重新推流)或者调用[destory]销毁推流。完成后推流重连,重新链接推流
    livePusher.reconnectPushAsync();
    /// 销毁推流后,推流停止,预览停止,预览画面移除。[AlivcLivePusher]相关的一切资源销毁
    livePusher.destory();
  8. 设置背景音乐。

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

    监听背景音乐相关回调。

    /// 背景音乐播放完毕
    livePusher.setOnBGMCompleted(() {});
    /// 背景音乐下载播放超时
    livePusher.setOnBGMDownloadTimeout(() {});
    /// 背景音乐开启失败
    livePusher.setOnBGMOpenFailed(() {});
    /// 背景音乐暂停播放
    livePusher.setOnBGMPaused(() {});
    /// 背景音乐当前播放进度
    livePusher.setOnBGMProgress((progress, duration) {});
    /// 背景音乐恢复播放
    livePusher.setOnBGMResumed(() {});
    /// 背景音乐开始播放
    livePusher.setOnBGMStarted(() {});
    /// 背景音乐停止播放
    livePusher.setOnBGMStoped(() {});
  9. 设置推流截图。

    /// 调用截图
    String dir = "xxxx"; // xxxx代表设置路径
    if (Platform.isIOS) {
        /// dir设置要求:iOS系统下是指定存放相对的路径,会在系统沙盒路径下自动生成自定义的目录,设置为""时,则保存在系统沙盒路径下。
        /// dirTypeForIOS:可选设置。不设置默认是放在系统沙盒的[document]路径下。
        livePusher.snapshot(1, 0, dir, dirTypeForIOS: AlivcLiveSnapshotDirType.document);
    } else {
        livePusher.snapshot(1, 0, dir);
    }
    /// 设置截图回调,需要在调用[snapshot]后调用
    livePusher.setSnapshotDelegate();
    
    /// 监听截图回调
    livePusher.setOnSnapshot((saveResult, savePath, {dirTypeForIOS}) {
      	// 截图保存成功
        if (saveResult == true) {
          if (Platform.isIOS) {
            // 根据dirTypeForIOS + savePath拼接获取沙盒路径下的完整截图保存路径
          } else {
            // 根据savePath获取SD下的截图保存路径
          }
        }
      });
  10. 摄像头相关操作。

    /// 切换前后摄像头
    livePusher.switchCamera();
    /// 开启/关闭闪光灯,在前置摄像头时开启闪关灯无效
    livePusher.setFlash(false);
    
    /// 焦距调整,即可实现采集画面的缩放功能。传入参数为正数,则放大焦距,传入参数为负数则缩小焦距
    double max = await livePusher.getMaxZoom();
    livePusher.setZoom(min(1.0, max));
    
    /// 手动对焦
    /// [autoFocus]参数表示是否需要自动对焦,该参数仅对调用接口的该次对焦操作生效。后续是否自动对焦沿用上述自动聚焦接口设置值。
    double pointX = 50.0; // 自定义数值
    double pointY = 50.0; // 自定义数值
    bool autoFocus = true;
    livePusher.focusCameraAtAdjustedPoint(pointX, pointY, autoFocus);
    
    /// 设置不打开自动对焦
    livePusher.setAutoFocus(false);
    /// 设置不打开预览镜像
    livePusher.setPreviewMirror(false);
    /// 设置不打开推流镜像
    livePusher.setPushMirror(false);
  11. 配置水印。直播推流SDK提供了添加水印功能,并且最多支持添加多个水印,水印图片必须为PNG格式图片。示例代码如下:

    String watermarkBundlePath = "xxxx"; //xxxx为手机存放的水印图片资源路径
    double coordX = 0.1;
    double coordY = 0.1;
    double width = 0.3;
    /// 添加水印
    livePusher.addWatermark(watermarkBundlePath, coordX, coordY, width);
    说明
    • coordX、coordY、width为相对值,例如coordX:0.1表示水印的x值为推流画面x轴的10%位置,如果推流分辨率为540*960,则水印x值为54。

    • 水印图片的高度,按照水印图片的真实宽高与输入的width值等比缩放。

    • 要实现文字水印,可以先将文字转换为图片,再使用此接口添加水印。

    • 为了保障水印显示的清晰度与边缘平滑,请您尽量使用和水印输出尺寸相同大小的水印源图片。如输出视频分辨率544*940,水印显示的w是0.1f,则尽量使用水印源图片宽度在544*0.1f=54.4左右。

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

    1. 在推流配置里面进行外部音视频输入配置。

      /// 开启允许外部流输入
      pusherConfig.setExternMainStream(true);
      /// 设置视频数据颜色格式定义,这里设置为YUVNV21,可根据需求设置为其他格式。
      pusherConfig.setExternVideoFormat(AlivcLivePushVideoFormat.YUVNV21);
      /// 设置音频数据位深度格式,这里设置为S16,可根据需求设置为其他格式
      pusherConfig.setExternMainStream(AlivcLivePushAudioFormat.S16);
    2. 插入外部视频数据。

      /// 只支持外部视频yuv和rbg格式的连续buffer数据,才可以通过sendVideoData接口,发送视频数据buffer、长度、宽高、时间戳、旋转角度
      Uint8List bufferData = xxxx; // xxxx代表Uint8List格式的连续buffer视频数据
      int width = 720; // 视频宽度
      int height = 1280; // 视频高度
      int dataSize = xxxx; // xxxx代表data数据大小
      int pts = xxxx; // xxxx代表时间戳(单位微秒)
      int rotation = 0; // 旋转角度
      livePusher.sendVideoData(bufferData, width, height, size, pts, rotation);
    3. 插入外部音频数据。

      /// 只支持外部pcm格式的连续buffer数据,sendPCMData,发送音频数据buffer、长度、时间戳
      Uint8List bufferData = xxxx; // xxxx代表Uint8List格式的连续buffer音频数据
      int dataSize = xxxx; // xxxx代表data数据大小
      int sampleRate = xxxx; // xxxx代表采样率
      int channel = 0; // 声道数
      int pts = xxxx; // xxxx代表时间戳(单位微秒)
      livePusher.sendPCMData(bufferData, size, sampleRate, channel, pts);