Configure a captura de vídeo, a codificação, o controle da câmera, a pré-visualização, o espelhamento e a renderização com o ARTC SDK.
Recursos
Durante uma chamada de vídeo ou transmissão interativa, configure a resolução de captura, a resolução de codificação, a taxa de quadros, a taxa de bits, o modo de espelhamento e o modo de renderização.
-
Resolução:
Resolução de captura: resolução do vídeo proveniente de um dispositivo de captura, como uma câmera.
Resolução de codificação: resolução do vídeo codificado.
Taxa de bits: número de bits transmitidos por segundo (bps).
Taxa de quadros: número de quadros exibidos por segundo (fps).
Configurações adequadas de resolução, taxa de quadros e taxa de bits melhoram a qualidade do vídeo. Os modos de espelhamento e renderização controlam a exibição do vídeo.
Código de exemplo
Uso básico de vídeo para Android: Android/ARTCExample/BasicUsage/src/main/java/com/aliyun/artc/api/basicusage/VideoBasicUsage/VideoBasicUsageActivity.java.
Uso básico de vídeo para iOS: iOS/ARTCExample/BasicUsage/VideoBasicUsage/VideoBasicUsageVC.swift.
Uso básico de vídeo para Harmony: Harmony/ARTCExample/entry/src/main/ets/pages/basicusage/VideoBasicUsage.ets.
Pré-requisitos
Antes de definir as configurações de vídeo:
Tenha uma conta Alibaba Cloud com um aplicativo ARTC (Crie um aplicativo). Você precisa do App ID e da App Key disponíveis no console do ApsaraVideo Live.
Integre o ARTC SDK e implemente chamadas básicas de áudio e vídeo. Consulte Baixe/Integração do SDK e Implementar uma chamada de áudio e vídeo.
Implementação
1. Defina configuração de captura da câmera
Use setCameraCapturerConfiguration para definir a direção da câmera e a taxa de quadros de captura.
Chame este método antes de iniciar a câmera, por exemplo, antes de chamar startPreview ou joinChannel (que inicia a câmera automaticamente).
Chamar
enableLocalVideo(false)para desativar a captura da câmera libera os recursos da câmera. Em seguida, redefina a configuração.
Definição do método:
/**
* @brief Sets the capture preference.
* @param cameraCapturerConfiguration The camera capture settings.
* - preference:
* - {@link AliRtcCaptureOutputPreference#ALIRTC_CAPTURER_OUTPUT_PREFERENCE_PREVIEW} Preview priority. Prioritizes video preview quality.
* - {@link AliRtcCaptureOutputPreference#ALIRTC_CAPTURER_OUTPUT_PREFERENCE_PERFORMANCE} Performance priority. Prioritizes device performance by selecting a resolution close to that of the published stream.
* - {@link AliRtcCaptureOutputPreference#ALIRTC_CAPTURER_OUTPUT_PREFERENCE_AUTO} Auto. The SDK automatically adjusts the capture resolution.
* - cameraDirection: The camera direction. You can set it to the front or rear camera.
* @return
* - 0: Success.
* - A non-zero value: Failure.
* @note You must call this method before you start the camera, for example, before you call {@link #startPreview} or {@link #joinChannel}.
*/
public abstract int setCameraCapturerConfiguration(AliEngineCameraCapturerConfiguration cameraCapturerConfiguration);
Parâmetros:
|
Parâmetro |
Tipo |
Descrição |
|
|
Preferência de captura.
|
|
|
|
Direção da câmera (frontal ou traseira). |
|
|
|
int |
Taxa de quadros de captura. Valor padrão: -1. O SDK usa o fps da configuração de codificação (o padrão interno do SDK é 15). |
|
|
Resolução de captura de vídeo.
|
|
|
|
int |
(Apenas Android) Indica se deve ativar a codificação de textura. |
|
|
int |
(Apenas Android) Indica se deve ativar a captura de textura para a câmera. |
Código de exemplo:
Android
AliRtcEngine.AliEngineCameraCapturerConfiguration config = new AliRtcEngine.AliEngineCameraCapturerConfiguration();
config.preference = AliRtcEngine.AliRtcCaptureOutputPreference.ALIRTC_CAPTURER_OUTPUT_PREFERENCE_AUTO;
config.cameraCaptureProfile = AliRtcEngine.AliRtcCameraCaptureProfile.ALIRTC_CAMERA_CAPTURER_PROFILE_DEFAULT;
config.cameraDirection = AliRtcEngine.AliRtcCameraDirection.CAMERA_FRONT;
config.fps = 30;
mAliRtcEngine.setCameraCapturerConfiguration(config);
iOS
let cameraCaptureConfig: AliRtcCameraCapturerConfiguration = AliRtcCameraCapturerConfiguration()
cameraCaptureConfig.preference = .auto
cameraCaptureConfig.cameraCaptureProfile = .profileDefault
cameraCaptureConfig.cameraDirection = .front
cameraCaptureConfig.fps = 30
engine.setCameraCapturerConfiguration(cameraCaptureConfig)
Harmony
const cameraConfig = new AliRtcCameraCaptureConfiguration();
cameraConfig.preference = AliRtcCaptureOutputPreference.AliRtcCaptureOutputPreferenceAuto;
cameraConfig.cameraDirection = AliRtcCameraDirection.AliRtcCameraDirectionFront;
cameraConfig.cameraCaptureProfile = AliRtcCameraCaptureProfile.AliRtcCameraCaptureProfileDefault;
cameraConfig.fps = 30;
this.rtcEngine?.setCameraCaptureConfiguration(cameraConfig);
macOS
AliRtcCameraCapturerConfiguration *configuration = [[AliRtcCameraCapturerConfiguration alloc] init];
configuration.preference = (AliRtcCaptureOutputPreference)outputBox.indexOfSelectedItem;
configuration.cameraCaptureProfile = AliRtcCameraCaptureProfileDefault;
configuration.fps = 15;
[self.engine setCameraCapturerConfiguration:configuration];
Windows
AliEngineCameraCapturerConfiguration config ;
config.preference = AliEngineCaptureOutputPreferencePerformance;
config.cameraCaptureProfile = AliEngineCameraCaptureProfileDefault;
config.fps = 30;
mAliRtcEngine->setCameraCapturerConfiguration(config);
2. Defina configuração do codificador de vídeo
Use setVideoEncoderConfiguration para definir a resolução de vídeo, a taxa de quadros, a taxa de bits e o intervalo de quadros-chave.
Chame setVideoEncoderConfiguration antes ou depois de entrar em um canal. Se for chamado apenas uma vez por chamada, faça-o antes de entrar.
Parâmetros:
|
Parâmetro |
Tipo |
Descrição |
|
|
Resolução de vídeo. Padrão: 640x480. Máximo: 1920x1080. |
|
|
|
int |
Taxa de quadros de codificação de vídeo. Padrão: 15. Máximo: 30. |
|
|
int |
Taxa de bits de vídeo em kbps. Padrão: 512. Defina como 0 para cálculo automático com base na resolução e na taxa de quadros. Se a taxa de bits estiver fora do intervalo recomendado, o SDK a ajustará automaticamente. Os intervalos recomendados estão nos comentários do código de exemplo. |
|
|
int |
Intervalo de quadros-chave em milissegundos. Padrão: 0 (controlado pelo SDK). Nota
Este parâmetro é necessário para transmissão interativa e interoperabilidade com mini programas. |
|
|
boolean |
Indica se deve forçar a geração estrita de quadros-chave no intervalo definido. Padrão:
|
|
|
Modo de espelhamento para o vídeo codificado. Nota
Você também pode usar o método |
|
|
|
Modo de orientação do vídeo codificado.
|
|
|
|
Ângulo de rotação do vídeo codificado. Valores válidos: 0, 90, 180 e 270. |
|
|
|
Tipo de codec.
|
|
|
|
Formato de codificação de vídeo. Formatos suportados: padrão do sistema, H.264 e H.265. |
|
|
|
int |
Indica se deve forçar um I-frame antes de enviar uma mensagem SEI. Valores válidos: |
Código de exemplo:
Android
AliRtcEngine.AliRtcVideoEncoderConfiguration aliRtcVideoEncoderConfiguration = new AliRtcEngine.AliRtcVideoEncoderConfiguration();
aliRtcVideoEncoderConfiguration.dimensions = new AliRtcEngine.AliRtcVideoDimensions(720, 1280);
aliRtcVideoEncoderConfiguration.frameRate = 20;
aliRtcVideoEncoderConfiguration.bitrate = 1200;
aliRtcVideoEncoderConfiguration.keyFrameInterval = 2000;
aliRtcVideoEncoderConfiguration.orientationMode = AliRtcVideoEncoderOrientationModeAdaptive;
mAliRtcEngine.setVideoEncoderConfiguration(aliRtcVideoEncoderConfiguration);
iOS
let config = AliRtcVideoEncoderConfiguration()
config.dimensions = CGSize(width: 720, height: 1280)
config.frameRate = 20
config.bitrate = 1200
config.keyFrameInterval = 2000
config.orientationMode = AliRtcVideoEncoderOrientationMode.adaptive
engine.setVideoEncoderConfiguration(config)
Harmony
const encoderConfig = new AliRtcVideoEncoderConfiguration();
const dimensions = new AliRtcVideoDimensions();
dimensions.width = 720;
dimensions.height = 1280;
encoderConfig.dimensions = dimensions;
encoderConfig.bitrate = 1200;
encoderConfig.frameRate = 20;
encoderConfig.orientationMode = AliRtcVideoEncoderOrientationMode.AliRtcVideoEncoderOrientationModeAdaptive;
encoderConfig.rotationMode = AliRtcRotationMode.AliRtcRotationMode_0;
// Call the RTC engine to set the configuration.
this.rtcEngine?.setVideoEncoderConfiguration(encoderConfig);
macOS
AliRtcVideoEncoderConfiguration *config = [[AliRtcVideoEncoderConfiguration alloc] init];
config.dimensions = CGSizeMake(720, 1280);
config.frameRate = 20;
config.bitrate = 1200
config.keyFrameInterval = 2000
config.orientationMode = AliRtcVideoEncoderOrientationModeAdaptive;
[self.engine setVideoEncoderConfiguration:config];
Windows
AliEngineVideoEncoderConfiguration aliRtcVideoEncoderConfiguration ;
aliRtcVideoEncoderConfiguration.dimensions = AliRtcVideoDimensions(720, 1280);
aliRtcVideoEncoderConfiguration.frameRate = AliEngineFrameRateFps20;
aliRtcVideoEncoderConfiguration.bitrate = 1200;
aliRtcVideoEncoderConfiguration.keyFrameInterval = 2000;
aliRtcVideoEncoderConfiguration.orientationMode = AliEngineVideoEncoderOrientationModeAdaptive;
mAliRtcEngine->SetVideoEncoderConfiguration(aliRtcVideoEncoderConfiguration);
3. Alternar câmeras
O SDK usa a câmera frontal por padrão. Chame setCameraCaptureConfiguration antes de iniciar a captura para especificar uma câmera diferente ou switchCamera para alternar durante a execução.
/**
* @brief Switches between the front and rear cameras.
* @return
* - `0`: Success
* - Non-zero: Failure
* @note This API is available on iOS and Android only.
*/
public abstract int switchCamera();
Código de exemplo:
Android
mSwitchCameraBtn.setOnClickListener(v -> {
if(mAliRtcEngine != null) {
mAliRtcEngine.switchCamera();
}
});
iOS
@IBAction func onCameraDirectionChanged(_ sender: UISegmentedControl) {
rtcEngine?.switchCamera()
}
Harmony
this.rtcEngine.switchCamera();
4. Controlar a câmera
Duas APIs controlam a câmera: muteLocalCamera e enableLocalVideo.
|
API |
|
|
|
Funcionamento |
Envia quadros pretos em vez de vídeo. |
Interrompe a captura da câmera e libera os recursos do dispositivo. |
|
Comportamento |
A pré-visualização local permanece ativa, mas os usuários remotos veem uma tela preta. |
A pré-visualização local e o vídeo remoto congelam no último quadro. |
|
Características |
|
|
4,1. Silenciar ou reativar vídeo local
muteLocalCamera mantém o pipeline de captura, codificação e transmissão de vídeo ativo, mas envia quadros pretos para usuários remotos. A pré-visualização local não é afetada.
/**
* @brief Mutes or unmutes the local video stream.
* @param mute true: Sends black frames. false: Resumes sending normal video frames.
* @param track The video track to mute. Only {@link AliRtcVideoTrack#AliRtcVideoTrackCamera} is supported.
* @return
* - 0: Success.
* - A non-zero value: Failure.
* @note This method sends black frames while the local preview remains unaffected. The video capture pipeline continues to run.
*/
public abstract int muteLocalCamera(boolean mute, AliRtcVideoTrack track);
/**
* @brief Occurs when a remote user mutes or unmutes their video stream.
* @param uid The ID of the user who called muteLocalCamera.
* @param isMute
* - true: The user is sending black frames.
* - false: The user is sending normal video frames.
*/
public void onUserVideoMuted(String uid ,boolean isMute){}
Android
Silencie ou reative o fluxo de vídeo:
if(!isMutedCamera) {
mAliRtcEngine.muteLocalCamera(true, AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackCamera);
mPublishVideoBtn.setText(R.string.resume_pub_video);
isMutedCamera = true;
} else {
mAliRtcEngine.muteLocalCamera(false, AliRtcEngine.AliRtcVideoTrack.AliRtcVideoTrackCamera);
mPublishVideoBtn.setText(R.string.stop_pub_video);
isMutedCamera = false;
}
Ouça o callback remoto:
@Override
public void onUserVideoMuted(String uid ,boolean isMute){
handler.post(new Runnable() {
@Override
public void run() {
ToastHelper.showToast(VideoBasicUsageActivity.this, "remote user uid:" + uid + " camera mute:" + isMute, Toast.LENGTH_SHORT);
}
});
}
iOS
Silencie ou reative o fluxo de vídeo:
@IBAction func onVideoMuteSwitched(_ sender: UISwitch) {
if sender.isOn {
// Send black frames.
rtcEngine?.muteLocalCamera(true, for: AliRtcVideoTrack.camera)
} else {
// Resume sending normal video frames.
rtcEngine?.muteLocalCamera(false, for: AliRtcVideoTrack.camera)
}
}
Ouça o callback remoto:
extension VideoBasicUsageVC: AliRtcEngineDelegate {
func onUserVideoMuted(_ uid: String, videoMuted isMute: Bool) {
"onUserVideoMuted: user id \(uid) video muted: \(isMute)".printLog()
}
}
Harmony
Silencie ou reative o fluxo de vídeo:
private toggleVideoSending(): void {
if (this.rtcEngine) {
if (!this.isMutedCamera) {
this.rtcEngine.muteLocalCamera(true, AliRtcVideoTrack.AliRtcVideoTrackCamera);
this.isMutedCamera = true;
} else {
this.rtcEngine.muteLocalCamera(false, AliRtcVideoTrack.AliRtcVideoTrackCamera);
this.isMutedCamera = false;
}
}
}
Ouça o callback remoto:
listener.onUserVideoMuted((uid : string, isMute : boolean) => {
console.info(`User ${uid}'s video has been ${isMute ? 'muted' : 'unmuted'}`);
});
macOS
Silencie ou reative o fluxo de vídeo:
[self.engine muteLocalCamera:self.muteLocalCamera forTrack:AliRtcVideoTrackCamera];
Ouça o callback remoto:
- (void)onUserVideoMuted:(NSString *_Nullable)uid videoMuted:(BOOL)isMute {
NSLog(@"uid=%@ mute:%d", uid, isMute );
}
Windows
Silencie ou reative o fluxo de vídeo:
if ( mMuteLocalCamera == TRUE) {
mAliRtcEngine->MuteLocalCamera(TRUE, AliRtcVideoTrackCamera);
} else {
mAliRtcEngine->MuteLocalCamera(FALSE, AliRtcVideoTrackCamera);
}
Ouça o callback remoto:
void CTutorialDlg::OnUserVideoMuted(const char* uid, bool isMute)
{
// Find the corresponding user view to update its status.
PartUserDlg *partUserView = mRemotePartDlgs[uid];
if (nullptr != partUserView)
{
partUserView->muteStream = isMute;
updateRemoteParticipants();
}
}
4,2. Ative ou desative captura de vídeo
enableLocalVideo controla a câmera. Desativá-lo interrompe a captura e a transmissão, liberando o dispositivo.
/**
* @brief Enables or disables local video capture.
* @param enabled
* - true: Enables local video capture.
* - false: Disables local video capture.
* @return
* - 0: Success.
* - < 0: Failure.
* @note This feature is enabled by default. Listen for the {@link AliRtcEngineNotify#onUserVideoEnabled} callback to be notified of changes to a remote user's video capture status.
*/
public abstract int enableLocalVideo(boolean enabled);
/**
* @brief Occurs when a remote user enables or disables their local video capture.
* @param uid The ID of the user who called enableLocalVideo.
* @param isEnable
* - true: The user enabled local video capture.
* - false: The user disabled local video capture.
*/
public void onUserVideoEnabled(String uid, boolean isEnable){}
Android
Ative ou desative a captura de vídeo:
mCameraSwitchBtn = findViewById(R.id.camera_control_btn);
mCameraSwitchBtn.setOnClickListener(v -> {
if(mAliRtcEngine != null) {
if(isEnableCamera) {
mAliRtcEngine.enableLocalVideo(false);
isEnableCamera = false;
mCameraSwitchBtn.setText(R.string.camera_on);
} else {
mAliRtcEngine.enableLocalVideo(true);
isEnableCamera = true;
mCameraSwitchBtn.setText(R.string.camera_off);
}
}
});
Ouça o callback remoto:
@Override
public void onUserVideoEnabled(String uid, boolean isEnable) {
handler.post(new Runnable() {
@Override
public void run() {
ToastHelper.showToast(VideoBasicUsageActivity.this, "remote user uid:" + uid + " camera enable:" + isEnable, Toast.LENGTH_SHORT);
}
});
}
iOS
Ative ou desative a captura de vídeo:
@IBAction func onCameraSwitch(_ sender: UISwitch) {
if sender.isOn {
rtcEngine?.enableLocalVideo(true)
} else {
rtcEngine?.enableLocalVideo(false)
}
updateCaptureUIVisibility()
}
Ouça o callback remoto:
extension VideoBasicUsageVC: AliRtcEngineDelegate {
func onUserVideoEnabled(_ uid: String?, videoEnabled isEnable: Bool) {
"onUserVideoEnabled: user id \(uid ?? "invalid uid") video enable: \(isEnable)".printLog()
}
}
Harmony
Ative ou desative a captura de vídeo:
private toggleCamera(): void {
if (this.rtcEngine) {
if (this.isEnableCamera) {
this.rtcEngine.enableLocalVideo(false);
this.isEnableCamera = false;
} else {
this.rtcEngine.enableLocalVideo(true);
this.isEnableCamera = true;
}
}
}
Ouça o callback remoto:
listener.onUserVideoEnabled((uid : string, isEnable : boolean) => {
console.info(`User ${uid}'s video has been ${isEnable ? 'enabled' : 'disabled'}`);
});
macOS
Ative ou desative a captura de vídeo:
[self.engine enableLocalVideo:isOpen];
Ouça o callback remoto:
- (void)onUserVideoEnabled:(NSString *_Nullable)uid videoEnabled:(BOOL)isEnable) {
NSLog(@"uid=%@ enabled:%d", uid, isEnable );
}
Windows
Ative ou desative a captura de vídeo:
mbLocalVideo = !mbLocalVideo;
mAliRtcEngine->EnableLocalVideo(mbLocalVideo);
Ouça o callback remoto:
void CTutorialDlg::OnUserVideoEnabled(const char* uid, bool isEnable) {
// Find the corresponding user view to update its status.
PartUserDlg *partUserView = mRemotePartDlgs[uid];
if (nullptr != partUserView)
{
partUserView->enableVideo = isEnable;
updateRemoteParticipants();
}
}
5. Iniciar ou parar pré-visualização
Use startPreview e stopPreview para controlar a pré-visualização local.
Nota:
Você deve chamar
setLocalViewConfigpara definir uma visualização de renderização antes de iniciar a pré-visualização.Por padrão, o SDK inicia a pré-visualização ao entrar em um canal. Se precisar iniciar a pré-visualização antes de entrar no canal, chame
startPreview.Após parar a pré-visualização, a visualização local congela no último quadro.
Sequência de chamadas de API
Código de exemplo:
Android
Inicie a pré-visualização:
private void startPreview() {
if (mAliRtcEngine != null) {
ViewGroup.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
// Set the local view.
if (mLocalVideoCanvas == null) {
mLocalVideoCanvas = new AliRtcEngine.AliRtcVideoCanvas();
SurfaceView localSurfaceView = mAliRtcEngine.createRenderSurfaceView(VideoBasicUsageActivity.this);
if (localSurfaceView != null) {
localSurfaceView.setZOrderOnTop(true);
localSurfaceView.setZOrderMediaOverlay(true);
fl_local.addView(localSurfaceView, layoutParams);
mLocalVideoCanvas.view = localSurfaceView;
try {
mAliRtcEngine.setLocalViewConfig(mLocalVideoCanvas, AliRtcVideoTrackCamera);
} catch (Exception e) {
e.printStackTrace(); // Handle potential exceptions
}
}
}
// Start the preview.
mAliRtcEngine.startPreview();
}
}
Pare a pré-visualização:
mAliRtcEngine.stopPreview();
mAliRtcEngine.setLocalViewConfig(null, AliRtcVideoTrackCamera);
mAliRtcEngine.leaveChannel();
mAliRtcEngine.destroy();
mAliRtcEngine = null;
iOS
Inicie a pré-visualização:
func startPreview() {
let seatView = self.createSeatView(uid: self.userId)
let canvas = AliVideoCanvas()
canvas.view = seatView.canvasView
canvas.renderMode = .auto
canvas.mirrorMode = .onlyFrontCameraPreviewEnabled
canvas.rotationMode = ._0
self.rtcEngine?.setLocalViewConfig(canvas, for: AliRtcVideoTrack.camera)
self.rtcEngine?.startPreview()
}
Pare a pré-visualização:
self.rtcEngine?.stopPreview()
self.rtcEngine?.setLocalViewConfig(nil, for: AliRtcVideoTrack.camera)
self.rtcEngine?.leaveChannel()
AliRtcEngine.destroy()
self.rtcEngine = nil
Harmony
Inicie a pré-visualização:
if (!this.aliRtcVideoCanvas) {
this.aliRtcVideoCanvas = new AliRtcVideoCanvas();
}
this.aliRtcVideoCanvas.surfaceId = this.localSurfaceId;
this.aliRtcVideoCanvas.renderMode = AliRtcRenderMode.AliRtcRenderModeAuto;
this.aliRtcVideoCanvas.mirrorMode = AliRtcRenderMirrorMode.AliRtcRenderMirrorModeAllMirror;
this.rtcEngine.setLocalViewConfig(
this.aliRtcVideoCanvas,
this.componentController,
AliRtcVideoTrack.AliRtcVideoTrackCamera
);
this.rtcEngine.startPreview();
Pare a pré-visualização:
this.rtcEngine.stopPreview();
Mac
Inicie a pré-visualização:
NSView * newView = [self createSeatView:uid];
AliVideoCanvas *canvas = [[AliVideoCanvas alloc] init];
canvas.renderMode = AliRtcRenderModeAuto;
canvas.view = newView;
canvas.mirrorMode = AliRtcRenderMirrorModeAllDisabled;
canvas.rotation = AliRtcRotationMode_0;
[self.engine setLocalViewConfig:canvas forTrack:AliRtcVideoTrackCamera];
[self.engine startPreview];
Pare a pré-visualização:
[self.engine stopPreview];
[self.engine setLocalViewConfig:nil, AliRtcVideoTrackCamera];
[self.engine leaveChannel];
[self.engine destroy];
_engine = nil ;
Windows
Inicie a pré-visualização:
AliEngineVideoCanvas canvas;
canvas.renderMode = AliEngineRenderModeAuto;
canvas.rotation = AliEngineRotationMode_0;
canvas.displayView = hLocalWnd;
mAliRtcEngine->SetLocalViewConfig(canvas, AliEngineVideoTrackCamera);
mAliRtcEngine->StartPreview();
Pare a pré-visualização:
mAliRtcEngine->StopPreview();
mAliRtcEngine->SetLocalViewConfig(nullptr, AliEngineVideoTrackCamera);
mAliRtcEngine->LeaveChannel();
mAliRtcEngine->Destroy();
mAliRtcEngine = nullptr;
6. Defina o modo de espelhamento
setVideoMirrorMode controla o espelhamento para a pré-visualização local e o fluxo publicado. Chame-o durante a execução em chamadas de vídeo ou transmissões ao vivo.
/**
* @brief Sets the mirror mode for the local video preview and the published stream.
* @param mirrorMode The mirror mode to set.
* @return
* - 0: Success.
* - <0: Failure.
* - AliRtcErrInner: An internal SDK state error occurred. Verify that the SDK instance was created successfully.
*
* @note
* - You can call this method to change the mirror mode at runtime, either before or after you join a channel. The SDK records the state and applies the setting when the preview and encoding are active.
* - This method overrides the mirror settings configured in `setLocalViewConfig` and `setVideoEncoderConfiguration`.
* - This method's settings duplicate those in `setLocalViewConfig` and `setVideoEncoderConfiguration`. Use only one method to configure mirroring.
*/
public abstract int setVideoMirrorMode(AliRtcVideoPipelineMirrorMode mirrorMode);
Modos de espelhamento:
|
Valor do Enum |
Descrição |
|
|
Espelhamento desativado tanto para pré-visualização quanto para codificação. |
|
|
Ativa o espelhamento tanto para a pré-visualização quanto para a codificação (padrão). |
|
|
Ativa o espelhamento apenas para a pré-visualização. |
|
|
Ativa o espelhamento apenas para o fluxo publicado. |
Código de exemplo:
Android
mMirrorSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
if(mAliRtcEngine != null) {
AliRtcEngine.AliRtcVideoPipelineMirrorMode mirrorMode = AliRtcEngine.AliRtcVideoPipelineMirrorMode.values()[position];
mAliRtcEngine.setVideoMirrorMode(mirrorMode);
}
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
iOS
let mirrorMode: AliRtcVideoPipelineMirrorMode = {
switch row {
case 0: return .bothMirror
case 1: return .noMirror
case 2: return .onlyPreviewMirror
case 3: return .onlyPublishMirror
default: return .bothMirror
}
}()
self.rtcEngine?.setVideoMirrorMode(mirrorMode)
Harmony
const mirrorMode = AliRtcVideoPipelineMirrorMode.AliRtcVideoPipelineMirrorModeBothMirror;
this.rtcEngine.setVideoMirrorMode(mirrorMode);
macOS
[self.engine setVideoMirrorMode:AliRtcVideoPipelineMirrorModeOnlyPreviewMirror];
Windows
mAliRtcEngine->setVideoMirrorMode(AliEngineVideoPipelineMirrorModeOnlyPreviewMirror);
7. Defina a visualização de renderização
Chame setLocalViewConfig ou setRemoteViewConfig para definir uma visualização de renderização antes de exibir o vídeo.
// Sets the render view for the local preview.
public abstract int setLocalViewConfig(AliRtcVideoCanvas viewConfig, AliRtcVideoTrack track);
// Sets the render view for a specified remote user.
public abstract int setRemoteViewConfig(AliRtcVideoCanvas canvas, String uid, AliRtcVideoTrack track);
Parâmetros de AliRtcVideoCanvas:
|
Parâmetro |
Tipo |
Descrição |
|
|
|
Visualização de exibição (obrigatório). |
|
|
|
Modo de renderização.
|
|
|
|
Modo de espelhamento.
|
|
|
|
Modo de rotação. Valores válidos: 0, 90, 180 e 270 graus. |
|
|
|
Cor de fundo no formato RGB hexadecimal, por exemplo, 0x000000. |
|
|
|
(Apenas Android) ID da textura, usado para exibir uma textura OpenGL ES de terceiros. |
|
|
|
(Apenas Android) Largura da textura. |
|
|
|
(Apenas Android) Altura da textura. |
|
|
|
(Apenas Android) Contexto OpenGL ES compartilhado para a textura. |
Código de exemplo:
7,1. Defina a visualização de renderização local
Android
mLocalVideoCanvas = new AliRtcEngine.AliRtcVideoCanvas();
// Get and set the SurfaceView.
SurfaceView localSurfaceView = mAliRtcEngine.createRenderSurfaceView(VideoChatActivity.this);
localSurfaceView.setZOrderOnTop(true);
localSurfaceView.setZOrderMediaOverlay(true);
FrameLayout fl_local = findViewById(R.id.fl_local);
fl_local.addView(localSurfaceView, layoutParams);
mLocalVideoCanvas.view = localSurfaceView;
// Set the local preview view.
mAliRtcEngine.setLocalViewConfig(mLocalVideoCanvas, AliRtcVideoTrackCamera);
mAliRtcEngine.startPreview();
iOS
let videoView = self.createVideoView(uid: self.userId)
let canvas = AliVideoCanvas()
canvas.view = videoView.canvasView
canvas.renderMode = .auto
canvas.mirrorMode = .onlyFrontCameraPreviewEnabled
canvas.rotationMode = ._0
self.rtcEngine?.setLocalViewConfig(canvas, for: AliRtcVideoTrack.camera)
self.rtcEngine?.startPreview()
macOS
NSView * newView = [self createSeatView:uid];
AliVideoCanvas *canvas = [[AliVideoCanvas alloc] init];
canvas.renderMode = AliRtcRenderModeAuto;
canvas.view = newView;
canvas.mirrorMode = AliRtcRenderMirrorModeAllDisabled;
canvas.rotation = AliRtcRotationMode_0;
[self.engine setLocalViewConfig:canvas forTrack:AliRtcVideoTrackCamera];
[self.engine startPreview];
Windows
AliEngineVideoCanvas canvas;
/* Window handle */
canvas.view = mHWnd;
canvas.mirrorMode = AliEngineRenderMirrorModeAllNoMirror;
mAliRtcEngine->setLocalViewConfig(canvas, AliEngineVideoTrackCamera);
Harmony
// Create or reuse the canvas.
if (!this.aliRtcVideoCanvas) {
this.aliRtcVideoCanvas = new AliRtcVideoCanvas();
}
this.aliRtcVideoCanvas.surfaceId = this.localSurfaceId;
this.aliRtcVideoCanvas.renderMode = AliRtcRenderMode.AliRtcRenderModeAuto;
this.aliRtcVideoCanvas.mirrorMode = AliRtcRenderMirrorMode.AliRtcRenderMirrorModeAllMirror;
this.rtcEngine.setLocalViewConfig(
this.aliRtcVideoCanvas,
this.componentController,
AliRtcVideoTrack.AliRtcVideoTrackCamera
);
this.rtcEngine.startPreview();
7,2. Defina a visualização de renderização remota
Android
@Override
public void onRemoteTrackAvailableNotify(String uid, AliRtcEngine.AliRtcAudioTrack audioTrack, AliRtcEngine.AliRtcVideoTrack videoTrack){
handler.post(new Runnable() {
@Override
public void run() {
if(videoTrack == AliRtcVideoTrackCamera) {
SurfaceView surfaceView = mAliRtcEngine.createRenderSurfaceView(VideoChatActivity.this);
surfaceView.setZOrderMediaOverlay(true);
FrameLayout fl_remote = findViewById(R.id.fl_remote);
if (fl_remote == null) {
return;
}
fl_remote.addView(surfaceView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
AliRtcEngine.AliRtcVideoCanvas remoteVideoCanvas = new AliRtcEngine.AliRtcVideoCanvas();
remoteVideoCanvas.view = surfaceView;
mAliRtcEngine.setRemoteViewConfig(remoteVideoCanvas, uid, AliRtcVideoTrackCamera);
} else if(videoTrack == AliRtcVideoTrackNo) {
FrameLayout fl_remote = findViewById(R.id.fl_remote);
fl_remote.removeAllViews();
mAliRtcEngine.setRemoteViewConfig(null, uid, AliRtcVideoTrackCamera);
}
}
});
}
iOS
func onRemoteTrackAvailableNotify(_ uid: String, audioTrack: AliRtcAudioTrack, videoTrack: AliRtcVideoTrack) {
"onRemoteTrackAvailableNotify uid: \(uid) audioTrack: \(audioTrack) videoTrack: \(videoTrack)".printLog()
// Handles the availability of a remote user's stream.
if audioTrack != .no {
let videoView = self.videoViewList.first { $0.uidLabel.text == uid }
if videoView == nil {
_ = self.createVideoView(uid: uid)
}
}
if videoTrack != .no {
var videoView = self.videoViewList.first { $0.uidLabel.text == uid }
if videoView == nil {
videoView = self.createVideoView(uid: uid)
}
let canvas = AliVideoCanvas()
canvas.view = videoView!.canvasView
canvas.renderMode = .auto
canvas.mirrorMode = .onlyFrontCameraPreviewEnabled
canvas.rotationMode = ._0
self.rtcEngine?.setRemoteViewConfig(canvas, uid: uid, for: AliRtcVideoTrack.camera)
}
else {
self.rtcEngine?.setRemoteViewConfig(nil, uid: uid, for: AliRtcVideoTrack.camera)
}
if audioTrack == .no && videoTrack == .no {
self.removeVideoView(uid: uid)
self.rtcEngine?.setRemoteViewConfig(nil, uid: uid, for: AliRtcVideoTrack.camera)
}
}
macOS
- (void)onRemoteTrackAvailableNotify:(NSString *)uid audioTrack:(AliRtcAudioTrack)audioTrack videoTrack:(AliRtcVideoTrack)videoTrack {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Remote user stream information callback");
__weak typeof(self)weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
__strong typeof(weakSelf)strongSelf = self;
if (videoTrack == AliRtcVideoTrackNo) {
// [self removeRemoteViewWithUid:uid];
} else if(videoTrack == AliRtcVideoTrackCamera) {
[strongSelf addRemoteViewWithUid:uid videoTrack:AliRtcVideoTrackCamera];
} else if(videoTrack == AliRtcVideoTrackScreen) {
[strongSelf addRemoteViewWithUid:uid videoTrack:AliRtcVideoTrackScreen];
} else if(videoTrack == AliRtcVideoTrackBoth) {
[strongSelf addRemoteViewWithUid:uid videoTrack:AliRtcVideoTrackBoth];
}
});
});
}
Windows
virtual void OnRemoteTrackAvailableNotify(const char *uid, AliEngineAudioTrack audioTrack, AliEngineVideoTrack videoTrack) {
AliEngineVideoCanvas remote_canvas;
if (videoTrack == AliEngineVideoTrackCamera
|| videoTrack == AliEngineVideoTrackBoth) {
RECT rect;
::GetWindowRect(mHWnd, &rect);
remote_canvas.displayView = remoteView;
remote_canvas.renderMode = AliEngineRenderModeAuto;
mAliRtcEngine->SetRemoteViewConfig(remote_canvas,uid,AliEngineVideoTrackCamera);
} else {
mAliRtcEngine->SetRemoteViewConfig(remote_canvas, uid, AliEngineVideoTrackCamera);
}
}
Harmony
// Remote audio/video stream availability notification
listener.onRemoteTrackAvailableNotify((userId: string, audioTrack: AliRtcAudioTrack,
videoTrack: AliRtcVideoTrack) => {
console.info(`Remote audio/video stream available: userId=${userId}, videoTrack=${videoTrack}`);
// Configure the remote view based on the video stream type.
if (videoTrack === AliRtcVideoTrack.AliRtcVideoTrackCamera) {
// Camera stream is available.
this.viewRemoteVideo(userId, AliRtcVideoTrack.AliRtcVideoTrackCamera);
this.removeRemoteVideo(userId, AliRtcVideoTrack.AliRtcVideoTrackScreen);
} else if (videoTrack === AliRtcVideoTrack.AliRtcVideoTrackScreen) {
// Screen sharing stream is available.
this.viewRemoteVideo(userId, AliRtcVideoTrack.AliRtcVideoTrackScreen);
this.removeRemoteVideo(userId, AliRtcVideoTrack.AliRtcVideoTrackCamera);
} else if (videoTrack === AliRtcVideoTrack.AliRtcVideoTrackBoth) {
// Dual streams are available (camera + screen sharing).
this.viewRemoteVideo(userId, AliRtcVideoTrack.AliRtcVideoTrackCamera);
this.viewRemoteVideo(userId, AliRtcVideoTrack.AliRtcVideoTrackScreen);
} else if (videoTrack === AliRtcVideoTrack.AliRtcVideoTrackNo) {
// No video stream.
this.removeAllRemoteVideo(userId);
}
});