Multi-source recording

Updated at:
Copy as MD

Multi-source recording extends the short video SDK with view recording (screen recording), letting you combine camera feeds and view recordings into composite videos.

Supported editions

Edition

Supported

Professional

Yes

Standard

Yes

Basic

No

Concepts

Before using this feature, familiarize yourself with these key concepts: multi-source recording, track, and track layout.

Related classes

Class

Description

AliyunIVideoRecorder

The core class for multi-source recording. Handles recording, preview configuration, effect settings, and callback handling.

AliyunMultiRecorderCreator

A factory class for creating video recording instances.

AliyunVideoRecorderConfig

Defines recording parameters, such as video resolution, encoder type, and frame rate.

AliyunIVideoCapture

An interface for configuring video data capture, with methods for adding camera and view recording capturers.

AliyunICameraCapture

An interface for camera recording.

AliyunIViewCapture

An interface for view recording.

OnVideoRecordListener

An interface for recording listeners, including callbacks for recording completion, progress, and errors.

OnAudioCallback

An audio callback interface that provides audio data in PCM format.

OnFrameCallback

A callback interface for camera data capture, with callbacks for preview resolution selection, captured frames, and camera startup failures.

OnPictureCallback

A callback interface for taking photos and screenshots.

AliyunIClipManager

An interface for managing video clips, such as deleting clips and setting the recording duration.

Procedure

Note

To use multi-source recording, you must grant camera and microphone permissions. Otherwise, recording will fail.

Phase

Step

Description

Sample code

Basic

1

Create and destroy recording instances, and configure recording parameters.

Initialize the AliyunIVideoRecorder class and configure parameters

2

Configure parameters for view recording and camera recording.

Configure video sources

3

Set up callbacks.

Configure callbacks

4

Set a preview view and enable the preview.

Enable preview

5

Start, stop, and cancel recording of a video clip.

Start recording

6

Finish recording to generate the final video.

Finish recording

Advanced

7

Configure camera controls (such as camera type and flash mode) and clip management parameters (such as maximum or minimum recording duration, deleting a clip, and querying the number of clips). These settings are optional.

Configure camera settings and manage video clips

8

Optionally, configure recording effects such as retouching, filters, and animated stickers.

Configure effects

9

Set background music, background images, and speed ramping.

Configure other features

Initialize and configure parameters

Initialize the AliyunIVideoRecorder class, create a recording instance, and configure recording parameters. For more information about the code parameters, refer to Related classes.

Initialize the class

// Create a recording instance.
AliyunIVideoRecorder recorder = AliyunMultiRecorderCreator.getVideoRecorderInstance(context, config);

// Destroy the recording instance.
// Call this method when you no longer need the SDK or before exiting the application.
// We recommend calling it in Activity#onDestroy. Do not destroy the instance during a recording session.
recorder.destroy();

Configure recording parameters

AliyunVideoRecorderConfig config = AliyunVideoRecorderConfig.builder()
                // Required parameters
                .videoWidth(***)
                .videoHeight(***)
                .outputPath(***)
                // Optional parameters
                .***()
                .***()
                .build();

Configure video sources

Combine multiple video sources as needed. After adding all sources, call recorder.prepare() to finalize the configuration.

Camera recording

For more information about API parameters, see AliyunICameraCapture.

// 1. Configure the layout.
AliyunLayoutParam cameraLayoutParam = AliyunLayoutParam.builder()
                .layoutLevel(***)
                .centerX(***)
                .centerY(***)
                .widthRatio(***)
                .heightRatio(***)
                .displayMode(***)
                .build();

// 2. Add the video source.
AliyunICameraCapture cameraCapture = recorder.getVideoCapture().addCameraCapture(cameraLayoutParam);

// 3. Configure the video source.
// Set the camera preview view. This is a required property.
cameraCapture.setDisplayView(SurfaceView)
// Other settings (configure as needed).
cameraCapture.set***();

View recording

For more information about API parameters, see AliyunIViewCapture.

