Todos os produtos
Search
Central de documentação

ApsaraVideo Live:Processamento de dados de vídeo brutos

Última atualização: Jun 30, 2026

Durante uma sessão de comunicação em tempo real (RTC), utilize observadores de vídeo para acessar e processar dados de vídeo brutos em diferentes estágios do pipeline de processamento do SDK.

Casos de uso

Os cenários mais comuns para processamento personalizado de dados de vídeo incluem:

  1. Retoque personalizado: capture o fluxo de vídeo local e processe-o com um SDK de retoque de terceiros antes de enviá-lo aos demais usuários no canal.

  2. Edição personalizada de vídeo: modifique o fluxo de vídeo em várias etapas do pipeline de processamento, aplicando efeitos especiais, marcas d'água, recortes ou cortes. O fluxo alterado pode ser transmitido ou salvo posteriormente.

  3. Visualização ou monitoramento de fluxo: obtenha o fluxo de vídeo em distintos pontos do pipeline para monitoramento e pré-visualização local ou na nuvem, permitindo verificar a qualidade do conteúdo, a transmissão e a reprodução em tempo real.

Antes de começar

Certifique-se de ter concluído as seguintes tarefas:

Como funciona

Captura de vídeo:

image

Decodificação e renderização:

image

O SDK ARTC oferece pontos de observação em diversas fases do pipeline de processamento de vídeo.

Esses pontos correspondem aos seguintes callbacks:

  • Ponto de observação 1: obtenha os dados originais do quadro de vídeo, sem redimensionamento, por meio de onCaptureVideoSample (iOS) ou onLocalVideoSample (Android) logo após a captura.

  • Ponto de observação 2: acesse os dados anteriores à codificação através de onPreEncodeVideoSample.

  • Ponto de observação 3: receba os dados decodificados via onRemoteVideoSample.

  • Ponto de observação 4: obtenha o contexto OpenGL (glcontext) usando onTextureCreate e vincule-o ao seu módulo de retoque.

  • Ponto de observação 5: receba os dados de textura atualizados por meio de onTextureUpdate para aplicar seus efeitos.

  • Ponto de observação 6: receba uma notificação para liberar o glcontext através de onTextureDestroy.

Nota
  • Nos pontos de observação 1, 2 e 3, retornar true indica que você modificou os dados. Retornar false mantém os dados originais inalterados.

  • No ponto de observação 5, o método deve retornar um textureId válido. Retornar um novo textureId instrui o SDK a usar sua textura modificada para codificação e processamento. Caso não realize nenhum processamento personalizado, retorne o textureId original.

Implementação

Android

Callbacks de quadros de vídeo

1. Registre os callbacks

Para receber dados de vídeo brutos, implemente a interface AliRtcEngine.AliRtcVideoObserver e registre sua instância chamando o método registerVideoSampleObserver().

public abstract void registerVideoSampleObserver(AliRtcVideoObserver observer);

2. Especifique os pontos de observação

O SDK define quais callbacks acionar com base na máscara de bits retornada por este método.

 public enum AliRtcVideoObserPosition{
        /*! Locally captured video data, corresponds to the onLocalVideoSample callback */
        AliRtcPositionPostCapture(1),
        /*! Decoded remote video data, corresponds to the onRemoteVideoSample callback */
        AliRtcPositionPreRender(2),
        /*! Pre-encoding video data, corresponds to the onPreEncodeVideoSample callback */
        AliRtcPositionPreEncoder(4);
    }

public int onGetObservedFramePosition(){
    return AliRtcVideoObserPosition.AliRtcPositionPostCapture.getValue() | AliRtcVideoObserPosition.AliRtcPositionPreRender.getValue();
}

3. Especifique o formato de saída

/**
 * @brief Video data format
 */
