全部產品
Search
文件中心

ApsaraVideo Live:自訂視頻採集

更新時間:Sep 23, 2025

功能介紹

ARTC SDK 提供了靈活的自訂視頻採集功能,支援客戶根據業務需求自主管理視頻採集裝置。

建議優先使用 RTC SDK 內部採集,如果對視頻品質、裝置相容性或採集流程有特殊要求而無法使用 SDK 內部採集,那麼自訂視頻採集為你提供更強的擴充性和定製能力。

範例程式碼

Android端自訂視頻採集Android/ARTCExample/AdvancedUsage/src/main/java/com/aliyun/artc/api/advancedusage/CustomVideoCaptureAndRender/CustomVideoCaptureActivity.java

iOS端自訂視頻採集iOS/ARTCExample/AdvancedUsage/CustomVideoCapture/CustomVideoCpatureVC.swift

前提條件

在設定視頻配置之前,請確保達成以下條件:

功能實現

1. 關閉 SDK 內部採集

可以調用enableLocalVideo介面關閉 SDK 內部採集。

Android

/* 關閉內部採集 */
mAliRtcEngine.enableLocalVideo(false);

/* 開啟內部採集,阿里內部預設狀態是true,所以如果不需要控制的情況下不需要調用此api */
mAliRtcEngine.enableLocalVideo(true);

iOS

/* 關閉內部採集 */
[_engine enableLocalVideo:NO];

/* 開啟內部採集,阿里內部預設狀態是true,所以如果不需要控制的情況下不需要調用此api */
[_engine enableLocalVideo:YES];

2. 設定自訂採集視頻源

調用 setExternalVideoSource 設定自訂採集視頻源,主要參數:

  • enable:控制是否開啟。

  • useTexture:是否使用紋理輸入。

  • streamType:相機流或螢幕畫面分享流,表示 sdk 替換哪一路流。

  • renderMode:處理模式,外部輸入視頻源寬高比和推流profile不一致時,會按照對應的rendermode做對應處理。

Android

YUV 輸入

/* YUV方式輸入 */
/* 開啟外部採集,這裡以camera流為例,具體可以根據sourceType指定,渲染模式也可以根據需要指定 */
mAliRtcEngine.setExternalVideoSource(true,false, AliRtcVideoTrackCamera,AliRtcRenderModeAuto );

/* 關閉外部採集,這裡以camera流為例,具體可以根據sourceType指定 */
mAliRtcEngine.setExternalVideoSource(false,false, AliRtcVideoTrackCamera,AliRtcRenderModeAuto );

紋理輸入

/* 紋理方式輸入 */
/* 開啟外部採集,這裡以camera流為例,具體可以根據sourceType指定,渲染模式也可以根據需要指定 */
mAliRtcEngine.setExternalVideoSource(true,true, AliRtcVideoTrackCamera,AliRtcRenderModeAuto );

/* 關閉外部採集,這裡以camera流為例,具體可以根據sourceType指定 */
mAliRtcEngine.setExternalVideoSource(false,true, AliRtcVideoTrackCamera,AliRtcRenderModeAuto );

iOS

/* 開啟外部採集,這裡以camera流為例,具體可以根據sourceType指定,渲染模式也可以根據需要指定 */
[_engine setExternalVideoSource:YES sourceType:AliRtcVideosourceCameraType renderMode:AliRtcRenderModeAuto]; 

/* 關閉外部採集,這裡以camera流為例,具體可以根據sourceType指定 */
[_engine setExternalVideoSource:NO sourceType:AliRtcVideosourceCameraType renderMode:AliRtcRenderModeAuto]; 

3. 向 SDK 發送資料

在採集到視頻

Android

YUV方式輸入樣本:

/* 以YUV(I420)格式為例 */
int width = 720;
int height = 1280;
AliRtcEngine.AliRtcVideoFormat videoformat = AliRtcEngine.AliRtcVideoFormat.AliRtcVideoFormatI420;
int[] lineSize = {width, width / 2, width / 2, 0};
int frameLength = width * height * 3 / 2;
byte[] buffer = new byte[frameLength];

/* 構造傳入SDK的資料對象 */
AliRtcEngine.AliRtcRawDataFrame rawDataFrame
        = new AliRtcEngine.AliRtcRawDataFrame(buffer,
                                             videoformat,
                                             width, 
                                             height, 
                                             lineSize, 
                                             0, 
                                             buffer.length);

/* 調用API傳入資料對象 */
int ret = mAliRtcEngine.pushExternalVideoFrame(rawDataFrame, AliRtcVideoTrackCamera);
if (ret != 0) {
    /* 列印下錯誤資訊 */
}

紋理方式輸入樣本:

/* 以紋理格式為例 */
/* 構造opengl的環境 */
private static EglBase14 createEglBase14(EGLContext shareEglContext) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        EglBase14.Context eglBase14Context = shareEglContext == null ? null : new EglBase14.Context(shareEglContext);
        EglBase14 eglBase14 = new EglBase14(eglBase14Context, EglBase.CONFIG_PIXEL_BUFFER);
        try {
            eglBase14.createDummyPbufferSurface();
            eglBase14.makeCurrent();
        } catch (RuntimeException e) {
            eglBase14.release();
            Log.e(TAG, "CreateEGLBase14Context, failed, " + e.getMessage());
        }
        return eglBase14;
    }
    return null;
}

/* 構造傳入的資料內容 */
float[] transformMatrix = {
  1, 0, 0, 0,
  0, 1, 0, 0,
  0, 0, 1, 0,
  0, 0, 0, 1
};
int frameWidth = 720; /* 映像的寬 */
int frameHeight = 1280; /* 映像的高 */
int textureID = xxx; /* 使用者自己的紋理id */

AliRtcEngine.AliRtcRawDataFrame aliRawDataFrame 
  = new AliRtcEngine.AliRtcRawDataFrame(textureID,
                                        AliRtcVideoFormatTexture2D,
                                        frameWidth, 
                                        frameHeight, 
                                        transformMatrix, 
                                        0, 
                                        0, 
                                        frameWidth, 
                                        frameHeight, 
                                        mEglBase14.getEglContext());

/* 調用API傳入資料對象 */
int ret = mAliRtcEngine.pushExternalVideoFrame(aliRawDataFrame, AliRtcVideoTrackCamera);
if (ret != 0) {
    /* 列印下錯誤資訊 */
}

iOS

/* 按照自己的資料格式填寫以下內容,下面以I420格式為例 */
AliRtcVideoDataSample *dataSample = [[AliRtcVideoDataSample alloc] init];
dataSample.dataPtr = (long)yuv_read_data;
dataSample.format = AliRtcVideoFormat_I420;
dataSample.type = AliRtcBufferType_Raw_Data;
dataSample.width = width;
dataSample.height = height;
dataSample.strideY = width;
dataSample.strideU = width/2;
dataSample.strideV = width/2;
dataSample.dataLength = dataSample.strideY * dataSample.height * 3/2;

/* 調用API傳入資料對象 */
int ret = [self.engine pushExternalVideoFrame:dataSample sourceType:AliRtcVideosourceCameraType];
if (ret != 0) {
    /* 列印下錯誤資訊 */
}