All Products
Search
Document Center

ApsaraVideo Live:Use Push SDK for Flutter

Last Updated:Jan 25, 2024

This topic describes how to use Push SDK for Flutter and the classes and methods in the SDK. This topic also provides examples on how to use the features provided by Push SDK for Flutter.

Features

  • Supports stream ingest over Real-Time Messaging Protocol (RTMP).

  • Supports stream ingest over ARTC based on User Datagram Protocol (UDP).

  • Adopts H.264 for video encoding and Advanced Audio Coding (AAC) for audio encoding.

  • Supports custom configurations for features such as bitrate control, resolution, and display mode.

  • Supports various camera operations.

  • Supports real-time retouching and allows you to adjust retouching effects.

  • Allows you to add animated stickers as animated watermarks and remove animated stickers.

  • Supports external audio and video inputs in different formats such as YUV and pulse-code modulation (PCM).

  • Supports ingest of audio-only streams and stream ingest in the background.

  • Supports background music and allows you to manage background music.

  • Supports the capture of video snapshots.

  • Supports automatic reconnection and error handling.

  • Supports the audio 3A algorithm.

  • Allows you to switch between the software and hardware encoding modes for video files. This improves the stability of the encoding module.

Limits

Take note of the following limits before you use Push SDK for Flutter:

  • You must configure screen orientation before stream ingest. You cannot rotate the screen during live streaming.

  • You must disable auto screen rotation for stream ingest in landscape mode.

  • In hardware encoding mode, the value of the output resolution must be a multiple of 16 to be compatible with the encoder. For example, if you set the resolution to 540p, the output resolution is 544 × 960. When you set the player view size, set proportional resizing based on the output resolution to prevent black bars.

Procedure

The following table describes how to use Push SDK for Flutter.

Step

Description

1. Register the SDK.

Configure the license-related parameters to register Push SDK for Flutter. If you do not call the registration function, the stream ingest feature cannot be used.

2. Configure stream ingest parameters.

Complete stream ingest configurations such as the basic parameters, bitrate control mode, and adaptive resolution.

3. Perform stream ingest.

After you initialize Push SDK for Flutter, register stream ingest callbacks, and create a preview view, you can start to ingest streams. You can manage streams, configure background music, configure camera settings, ingest external audio sources, and add animated stickers based on your business requirements.

Note

ApsaraVideo Live does not allow you to ingest multiple streams to a URL at the same time. If you attempt to ingest multiple streams at the same time, only the first stream is ingested.

Register the SDK

An all-in-one license is used together with Push SDK for Flutter. For more information about how to apply for and configure a license, see Integrate a Push SDK license.

You must register Push SDK for Flutter before you can use the stream ingest feature.

  1. Create an AlivcBase instance.

    AlivcBase alivcBase = AlivcBase.init();
  2. Register the SDK.

    Important

    Before you call the method to register the SDK, you must configure the license.

    alivcBase.registerSDK();
  3. Set the listener for callbacks.

    alivcBase.setObserver();
  4. Configure the callback for license verification.

    alivcBase.setOnLicenceCheck((result, reason) {
        if (result == AlivcLiveLicenseCheckResultCode.success) {
          // The SDK is registered.
        }
    });
  5. Call other methods of AlivcBase.

    /// Obtain the version number of Push SDK.
    String sdkVersion = await AlivcBase.getSdkVersion();
    
    /// Enable log printing in the console.
    AlivcBase.setConsoleEnable(true);
    
    /// Set the log level to Debug.
    AlivcBase.setLogLevel(AlivcLivePushLogLevel.debug);
    /// Specify the log path.
    String logPath = "xxxx"; // xxxx indicates the path in the phone.
    int maxPartFileSizeInKB = 100 * 1024 * 1024; // The custom settings.
    AlivcBase.setLogPath(logPath, maxPartFileSizeInKB);