// 1. Configure the layout.
AliyunLayoutParam viewLayoutParam = AliyunLayoutParam.builder()
                .layoutLevel(***)
                .centerX(***)
                .centerY(***)
                .widthRatio(***)
                .heightRatio(***)
                .displayMode(***)
                .build();

// 2. Add the video source.
// Get the current recording view.
View recordView = getRecordView();
AliyunIViewCapture viewCapture = recorder.getVideoCapture().addViewCapture(viewLayoutParam, recordView);

// 3. Configure the video source (as needed).
viewCapture.set***();

Prepare video sources

After adding all video sources, call the following method to complete the configuration.

recorder.prepare();

Configure callbacks

Set up callbacks for real-time audio and video processing status updates. For more information about the parameters used in the code, see the API reference in Related classes.

// Set the recording callback (optional).
recorder.setOnRecordListener(OnVideoRecordListener);

// Set the callback for captured audio data (optional).
recorder.setOnAudioCallback(OnAudioCallback);

Enable preview

Typically, you call startPreview in Activity#onResume and stopPreview in Activity#onPause. For more information about the parameters used in the code, see the API reference in Related classes.

// Start the preview.
// Typically called in Activity#onResume.
AliyunIRecorder.startPreview();

// Stop the preview.
// Typically called in Activity#onPause.
AliyunIRecorder.stopPreview();

Start recording

During recording, you can stop, cancel, and restart multiple times. Stopping the recording saves a video clip, while canceling discards the current one. For more information about the parameters used in the code, see the API reference in Related classes.

Start recording

// Start recording.
recorder.startRecording();

Record a clip

// Start recording.
recorder.startRecording();

// Stop recording. A video clip is generated.
recorder.stopRecording();

recorder.startRecording();
// Cancel recording. The current video clip is not saved.
recorder.cancelRecording();

// Continue recording the next video clip.
recorder.startRecording();
recorder.stopRecording();

Finish recording

When you finish recording, you can either merge all clips into a single video or generate a configuration file for the clips without merging them. For more information about the parameters used in the code, see the API reference in Related classes.

// Finish recording and merge the video clips into a single video.
recorder.finishRecording();

// Finish recording and generate a configuration file for the clips (without merging).
recorder.finishRecordingForEdit();

Camera control and clip management

Configure camera controls (such as camera type and flash mode) and clip management parameters (such as maximum or minimum recording duration, deleting a clip, and querying the number of clips). These settings are optional. For more information about the parameters used in the code, see the API reference in Related classes.

Camera controls

// Get the number of cameras.
AliyunICameraCapture.getCameraCount();

// Set the camera type: front camera or rear camera.
AliyunICameraCapture.setCamera(CameraType cameraType);

// Set the sensor rotation angle.
// Important: Refer to the API reference for correct usage.
AliyunICameraCapture.setRotation(int rotation);

// Set the video recording rotation angle.
// Important: Refer to the API reference for correct usage.
AliyunICameraCapture.setRecordRotation(int rotation);

// Set camera preview parameters (flash, focus mode, zoom, exposure).
// You can also set these parameters individually using the methods below.
AliyunICameraCapture.setCameraParam(CameraParam cameraParam);

// Switch between the front and rear cameras.
AliyunICameraCapture.switchCamera();

// Set the flash mode.
AliyunICameraCapture.setLight(FlashType flashType);

// Set the zoom level.
AliyunICameraCapture.setZoom(float rate);

// Set the exposure compensation ratio.
AliyunICameraCapture.setExposureCompensationRatio(float value);

// Set the focus mode.
AliyunICameraCapture.setFocusMode(int mode);

// Manually set the focus point.
AliyunICameraCapture.setFocus(float xRatio, float yRatio);

Clip management

// Get the clip manager.
AliyunIClipManager manager = AliyunIVideoRecorder.getClipManager();

// Set the maximum recording duration (total duration, not for a single clip).
manager.setMaxDuration(int maxDurationMs);

// Set the minimum recording duration (total duration, not for a single clip).
manager.setMinDuration(int minDurationMs);