public enum AliRtcVideoFormat{
        AliRtcVideoFormatUNKNOW(-1),
        AliRtcVideoFormatBGRA(0),
        AliRtcVideoFormatI420(1),
        AliRtcVideoFormatNV21(2),
        AliRtcVideoFormatNV12 (3),
        AliRtcVideoFormatRGBA(4),
        AliRtcVideoFormatI422 (5),
        AliRtcVideoFormatARGB(6),
        AliRtcVideoFormatABGR (7),
        AliRtcVideoFormatRGB24(8),
        AliRtcVideoFormatBGR24(9),
        AliRtcVideoFormatRGB565(10),
        AliRtcVideoFormatTextureOES(11),
        AliRtcVideoFormatTexture2D(12),
        AliRtcVideoFormatH264(13),
        AliRtcVideoFormatH265(14),
        AliRtcVideoFormatFile(15);
};

/*
* The SDK calls this method after you call AliRtcEngine::registerVideoSampleObserver.
*/

/**
* @brief Video data output format
* @return The desired video output format. See {@link AliRtcVideoFormat}.
*/
public AliRtcVideoFormat onGetVideoFormatPreference(){
    return AliRtcVideoFormat.AliRtcVideoFormatI420;
}

4. Especifique o alinhamento de memória

public enum AliRtcVideoObserAlignment{
        /*! Keep the original video width (default) */
        AliRtcAlignmentDefault(0),
        /*! Align the stride to a multiple of 2 bytes */
        AliRtcAlignmentEven(1),
        /*! Align the stride to a multiple of 4 bytes */
        AliRtcAlignment4(2),
        /*! Align the stride to a multiple of 8 bytes */
        AliRtcAlignment8(3),
        /*! Align the stride to a multiple of 16 bytes */
        AliRtcAlignment16(4);
};

/*
* The SDK calls this method after you call AliRtcEngine::registerVideoSampleObserver.
*/

public int onGetVideoAlignment(){
  return AliRtcVideoObserAlignment.AliRtcAlignmentDefault.getValue();
}

5. Especifique se deseja aplicar efeito espelhado

public boolean onGetObserverDataMirrorApplied(){
  return false;
}

6. Implemente os callbacks

/*
* Return true to write your modifications back to the SDK's processing pipeline. 
* This is required if you modify AliRtcVideoSample.data.
*/

@Override
public boolean onLocalVideoSample(AliRtcEngine.AliRtcVideoSourceType sourceType, AliRtcEngine.AliRtcVideoSample videoSample) {
  boolean ret = false;
  /*
  * Process locally captured data.
  */
  return ret;
}

@Override
public boolean onRemoteVideoSample(String userId, AliRtcEngine.AliRtcVideoSourceType sourceType, AliRtcEngine.AliRtcVideoSample videoSample) {
  /*
  * Process the decoded data from a remote user.
  */
  return false;
}

@Override
public boolean onPreEncodeVideoSample(AliRtcEngine.AliRtcVideoSourceType aliVideoSourceType, AliRtcEngine.AliRtcVideoSample videoSample) {
  boolean ret = false;
  /*
  * Process pre-encoding data.
  */
  return false ;
}

7. Cancele o registro do callback

Quando não for mais necessário observar os quadros de vídeo, cancele o registro do observador para evitar processamento desnecessário.

unregisterVideoSampleObserver

Processamento de texturas

Todos os callbacks relacionados a texturas são executados na mesma thread dedicada do OpenGL. Para utilizá-los, implemente a interface AliRtcTextureObserver.

Pré-requisitos

Ative a captura e a codificação de texturas definindo as opções abaixo durante a inicialização do mecanismo.

String extras = "{\"user_specified_camera_texture_capture\":\"TRUE\",\"user_specified_texture_encode\":\"TRUE\" }";
_engine = AliRtcEngine.getInstance(getApplicationContext(), extras);

1. Registre o callback de textura

public abstract void registerLocalVideoTextureObserver(AliRtcTextureObserver observer);

2. Implemente o callback

Callback após criação do contexto OpenGL
@Override
public void onTextureCreate(long context) {
      context_ = context ;
      Log.d(TAG, "texture context: "+context_+" create!") ;
}
Callback de atualização de textura OpenGL
@Override
public int onTextureUpdate(int textureId, int width, int height, AliRtcEngine.AliRtcVideoSample videoSample) {
    /*
    *  Process the textureid.
    */
     ++log_ref ;
     return textureId;
}       
Callback de destruição do contexto OpenGL
@Override
public void onTextureDestroy() {
     Log.d(TAG, "texture context: "+context_+" destory!") ;
}