Configure stream ingest parameters

  1. Create an AlivcLivePusher instance.

    AlivcLivePusher livePusher = AlivcLivePusher.init();
  2. Create a Config object to associate AlivcLivePusherConfig with AlivcLivePusher.

    livePusher.createConfig();
  3. Create an AlivcLivePusherConfig instance.

    AlivcLivePusherConfig pusherConfig = AlivcLivePusherConfig.init();
  4. Complete basic stream ingest configurations based on your business requirements.

    Each parameter that is used for basic stream ingest configurations has a default value. We recommend that you use the default values. The following sample code provides an example:

    /// Set the resolution to 540p.
    pusherConfig.setResolution(AlivcLivePushResolution.resolution_540P);
    /// Specify the frame rate. We recommend that you set the frame rate to 20 frames per second (FPS).
    pusherConfig.setFps(AlivcLivePushFPS.fps_20);
    /// Enable adaptive bitrate streaming. The default value is true.
    pusherConfig.setEnableAutoBitrate(true);
    /// Specify the group of pictures (GOP) size. A larger value indicates  higher latency. We recommend that you set the value to a number from 1 to 2.
    pusherConfig.setVideoEncodeGop(AlivcLivePushVideoEncodeGOP.gop_2);
    /// Specify the reconnection duration. The value cannot be less than 1000. Unit: milliseconds. We recommend that you use the default value. 
    pusherConfig.setConnectRetryInterval(2000);
    /// Disable the mirroring mode for preview.
    pusherConfig.setPreviewMirror(false);
    /// Set the stream ingest orientation to portrait.
    pusherConfig.setOrientation(AlivcLivePushOrientation.portrait);
  5. Specify the bitrate control mode.

    You can configure the AlivcLivePushQualityMode parameter to specify the bitrate control mode. Push SDK for Flutter provides the following bitrate control modes. Specify the value of each parameter based on your business requirements.

    Bitrate control mode

    Description

    Sample code

    AlivcLivePushQualityMode.resolution_first

    The quality-first mode. Push SDK for Flutter configures bitrate parameters to prioritize the quality of video streams.

    pusherConfig.setQualityMode(AlivcLivePushQualityMode.resolution_first);

    AlivcLivePushQualityMode.fluency_first

    The smoothness-first mode. Push SDK for Flutter configures bitrate parameters to prioritize the smoothness of video streams.

    pusherConfig.setQualityMode(AlivcLivePushQualityMode.fluency_first);

    AlivcLivePushQualityMode.custom

    The custom mode. Push SDK for Flutter configures bitrate parameters based on your custom settings. If you use the custom mode, you can select quality-first or smoothness-first based on your business requirements and configure the initialVideoBitrate, minVideoBitrate, and targetVideoBitrate parameters.

    • initialVideoBitrate: the initial bitrate when a live stream starts.

    • minVideoBitrate: In poor network conditions, the bitrate is gradually reduced to the minimum bitrate to prevent stuttering.

    • targetVideoBitrate: In good network conditions, the bitrate is gradually increased to the target bitrate to improve the quality of a video stream.

    pusherConfig.setQualityMode(AlivcLivePushQualityMode.custom);

    Note
    • If you use the quality-first or smoothness-first mode, you do not need to call setInitialVideoBitrate, setMinVideoBitrate, and setTargetVideoBitrate to specify the initial bitrate, minimum bitrate, and target bitrate. Push SDK can ensure the quality or smoothness of video streams when network jitter occurs.

    • If you use the custom mode, configure the bitrate parameters based on the recommended settings. The following table shows the recommended settings.

    Recommended settings for custom bitrate in quality-first mode

    Resolution

    initialVideoBitrate

    minVideoBitrate

    targetVideoBitrate

    360P

    600

    300

    1000

    480P

    800

    300

    1200

    540P

    1000

    600

    1400

    720P

    1500

    600

    2000

    1080P

    1800

    1200

    2500

    Recommended settings for custom bitrate in smoothness-first mode

    Resolution

    initialVideoBitrate

    minVideoBitrate

    targetVideoBitrate

    360P

    400

    200

    600

    480P

    600

    300

    800

    540P

    800

    300

    1000

    720P

    1000

    300

    1200

    1080P

    1500

    1200

    2200

  6. Configure the adaptive resolution feature.

    The adaptive resolution feature is used to dynamically adjust the resolution of a stream. When you enable the adaptive resolution feature, the resolution is automatically reduced to ensure the smoothness and quality of video streams in poor network conditions. The following sample code provides an example:

    /// Enable the adaptive resolution feature.
    pusherConfig.setEnableAutoResolution(true);
    Important
    • The adaptive resolution feature is not supported by all players. If you need to use this feature, we recommend that you use ApsaraVideo Player.

    • The adaptive resolution feature takes effect only when you use the quality-first or smoothness-first mode by configuring the AlivcLivePushQualityMode parameter. This feature is unavailable if you use the custom mode.

  7. Configure image ingest.

    Push SDK for Android allows you to ingest images when your application is switched to the background or the bitrate is low. This improves user experience. When your application is switched to the background, video stream ingest is paused. In this case, only audio streams are ingested. You can also specify an image that you want to ingest. The following sample code provides an example:

    /// Specify the image that is displayed if stream ingest is paused.
    String pauseImagePath = "xxxx"; // xxxx is the path in which the image is stored.
    pusherConfig.setPauseImg(pauseImagePath);

    You can specify a static image for stream ingest in poor network conditions. If the bitrate is low, the image that you specify is ingested to prevent stuttering. The following sample code provides an example:

    /// Specify the image that is displayed in poor network conditions.
    String networkPoorImagePath = "xxxx"; // xxxx is the path in which the image is stored.
    pusherConfig.setNetworkPoorImg(networkPoorImagePath);
  8. Specify the preview mode.

    Push SDK for Flutter supports the following preview modes. The preview mode does not affect stream ingest.

    • AlivcPusherPreviewDisplayMode.preview_scale_fill: In this mode, the video fills the entire preview window. If the aspect ratio of the video is not the same as the aspect ratio of the preview window, deformation occurs during preview.

    • AlivcPusherPreviewDisplayMode.preview_aspect_fit: In this mode, the original aspect ratio of the video is used during preview. If the aspect ratio of the video is not the same as the aspect ratio of the preview window, black bars appear on the preview window.

    • AlivcPusherPreviewDisplayMode.preview_aspect_fill: In this mode, the video is cropped to fit the preview window during preview. If the aspect ratio of the video is not the same as the aspect ratio of the preview window, the video is cropped.

    The following sample code provides an example:

    /// Set the preview mode to AlivcPusherPreviewDisplayMode.preview_aspect_fit.
    pusherConfig.setPreviewDisplayMode(AlivcPusherPreviewDisplayMode.preview_aspect_fit);
  9. Reset the Config object on iOS.

    You can call this method to clear the settings that are configured by the Config object when you do not use AlivcLivePusherConfig on iOS.

    We recommend that you call this method after you call the destroy method of AlivcLivePusher.

    /// Reset the Config object on iOS.
    livePusher.destroyConfigForIOS();