// Delete the last clip.
manager.deletePart();

// Delete a clip at a specific index.
manager.deletePart(int index);

// Delete all clips.
manager.deleteAllPart();

// Get the total duration of all clips.
manager.getDuration();

// Get the total number of clips.
manager.getPartCount();

// Get the list of clip file paths.
manager.getVideoPathList();

Configure effects

Optionally, configure recording effects such as retouching, filters, and animated stickers. For more information about the parameters used in the code, see the API reference in Related classes.

Filters

You can create custom filters. For more information about how to create a filter, see Filters and transitions.

// Apply a filter.
AliyunICameraCapture.applyFilter(EffectFilter effectFilter);

// Remove the filter.
AliyunICameraCapture.removeFilter();

Animated filters

// Apply an animated filter.
AliyunICameraCapture.applyAnimationFilter(EffectFilter effectFilter);

// Remove an animated filter.
AliyunICameraCapture.removeAnimationFilter(EffectFilter effctFilter);

Static stickers

// Add a static sticker.
AliyunICameraCapture.addImage(EffectImage effctImage);

// Remove a static sticker.
AliyunICameraCapture.removeImage(EffectImage effctImage);

// Update the position of a static sticker.
AliyunICameraCapture.setEffectView(float xRatio,float yRatio,float widthRatio,float heightRatio,EffectBase effectBase);

Animated stickers

You can create custom animated stickers. For more information about how to create an animated sticker, see Animations.

// Add an animated sticker.
AliyunICameraCapture.addPaster(EffectPaster effectPaster,float sx,float sy,float sw,float sh,float rotation,boolean flip);

// Remove an animated sticker.
AliyunICameraCapture.removePaster(EffectPaster effectPaster);

// Update the position of an animated sticker.
AliyunICameraCapture.setEffectView(float xRatio,float yRatio,float widthRatio,float heightRatio,EffectBase effectBase);

Advanced retouching

The video recording module includes basic built-in retouching and supports third-party SDKs such as the Alibaba Cloud Queen SDK and FaceUnity. Built-in retouching only adjusts the retouching level, while third-party SDKs provide advanced capabilities including retouching, face shaping, makeup, filters, and stickers.

  • Built-in retouching

    // Enable or disable retouching.
    AliyunICameraCapture.setBeautyStatus(boolean on);
    
    // Set the retouching level.
    AliyunICameraCapture.setBeautyLevel(int level);
  • Retouching SDKs

    To use effects from a third-party retouching SDK, you must first obtain the necessary permissions and integrate that SDK with the short video SDK.

    • For information about how to integrate the Alibaba Cloud Queen SDK, see Alibaba Cloud Queen SDK. For sample code that shows how to configure effects, see Usage examples.

    • For information about how to purchase, integrate, and use FaceUnity, see FaceUnity.

    Third-party retouching SDKs require a camera texture ID and raw camera frame data to apply effects. The following code shows how to obtain this data.

    • Get camera texture ID data

      AliyunICameraCapture.setOnTextureIdCallback(new OnTextureIdCallBack() {
                  @Override
                  public int onTextureIdBack(int textureId, int textureWidth, int textureHeight, float[] matrix) {
                      if (mBeautyInterface != null) {
                          return mBeautyInterface.onTextureIdBack(textureId, textureWidth, textureHeight, matrix, mControlView.getCameraType().getType());
                      }
                      return textureId;
                  }
      
                  @Override
                  public int onScaledIdBack(int scaledId, int textureWidth, int textureHeight, float[] matrix) {
                      return scaledId;
                  }
      
                  @Override
                  public void onTextureDestroyed() {
                      // To destroy GL resources for custom rendering (third-party rendering):
                      // In SDK versions earlier than 3.7.8, you can use GLSurfaceView.queueEvent.
                      // In SDK versions 3.7.8 and later, destroy GL resources in this callback.
                      if (mBeautyInterface != null) {
                          mBeautyInterface.release();
                          mBeautyInterface = null;
                      }
                  }
              });
    • Get raw camera frame data

      AliyunICameraCapture.setOnFrameCallback(new OnFrameCallback() {
                  @Override
                  public void onFrameBack(byte[] bytes, int width, int height, Camera.CameraInfo info) {
                      // The callback provides raw NV21 data. This data is primarily used for advanced retouching with FaceUnity.
                      if (mBeautyInterface != null) {
                          mBeautyInterface.onFrameBack(bytes, width, height, info);
                      }
                  }
      
                  @Override
                  public Camera.Size onChoosePreviewSize(List<Camera.Size> supportedPreviewSizes,
                                                         Camera.Size preferredPreviewSizeForVideo) {
                      return null;
                  }
      
                  @Override
                  public void openFailed() {
                  }
              });