3. Cancele o registro do callback de textura

public abstract void  unRegisterLocalVideoTextureObserver();

iOS

Callbacks de quadros de vídeo

1. Registre os callbacks

Implemente AliRtcEngineDelegate e chame registerVideoSampleObserver para registrar os callbacks de quadros de vídeo.

registerVideoSampleObserver

2. Especifique os pontos de observação

O SDK define quais callbacks acionar com base na máscara de bits retornada por este método.

/**
 * @brief Video data output position
 */
typedef NS_ENUM(NSInteger, AliRtcVideoObserPosition) {
    /** Captured video data, corresponds to onCaptureVideoSample callback */
    AliRtcPositionPostCapture = 1 << 0,
    /** Decoded remote video data, corresponds to onRemoteVideoSample callback */
    AliRtcPositionPreRender = 1 << 1,
    /** Pre-encoding video data, corresponds to onPreEncodeVideoSample callback */
    AliRtcPositionPreEncoder = 1 << 2,
};

/*
* The SDK calls this method after you call AliRtcEngine::registerVideoSampleObserver.
*/

- (NSInteger)onGetVideoObservedFramePosition;

3. Especifique o formato de saída

Para receber dados de vídeo como CVPixelBuffer, defina a opção user_specified_native_buffer_observer como TRUE no campo extra ao criar o mecanismo.

/**
 * @brief Video data format
 */
typedef NS_ENUM(NSInteger, AliRtcVideoFormat) {
    AliRtcVideoFormat_UNKNOW = -1,
    AliRtcVideoFormat_BGRA = 0,
    AliRtcVideoFormat_I420,
    AliRtcVideoFormat_NV21,
    AliRtcVideoFormat_NV12,
    AliRtcVideoFormat_RGBA,
    AliRtcVideoFormat_I422,
    AliRtcVideoFormat_ARGB,
    AliRtcVideoFormat_ABGR,
    AliRtcVideoFormat_RGB24,
    AliRtcVideoFormat_BGR24,
    AliRtcVideoFormat_RGB565,
    AliRtcVideoFormat_TextureOES,
    AliRtcVideoFormat_Texture2D,
    AliRtcVideoFormat_H264,
    AliRtcVideoFormat_H265,
    AliRtcVideoFormat_File,
    AliRtcVideoFormat_cvPixelBuffer,
};

/*
* The SDK calls this method after you call AliRtcEngine::registerVideoSampleObserver.
*/

- (AliRtcVideoFormat)onGetVideoFormatPreference {
    return AliRtcVideoFormat_I420;
}

4. Especifique o alinhamento de memória

/**
 * @brief Video output width alignment
 */
typedef enum {
    /** Keep the original video width (default) */
    AliRtcAlignmentDefault = 0,
    /** Align the stride to a multiple of 2 bytes */
    AliRtcAlignmentEven = 1,
    /** Align the stride to a multiple of 4 bytes */
    AliRtcAlignment4 = 2,
    /** Align the stride to a multiple of 8 bytes */
    AliRtcAlignment8 = 3,
    /** Align the stride to a multiple of 16 bytes */
    AliRtcAlignment16 = 4,
} AliRtcVideoObserAlignment;

/*
* The SDK calls this method after you call AliRtcEngine::registerVideoSampleObserver.
*/

- (AliRtcVideoObserAlignment)onGetVideoAlignment {
  return AliRtcAlignmentDefault;
}

5. Especifique se deseja aplicar efeito espelhado

/**
 * @brief Specifies whether the output video data should be mirrored.
 * @return
 * - YES: Mirrored
 * - NO: Not mirrored (default)
 */
 
 /*
* The SDK calls this method after you call AliRtcEngine::registerVideoSampleObserver.
*/
- (BOOL)onGetObserverDataMirrorApplied {
  return FLASE ;
}