Perform stream ingest

  1. Create a stream ingest engine.

    livePusher.initLivePusher();
  2. Register stream ingest listeners.

    /// Set the listener for the stream ingest status.
    livePusher.setInfoDelegate();
    /// Set the listener for stream ingest errors.
    livePusher.setErrorDelegate();
    /// Set the listener for the network status during stream ingest.
    livePusher.setNetworkDelegate();
  3. Configure callbacks related to stream ingest.

    /// Listener for stream ingest errors
    /// Configure the callback for system errors.
    livePusher.setOnSDKError((errorCode, errorDescription) {});
    /// Configure the callback for system errors.
    livePusher.setOnSystemError((errorCode, errorDescription) {});
    
    /// Listener for the stream ingest status
    /// Configure the callback for preview start.
    livePusher.setOnPreviewStarted(() {});
    /// Configure the callback for preview stop.
    livePusher.setOnPreviewStoped(() {});
    /// Configure the callback for first frame rendering.
    livePusher.setOnFirstFramePreviewed(() {});
    /// Configure the callback for start of stream ingest.
    livePusher.setOnPushStarted(() {});
    /// Configure the callback for pause of stream ingest from the camera.
    livePusher.setOnPushPaused(() {});
    /// Configure the callback for resume of stream ingest from the camera.
    livePusher.setOnPushResumed(() {});
    /// Configure the callback for restart of stream ingest.
    livePusher.setOnPushRestart(() {});
    /// Configure the callback for end of stream ingest.
    livePusher.setOnPushStoped(() {});
    
    /// Listener for the network status during stream ingest
    /// Configure the callback for failed connections during stream ingest.
    livePusher.setOnConnectFail((errorCode, errorDescription) {});
    /// Configure the callback for network recovery.
    livePusher.setOnConnectRecovery(() {});
    /// Configure the callback for disconnection.
    livePusher.setOnConnectionLost(() {});
    /// Configure the callback for poor network connections.
    livePusher.setOnNetworkPoor(() {});
    /// Configure the callback for failed reconnections.
    livePusher.setOnReconnectError((errorCode, errorDescription) {});
    /// Configure the callback for reconnection start.
    livePusher.setOnReconnectStart(() {});
    /// Configure the callback for successful reconnections.
    livePusher.setOnReconnectSuccess(() {});
  4. Create a preview view for stream ingest.

    var x = 0.0; // The custom value.
    var y = 0.0; // The custom value.
    var width = MediaQuery.of(context).size.width; // The custom value.
    var height = MediaQuery.of(context).size.height; // The custom value.
    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. Start preview.

    /// The callback that is fired when a preview view is created.
    _onPusherPreviewCreated(id) {
         /// Start preview.
        livePusher.startPreview();
    }
    Note

    Assume that the screen orientation of the Flutter project is portrait, and you call setOrientation to set the screen orientation to landscape. After you create a preview view and call startPreview to start preview, if the video does not fill the entire preview view, we recommend that you wait a moment before call startPreview. For example, you can wait for 100 ms and then call startPreview.

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

  6. Starts stream ingest. You can start stream ingest only after the preview succeeds.

    String pushURL = "Ingest URL (rtmp://......)"; 
    livePusher.startPushWithURL(pushURL);
  7. Complete other stream ingest configurations.

    /// Pause stream ingest from the camera. Call the pause method to switch from camera ingest to image ingest after you call setPauseImg. The audio stream continues to be ingested. 
    livePusher.pause();
    /// Switch from image ingest to camera ingest. The audio stream continues to be ingested.
    livePusher.resume();
    /// Stop a stream that is being ingested.
    livePusher.stopPush();
    /// Stop preview. However, this operation does not take effect for a stream that is being ingested. When preview is stopped, the preview window is frozen at the last frame.
    livePusher.stopPreview();
    /// Restart stream ingest when the stream is being ingested or when an error callback is received. If an error occurs, you can call only this method or the reconnectPushAsync method to restart stream ingest. You can also call the destroy method to destroy the stream ingest engine. Then, you can restart all AlivcLivePusher resources that are required for operations, such as preview and stream ingest.
    livePusher.restartPush();
    /// Call this method when the stream is being ingested or when an error callback related to setNetworkDelegate is received. If an error occurs, you can call only this method or the restartPush method to restart stream ingest. You can also call the destroy method to destroy the stream ingest engine. Then, you can restart stream ingest over RTMP.
    livePusher.reconnectPushAsync();
    /// Destroy the stream ingest engine. After you call this method, stream ingest and preview are stopped, and the preview window is removed. All resources related to AlivcLivePusher are destroyed.
    livePusher.destory();
  8. Manage background music.

    /// Start the playback of background music.
    String musicPath = "xxxx"; // xxxx is the path in which the music resources are stored.
    livePusher.startBGMWithMusicPathAsync(musicPath);
    /// Stop the playback of background music. If you want to change the background music, call the method that is used to start the playback of background music. You do not need to stop the playback of the current background music.
    livePusher.stopBGMAsync();
    /// Pause the playback of background music. You can call this method only after the playback of background music starts.
    livePusher.pauseBGM();
    /// Resume the playback of background music. You can call this method only after the playback of background music is paused.
    livePusher.resumeBGM();
    /// Enable looping.
    livePusher.setBGMLoop(true);
    /// Configure noise reduction. If you enable noise reduction, the system filters out non-vocal parts from collected audio. This feature may slightly reduce the volume of the human voice. We recommend that you allow your users to determine whether to enable this feature. By default, this feature is disabled.
    livePusher.setAudioDenoise(true);
    /// Configure in-ear monitoring. In-ear monitoring is suitable for scenarios that involve karaoke. If you enable in-ear monitoring, you can hear your voice on your earphones during streaming. If you disable in-ear monitoring, you cannot hear your voice on your earphones during streaming. This feature does not take effect if no earphones are detected.
    livePusher.setBGMEarsBack(true);
    /// Specify the volume of the background music in the mixed audio.
    livePusher.setBGMVolume(50); // Valid values: 0 to 100. Default value: 50.
    /// Specify the volume of the human voice in the mixed audio.
    livePusher.setCaptureVolume(50); // Valid values: 0 to 100. Default value: 50.
    /// Configure muting. If you enable this feature, the background music and human voice are muted. To separately mute the background music or human voice, call the method that is used to configure the volume.
    livePusher.setMute(true);

    Configure callbacks related to background music.

    /// Configure the callback for complete playback of background music.
    livePusher.setOnBGMCompleted(() {});
    /// Configure the callback for timeout of the download of background music.
    livePusher.setOnBGMDownloadTimeout(() {});
    /// Configure the callback for failed playback of background music.
    livePusher.setOnBGMOpenFailed(() {});
    /// Configure the callback for paused playback of background music.
    livePusher.setOnBGMPaused(() {});
    /// Configure the callback for playback progress.
    livePusher.setOnBGMProgress((progress, duration) {});
    /// Configure the callback for resumed playback of background music.
    livePusher.setOnBGMResumed(() {});
    /// Configure the callback for start of playback of background music.
    livePusher.setOnBGMStarted(() {});
    /// Configure the callback for stop of playback of background music.
    livePusher.setOnBGMStoped(() {});
  9. Configure stream ingest snapshots.

    /// Configure snapshot settings.
    String dir = "xxxx"; // xxxx is the path in which snapshots are stored.
    if (Platform.isIOS) {
        /// dir parameter: On iOS, the path is a relative path. A custom directory is automatically generated in the system sandbox. If you set this parameter to "", snapshots are stored in the root directory of the system sandbox. 
        /// dirTypeForIOS parameter: Optional. If you do not specify this parameter, snapshots are stored in the [document] directory of the system sandbox. 
        livePusher.snapshot(1, 0, dir, dirTypeForIOS: AlivcLiveSnapshotDirType.document);
    } else {
        livePusher.snapshot(1, 0, dir);
    }
    /// Set the listener for snapshot capture.
    livePusher.setSnapshotDelegate();
    
    /// Configure callbacks related to snapshot capture.
    livePusher.setOnSnapshot((saveResult, savePath, {dirTypeForIOS}) {
      	// The callback that is fired when a snapshot is stored.
        if (saveResult == true) {
          if (Platform.isIOS) {
            // Construct the full path of snapshots in the system sandbox. Format: dirTypeForIOS + savePath.
          } else {
            // Obtain the path of screenshots in SD based on the value of savePath.
          }
        }
      });
  10. Perform camera-related operations.

    /// Switch between the front and rear cameras.
    livePusher.switchCamera();
    /// Enable or disable flash. You cannot enable flash for the front camera.
    livePusher.setFlash(false);
    
    /// Adjust the focal length to zoom in or out. If you set the input parameter to a positive number, the system increases the focal length. If you set the input parameter to a negative number, the system decreases the focal length.
    double max = await livePusher.getMaxZoom();
    livePusher.setZoom(min(1.0, max));
    
    /// Configure manual focus.
    /// The autoFocus parameter specifies whether to enable autofocus. This parameter takes effect only for this configuration. Whether autofocus is enabled otherwise depends on the setAutoFocus method. 
    double pointX = 50.0; // The custom value.
    double pointY = 50.0; // The custom value.
    bool autoFocus = true;
    livePusher.focusCameraAtAdjustedPoint(pointX, pointY, autoFocus);
    
    /// Disable autofocus.
    livePusher.setAutoFocus(false);
    /// Disable the mirroring mode for preview.
    livePusher.setPreviewMirror(false);
    /// Disable the mirroring mode for stream ingest.
    livePusher.setPushMirror(false);
  11. Configure watermarks. Push SDK for Flutter allows you to add one or more watermarks. Watermarks must be in the PNG format. The following sample code provides an example:

    String watermarkBundlePath = "xxxx"; //xxxx is the path in which watermark resources are stored.
    double coordX = 0.1;
    double coordY = 0.1;
    double width = 0.3;
    /// Add a watermark.
    livePusher.addWatermark(watermarkBundlePath, coordX, coordY, width);
    Note
    • The values of the coordX, coordY, and width parameters are relative. For example, a value of 0.1 for the coordX parameter indicates that the left edge of the watermark is at the 10% position on the x-axis of the stream ingest screen. Therefore, if the stream resolution is 540 × 960, the value of the coordX parameter is 54.

    • The height of the watermark is scaled based on the width and height of the source image and the input width value of the watermark.

    • If you want to add a text watermark, you can convert the text into an image and call the addWatermark method to add the image as a watermark.

    • To ensure the clarity and smoothness of the edges of the watermark, we recommend that you use a source image that has the same size as the output watermark. For example, if the resolution of the output video is 544 × 940 and the width of the watermark is 0.1f, we recommend that you use the following width for the source image: 544 × 0.1f = 54.4.

  12. Configure external audio and video sources. Push SDK for Flutter allows you to import external audio and video sources for stream ingest. For example, you can ingest an audio or video file.

    1. Configure the input of external audio and video sources in stream ingest settings.

      /// Enable the input of external streams.
      pusherConfig.setExternMainStream(true);
      /// Specify the color format for video data. In this example, the color format is YUVNV21. You can also use other formats based on your business requirements. 
      pusherConfig.setExternVideoFormat(AlivcLivePushVideoFormat.YUVNV21);
      /// Specify the bit depth format for audio data. In this example, the bit depth format is S16. You can also use other formats based on your business requirements.
      pusherConfig.setExternMainStream(AlivcLivePushAudioFormat.S16);
    2. Import external video data.

      /// The sendVideoData method supports only native YUV and RGB buffer data. You can call the sendVideoData method to transmit video data such as the buffer, length, width, height, timestamp, and rotation angle.
      Uint8List bufferData = xxxx; // xxxx indicates the continuous video buffer data in the Uint8List format.
      int width = 720; // The video width.
      int height = 1280; // The video height.
      int dataSize = xxxx; // xxxx indicates the size of the data.
      int pts = xxxx; // xxxx indicates the timestamp in microseconds.
      int rotation = 0; // The rotation angle.
      livePusher.sendVideoData(bufferData, width, height, size, pts, rotation);
    3. Import external audio data.

      /// The sendPCMData method supports only native PCM buffer data. You can call this method to transmit audio data such as the buffer, length, and timestamp.
      Uint8List bufferData = xxxx; // xxxx indicates the continuous audio buffer data in the Uint8List format.
      int dataSize = xxxx; // xxxx indicates the size of the data.
      int sampleRate = xxxx; // xxxx indicates the sampling rate.
      int channel = 0; // The number of sound channels.
      int pts = xxxx; // xxxx indicates the timestamp in microseconds.
      livePusher.sendPCMData(bufferData, size, sampleRate, channel, pts);

Add retouching effects

Push SDK for Flutter provides retouching effects by using plug-ins. To use the retouching feature, download the source code package from SDK download and use the flutter_livepush_beauty_plugin plug-in in the demo > plugins directory. Note: The retouching plug-in is not released to the public.

/// 1. Initialize a retouching object.
AlivcLiveBeautyManager beautyManager = AlivcLiveBeautyManager.init();
beautyManager.setupBeauty();
/// 2. Open the retouching panel.
beautyManager.showPanel();
/// 3. Close the retouching panel (for Android).
beautyManager.hidePanel();
/// 4. Destroy the retouching object.
beautyManager.destroyBeauty();