Other features

Add background music, watermarks, and speed ramping. For more information about the parameters used in the code, see the API reference in Related classes.

Speed ramping

// Set the recording speed.
AliyunIVideoRecorder.setRate(float rate);

Mute

// Mute the microphone.
AliyunIVideoRecorder.setMute(boolean isMute);

Autoclear

// Controls whether recorded video clips are automatically cleared when you exit the recording interface.
AliyunIVideoRecorder.setIsAutoClearClipVideos(boolean isAutoClear);

Background music

// Set the background music.
AliyunIVideoRecorder.setMusic(String path,long startTime,long duration);

// Remove the background music.
AliyunIVideoRecorder.removeMusic();

Watermark

// Add a watermark.
AliyunIVideoRecorder.addWaterMark(EffectImage effectImage);

// Remove the watermark.
AliyunIVideoRecorder.removeWaterMark(EffectImage effectImage);

Configure the background

// Set the background color.
AliyunIVideoRecorder.setBackgroundColor(int color);

// Set the background image from a bitmap.
AliyunIVideoRecorder.setBackgroundImage(Bitmap bitmap);

// Set the background image from a file path.
AliyunIVideoRecorder.setBackgroundImage(String path);

// Clear the background.
AliyunIVideoRecorder.clearBackground();

Sample code

import android.os.Bundle;
import android.os.Environment;
import android.view.SurfaceView;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.aliyun.svideosdk.common.struct.common.AliyunLayoutParam;
import com.aliyun.svideosdk.common.struct.common.VideoDisplayMode;
import com.aliyun.svideosdk.common.struct.encoder.VideoCodecs;
import com.aliyun.svideosdk.common.struct.recorder.CameraType;
import com.aliyun.svideosdk.multirecorder.AliyunICameraCapture;
import com.aliyun.svideosdk.multirecorder.AliyunIVideoRecorder;
import com.aliyun.svideosdk.multirecorder.AliyunIViewCapture;
import com.aliyun.svideosdk.multirecorder.OnVideoRecordListener;
import com.aliyun.svideosdk.multirecorder.config.AliyunVideoRecorderConfig;
import com.aliyun.svideosdk.multirecorder.impl.AliyunMultiRecorderCreator;

import java.io.File;

/**
 * A demo for multi-source recording.
 * Note: You must grant storage, camera, and microphone permissions before you start.
 */
public class MultiRecorderDemo extends AppCompatActivity {

    private AliyunIVideoRecorder mRecorder;
    private TextView mBtnRecord;
    private SurfaceView mCameraPreview;
    private View mViewRecord;
    private View mViewRecordIcon;