6. Implemente os callbacks

/**
 * @brief Callback for subscribed local video data.
 * @param videoSource The type of video stream.
 * @param videoSample The raw video data.
 * @return
 * - YES: Write the modified data back to the SDK. On iOS and macOS, writing back data by returning YES is only supported for the I420 and CVPixelBuffer formats.
 * - NO: Do not write data back to the SDK.
*/
- (BOOL)onCaptureVideoSample:(AliRtcVideoSource)videoSource videoSample:(AliRtcVideoDataSample *_Nonnull)videoSample {
  /*
   * do....
   */
   return FALSE ;
}

/**
 * @brief Callback for subscribed local pre-encoding video data.
 * @param videoSource The type of video stream.
 * @param videoSample The raw video data.
 * @return
 * - YES: Write the modified data back to the SDK. On iOS and macOS, writing back data by returning YES is only supported for the I420 and CVPixelBuffer formats.
 * - NO: Do not write data back to the SDK.
*/
- (BOOL)onPreEncodeVideoSample:(AliRtcVideoSource)videoSource videoSample:(AliRtcVideoDataSample *_Nonnull)videoSample {
  /*
   * do....
   */
   return FALSE ;
}

/**
 * @brief Callback for subscribed remote video data.
 * @param uid The user ID.
 * @param videoSource The type of video stream.
 * @param videoSample The raw video data.
 * @return
 * - YES: Write the modified data back to the SDK. On iOS and macOS, writing back data by returning YES is only supported for the I420 and CVPixelBuffer formats.
 * - NO: Do not write data back to the SDK.
*/
- (BOOL)onRemoteVideoSample:(NSString *_Nonnull)uid videoSource:(AliRtcVideoSource)videoSource videoSample:(AliRtcVideoDataSample *_Nonnull)videoSample {

  /*
   * do....
   */
  return TRUE ;
}

7. Cancele o registro do callback

Quando não for mais necessário observar os quadros de vídeo, cancele o registro do observador para evitar processamento desnecessário.

unregisterVideoSampleObserver

Processamento de texturas

Todos os callbacks relacionados a texturas são executados na mesma thread dedicada do OpenGL.

1. Registre o callback de textura

registerLocalVideoTexture

2. Implemente o callback

Callback após criação do contexto OpenGL
/**
 * @brief Callback for OpenGL context creation.
 * @param context The OpenGL context.
 * @note This callback is triggered when the SDK's internal OpenGL context is created.
 */
- (void)onTextureCreate:(void *_Nullable)context {
    [[beautifyMoudle_ shared] create];
}
Callback de atualização de textura OpenGL
/**
 * @brief Callback for OpenGL texture updates.
 * @param textureId The ID of the OpenGL texture.
 * @param width The width of the texture.
 * @param height The height of the texture.
 * @param videoSample The video frame data, see {@link AliRtcVideoDataSample}.
 * @return The ID of the processed OpenGL texture.
 * @note
 * - The callback is invoked after the SDK uploads the current video frame to a GPU texture. If you registered the OpenGL texture observer, you can process the texture and return the texture ID to be used downstream after your processing.
 * - You must return a valid texture ID,If you do not modify the texture, return the incoming textureId unchanged.
 * The callback's textureId is in AliRtcVideoFormat_Texture2D format.
 */
- (int)onTextureUpdate:(int)textureId width:(int)width height:(int)height videoSample:(AliRtcVideoDataSample *_Nonnull)videoSample {
    
    if ( [[beautifyMoudle_ shared] enabled] == NO) {
        return textureId;
    }
    
    int texId = [[beautifyMoudle_ shared] processTextureToTexture:textureId Width:width Height:height];
    
    if(texId<0) {
       texId = textureId;
    }
    return texId;
}
Callback de destruição do contexto OpenGL
- (void)onTextureDestory
{
    if (self.settingModel.chnnelType == ChannelTypePrimary) {
        [[beautifyMoudle_ shared] destroy];
    }
    
}

3. Cancele o registro do callback de textura

unregisterLocalVideoTexture