    private boolean mIsRecording = false;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.multi_recoder_demo_layout);
        initViews();
        initRecorder();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mRecorder.startPreview();
    }

    @Override
    protected void onPause() {
        super.onPause();
        stopRecording();
        mRecorder.stopPreview();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mRecorder.destroy();
    }

    private String getSaveDir() {
        String saveDir = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "MultiRecord";
        File dirFile = new File(saveDir);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }
        return saveDir;
    }

    private void initViews() {
        mBtnRecord = findViewById(R.id.record_btn);
        mCameraPreview = findViewById(R.id.multi_record_camera);
        mViewRecord = findViewById(R.id.multi_record_view);
        mViewRecordIcon = mViewRecord.findViewById(R.id.record_view_icon);
    }

    private void initRecorder() {
        // 1. Configure parameters.
        AliyunVideoRecorderConfig config = AliyunVideoRecorderConfig.builder()
                // Required parameters
                .videoWidth(1080)
                .videoHeight(1920)
                .outputPath(getSaveDir() + File.separator + System.currentTimeMillis() + ".mp4")
                // Optional parameters
                .videoCodecs(VideoCodecs.H264_HARDWARE) // Use hardware encoding.
                .build();

        // 2. Create a recording instance.
        mRecorder = AliyunMultiRecorderCreator.getVideoRecorderInstance(this, config);

        // 3. Configure video sources.
        // 3.1 Configure camera recording.
        addCameraCapture();
        // 3.2 Configure view recording.
        addViewCapture();
        // 3.3 Prepare the video sources.
        mRecorder.prepare();

        // 4. Configure callbacks.
        mRecorder.setOnRecordListener(new OnVideoRecordListener() {
            @Override
            public void onProgress(long duration) {

            }

            @Override
            public void onFinish(String outputPath) {

            }

            @Override
            public void onClipComplete(boolean validClip, long clipDuration) {

            }

            @Override
            public void onMaxDuration() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        stopRecording();
                    }
                });
            }

            @Override
            public void onError(int errorCode) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        stopRecording();
                    }
                });
            }

            @Override
            public void onInitReady() {

            }
        });
    }

    private void addCameraCapture() {
        // 1. Configure the layout for the left side.
        AliyunLayoutParam cameraLayoutParam = AliyunLayoutParam.builder()
                .layoutLevel(1)
                .centerX(0.25f)
                .centerY(0.5f)
                .widthRatio(0.5f)
                .heightRatio(1.0f)
                .displayMode(VideoDisplayMode.FILL)
                .build();

        // 2. Add the video source.
        AliyunICameraCapture cameraCapture = mRecorder.getVideoCapture().addCameraCapture(cameraLayoutParam);

        // 3. Configure the video source.
        // Set the camera preview view. This is a required property.
        cameraCapture.setDisplayView(mCameraPreview);

        // Optional settings
        cameraCapture.setCamera(CameraType.BACK);// Use the rear camera.
    }

    private void addViewCapture() {
        // 1. Configure the layout for the right side.
        AliyunLayoutParam viewLayoutParam = AliyunLayoutParam.builder()
                .layoutLevel(2)
                .centerX(0.75f)
                .centerY(0.5f)
                .widthRatio(0.5f)
                .heightRatio(1.0f)
                .displayMode(VideoDisplayMode.FILL)
                .build();

        // 2. Add the video source.
        // Get the current recording view.
        View recordView = mViewRecord;
        AliyunIViewCapture viewCapture = mRecorder.getVideoCapture().addViewCapture(viewLayoutParam, recordView);

        // 3. Configure the video source (optional).
    }

    private void startRecording() {
        if (mIsRecording) {
            return;
        }
        mIsRecording = true;
        mRecorder.startRecording();
    }

    private void stopRecording() {
        if (!mIsRecording) {
            return;
        }
        mRecorder.stopRecording();
        mIsRecording = false;
    }

    public void onClickRecord(View view) {
        if (mIsRecording) {
            stopRecording();
            mBtnRecord.setText("Start recording");
        } else {
            startRecording();
            mBtnRecord.setText("Stop recording");
        }
    }
}

Sample XML configuration

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/demo_root_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <SurfaceView
            android:id="@+id/multi_record_camera"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <FrameLayout
            android:id="@+id/multi_record_view"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <TextView
                android:id="@+id/record_view_icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="View recording" />

        </FrameLayout>

    </LinearLayout>

    <Button
        android:id="@+id/record_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginLeft="5dp"
        android:layout_marginBottom="5dp"
        android:onClick="onClickRecord"
        android:text="Start recording" />

</RelativeLayout>