All Products
Search
Document Center

ApsaraVideo Live:Manage video capture devices

Last Updated:Mar 26, 2026

Video capture device management is a core feature of Real-Time Communication (RTC). The ARTC SDK provides extensive APIs for managing devices. As implementations vary significantly across platforms, this topic describes the video device management features provided by the RTC engine.

Feature overview

The ARTC SDK gives developers comprehensive control over video capture devices. You can fine-tune camera parameters, such as zoom, exposure, and manual/auto focus modes, on platforms such as iOS and Android to significantly improve video capture quality.

Sample code

Android video capture device management: Android/ARTCExample/BasicUsage/src/main/java/com/aliyun/artc/api/basicusage/CameraCommonControl/CameraActivity.java.

iOS video capture device management: iOS/ARTCExample/BasicUsage/CameraCommonSetting/CameraCommonControlVC.swift.

Harmony video capture device management: Harmony/ARTCExample/entry/src/main/ets/pages/basicusage/CameraPage.ets.

Prerequisites

  • You have an Alibaba Cloud account and have created a Real-Time Communication (RTC) application. For more information, see Create an application. You have obtained an AppID and an AppKey from the ApsaraVideo Live console.

  • SDK integration and basic feature implementation:

    • You have integrated the ARTC SDK into your project and implemented basic Real-Time Communication (RTC) features. For more information, see Integrate the SDK and Implement an audio and video call.

    • The camera has been started, for example, by starting a preview with startPreview or joining a channel with joinChannel.

Implementation

Set camera zoom

The ARTC SDK allows you to control the camera zoom.

API reference

/**
 * @brief Sets the camera zoom.
 * @param zoom The zoom factor. The value ranges from 1 to the maximum zoom value supported by the camera.
 * @return
 * - 0: Success.
 * - A non-zero value: Failure.
 * @note This API is available only on iOS and Android.
 */
public abstract int setCameraZoom(float zoom);

 /**
 * @brief Gets the maximum zoom factor of the camera.
 * @return The maximum zoom factor of the camera.
 */
public abstract float GetCameraMaxZoomFactor();

/**
 * @brief Gets the current zoom factor of the camera.
 * @return The current zoom factor of the camera.
 */
public abstract float GetCurrentZoom();

Examples

Android

// Get zoom information.
private void initZoomSeekBar() {
    if (mAliRtcEngine != null) {
        zoomSeekBar.setEnabled(true);
        // Get the maximum zoom value.
        float maxZoom = mAliRtcEngine.GetCameraMaxZoomFactor();
        float currZoom = mAliRtcEngine.GetCurrentZoom();
        // Set the SeekBar range (from 1.0 to maxZoom, with a step of 0.1).
        if(maxZoom >= 1.0) {
            int maxProgress = (int)((maxZoom - 1) * 10);
            zoomSeekBar.setMax(maxProgress);
            int currProgress = (int)((currZoom - 1) * 10);
            zoomSeekBar.setProgress(currProgress);
        } else{
            zoomSeekBar.setEnabled(false);
        }
    }
}
// Set the zoom.
zoomSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
        if(mAliRtcEngine != null) {
            float newZoom = (float)((i+10) / 10.0);
            mAliRtcEngine.setCameraZoom(newZoom);
            zoomTextView.setText(String.format("%.1f", newZoom));
        }
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }
});

iOS

// Get zoom information.
self.cameraZoomSlider.isEnabled = true
let maxZoom = rtcEngine.getCameraMaxZoomFactor()
let currZoom = rtcEngine.getCurrentZoom()
"Get maxZoom=\(maxZoom), currZoom=\(currZoom)".printLog()

self.cameraZoomSlider.minimumValue = 1.0
if maxZoom > 1.0 {
    self.cameraZoomSlider.maximumValue = maxZoom
} else {
    self.cameraZoomSlider.isEnabled = false
}
if currZoom >= 1.0 && currZoom <= maxZoom {
    self.cameraZoomSlider.value = currZoom
    self.cameraZoomValueLabel.text = String(format: "%.1f", self.cameraZoomSlider.value)
}
else {
    self.cameraZoomSlider.value = self.cameraZoomSlider.minimumValue
    self.cameraZoomValueLabel.text = "\(self.cameraZoomSlider.minimumValue)"
}

// Set the zoom.
@IBOutlet weak var cameraZoomSlider: UISlider!
@IBOutlet weak var cameraZoomValueLabel: UILabel!
@IBAction func onCameraZoomChanged(_ sender: UISlider) {
    let currValue = sender.value
    self.cameraZoomValueLabel.text = String(format: "%.1f", currValue)
    self.rtcEngine?.setCameraZoom(currValue)
}

Harmony

private handleZoomChange(value: number): void {
  if (!this.rtcEngine) {
    return;
  }

  // Calculate the zoom value based on the progress: zoom = 1.0 + (value / 10.0).
  const newZoom = 1.0 + (value / 10.0);

  // Clamp the zoom value between 1.0 and 10.0.
  const clampedZoom = Math.max(1.0, Math.min(10.0, newZoom));

  this.rtcEngine.setCameraZoom(clampedZoom);
  this.zoomValue = clampedZoom.toFixed(1);

  console.info(`Set zoom: ${clampedZoom}`);
}

Set camera exposure

The ARTC SDK allows you to set the camera exposure to control the image brightness.

API reference

/**
 * @brief Sets the camera exposure.
 * @param exposure The exposure value.
 * @return
 * - 0: Success.
 * - A non-zero value: Failure.
 */
public abstract int SetExposure(float exposure);

/**
 * @brief Gets the current camera exposure.
 * @return The current camera exposure.
 */
public abstract float GetCurrentExposure();

/**
 * @brief Gets the minimum camera exposure.
 * @return The minimum camera exposure.
 */
public abstract float GetMinExposure();

/**
 * @brief Gets the maximum camera exposure.
 * @return The maximum camera exposure.
 */
public abstract float GetMaxExposure();

Examples

Android

// Get exposure information.
private void initExposureSeekBar() {
    if (mAliRtcEngine != null) {
        exposureSeekBar.setEnabled(true);
        // Get the maximum exposure value.
        float maxExposure = mAliRtcEngine.GetMaxExposure();
        // Get the minimum exposure value.
        float minExposure = mAliRtcEngine.GetMinExposure();
        float currExposure = mAliRtcEngine.GetCurrentExposure();
        if(maxExposure > minExposure) {
            // Reset the SeekBar range.
            int maxProgress = (int)((maxExposure - minExposure) * 10);
            exposureSeekBar.setMax(maxProgress);
            int currProgress = (int)((currExposure - minExposure) * 10);
            exposureSeekBar.setProgress(currProgress);
        } else {
            exposureSeekBar.setEnabled(false);
        }
    }
}
// Set the exposure.
exposureSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
        if(mAliRtcEngine != null) {
            float minExposure = mAliRtcEngine.GetMinExposure();
            float newExposure = minExposure + (float)(i / 10.0);

            mAliRtcEngine.SetExposure(newExposure);
            exposureTextView.setText(String.format("% .1f", newExposure));
        }
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }
});

iOS

// Get device exposure information.
self.cameraExposureSlider.isEnabled = true
let minExposure = rtcEngine.getMinExposure()
let maxExposure = rtcEngine.getMaxExposure()
let currExposure = rtcEngine.getCurrentExposure()
"Get minExposure=\(minExposure), maxExposure=\(maxExposure), currExposure=\(currExposure)".printLog()
if maxExposure > minExposure {
    self.cameraExposureSlider.minimumValue = minExposure
    self.cameraExposureSlider.maximumValue = maxExposure
} else {
    self.cameraExposureSlider.isEnabled = false
}
if currExposure >= minExposure && currExposure <= maxExposure {
    self.cameraExposureSlider.value = currExposure
    self.cameraExposureValueLabel.text = String(format: "%.1f", self.cameraExposureSlider.value)
}
else {
    self.cameraExposureSlider.value = self.cameraExposureSlider.minimumValue
    self.cameraExposureValueLabel.text = "\(self.cameraExposureSlider.minimumValue)"
}
// Set the exposure.
@IBOutlet weak var cameraExposureValueLabel: UILabel!
@IBOutlet weak var cameraExposureSlider: UISlider!
@IBAction func onCameraExposureChanged(_ sender: UISlider) {
    let currValue = sender.value
    self.cameraExposureValueLabel.text = String(format: "%.1f", currValue)
    self.rtcEngine?.setExposure(currValue)
}

Harmony

// Handle exposure change.
private handleExposureChange(value: number): void {
  if (!this.rtcEngine) {
    return;
  }
  // Conversion formula: exposure value = progress value / 10.
  const actualValue = value / 10.0;
  // Clamp the exposure value between -12.0 and 12.0.
  const clampedExposure = Math.max(-12.0, Math.min(12.0, actualValue));
  // Update the state.
  this.exposureSliderValue = value;
  this.exposureValue = this.formatExposureValue(clampedExposure);
  // Call the RTC engine to set the exposure compensation.
  try {
    this.rtcEngine.setExposure(clampedExposure);
    console.info(`Set exposure compensation: ${clampedExposure}`);
  } catch (error) {
    console.error('Failed to set exposure compensation:', error);
  }
}

Manually set the exposure point

The ARTC SDK allows you to manually set an exposure point. When a user taps a location on the screen, the camera adjusts its exposure based on the lighting conditions in that area.

Note
  • When setting an exposure point, you must first call the isCameraExposurePointSupported interface to check for support.

  • The coordinates must be normalized values.

API reference

/**
 * @brief Checks whether the camera supports setting a manual exposure point.
 * @return
 * - true: Supported.
 * - false: Not supported.
 * @note This API is available only on iOS and Android and is used to check if an exposure point can be set for the current camera.
 */
public abstract boolean isCameraExposurePointSupported();
/**
 * @brief Sets the camera exposure point.
 * @param x The normalized x-coordinate. The value ranges from 0 to 1.
 * @param y The normalized y-coordinate. The value ranges from 0 to 1.
 * @return
 * - 0: Success.
 * - A non-zero value: Failure.
 * @note This API is available only on iOS and Android. After you call this method, the camera performs a one-time exposure adjustment at the specified point and maintains that exposure value.
 */
public abstract int setCameraExposurePoint(float x, float y);

Examples

Android

// Manually set the exposure point.
mLocalViewGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
    @Override
    public boolean onDoubleTap(@NonNull MotionEvent e) {
        // Handle double-tap.
        // ...
        return true;
    }
    @Override
    public boolean onSingleTapConfirmed(@NonNull MotionEvent e) {
        // Handle single-tap.
        if(mAliRtcEngine != null && mAliRtcEngine.isCameraExposurePointSupported()) {
            float[] normalizedCoords = getNormalizedCoordinates(e.getX(), e.getY());
            if (normalizedCoords[0] != -1 && normalizedCoords[1] != -1) {
                mAliRtcEngine.setCameraExposurePoint(normalizedCoords[0], normalizedCoords[1]);
                mCameraExposurePointX.setText(String.format("%.2f", normalizedCoords[0]));
                mCameraExposurePointY.setText(String.format("%.2f", normalizedCoords[1]));
            }
        }
        return true;
    }
});

iOS

@objc func handleSeatViewTap(_ gesture: UITapGestureRecognizer) {
    guard let localSeatView = self.localPreviewSeatView else {
        return
    }
    guard let rtcEngine = self.rtcEngine, rtcEngine.isCameraExposurePointSupported() else { return }


    let tapPoint = gesture.location(in: localSeatView)
    // Convert the tap coordinates to normalized coordinates (0-1 range) of the video frame.
    let normalizedX = tapPoint.x / localSeatView.bounds.width
    let normalizedY = tapPoint.y / localSeatView.bounds.height

    rtcEngine.setCameraExposurePoint(CGPoint(x: normalizedX, y: normalizedY))
    self.cameraExposurePointXTextField.text = String(format: "%.2f", normalizedX)
    self.cameraExposurePointYTextField.text = String(format: "%.2f", normalizedY)
}

Harmony

private handleSingleTap(touchX: number, touchY: number): void {
  if (!this.rtcEngine) {
    return;
  }
  // Get normalized coordinates.
  const normalizedCoords = this.getNormalizedCoordinates(touchX, touchY);
  if (normalizedCoords[0] !== -1 && normalizedCoords[1] !== -1) {
    this.rtcEngine.setCameraExposurePoint(normalizedCoords[0], normalizedCoords[1]);
    this.exposurePointX = normalizedCoords[0].toFixed(2);
    this.exposurePointY = normalizedCoords[1].toFixed(2);
    console.info('Set exposure point:', this.exposurePointX, this.exposurePointY);
  }
}

Manually set the focus point

ARTC provides a feature to set a manual camera focus point. This is similar to the interface for an exposure point, but it focuses on adjusting the camera's focus position. Before using this feature, call isCameraFocusPointSupported to check if it is supported.

Note

After you manually set a focus point, the focus becomes static. It does not continuously track the area or dynamically adjust as the object moves. For dynamic tracking, consider using the auto-focus on faces feature.

API reference

/**
 * @brief Checks whether the camera supports manual focus.
 * @return
 * - true: Supported.
 * - false: Not supported.
 * @note This API is available only on iOS and Android and is used to check if a focus point can be set for the current camera.
 */
public abstract boolean isCameraFocusPointSupported();
/**
 * @brief Sets the manual focus point for the camera.
 * @param x The x-coordinate value (normalized).
 * @param y The y-coordinate value (normalized).
 * @return
 * - 0: Success.
 * - A non-zero value: Failure.
 * @note This API is available only on iOS and Android. After you call this method, the camera performs a one-time focus adjustment at the specified point and maintains that focus value.
 */
public abstract int setCameraFocusPoint(float x, float y);

Examples

The following examples show how to set the exposure point on a single tap and the focus point on a double tap.

Android

mLocalViewGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
    @Override
    public boolean onDoubleTap(@NonNull MotionEvent e) {
        // Handle double-tap.
        if(mAliRtcEngine != null && mAliRtcEngine.isCameraFocusPointSupported()) {
            float[] normalizedCoords = getNormalizedCoordinates(e.getX(), e.getY());
            if (normalizedCoords[0] != -1 && normalizedCoords[1] != -1) {
                mAliRtcEngine.setCameraFocusPoint(normalizedCoords[0], normalizedCoords[1]);
                mCameraFocusPointX.setText(String.format("%.2f", normalizedCoords[0]));
                mCameraFocusPointY.setText(String.format("%.2f", normalizedCoords[1]));
            }
        }
        return true;
    }
    @Override
    public boolean onSingleTapConfirmed(@NonNull MotionEvent e) {
        // Handle single-tap.
        // ...
        return true;
    }
});

iOS

@objc func handleSeatViewDoubleTap(_ gesture: UITapGestureRecognizer) {
    guard let localSeatView = self.localPreviewSeatView else {
        return
    }
    guard let rtcEngine = self.rtcEngine, rtcEngine.isCameraFocusPointSupported() else { return }
    
    let tapPoint = gesture.location(in: localSeatView)
    // Convert the tap coordinates to normalized coordinates (0-1 range) of the video frame.
    let normalizedX = tapPoint.x / localSeatView.bounds.width
    let normalizedY = tapPoint.y / localSeatView.bounds.height
    
    rtcEngine.setCameraFocus(CGPoint(x: normalizedX, y: normalizedY))
    self.cameraFocusPointXTextField.text = String(format: "%.2f", normalizedX)
    self.cameraFocusPointYTextField.text = String(format: "%.2f", normalizedY)
}

Harmony

private handleDoubleTap(touchX: number, touchY: number): void {
  if (!this.rtcEngine) {
    return;
  }
  // Get normalized coordinates.
  const normalizedCoords = this.getNormalizedCoordinates(touchX, touchY);
  if (normalizedCoords[0] !== -1 && normalizedCoords[1] !== -1) {
    this.rtcEngine.setCameraFocusPoint(normalizedCoords[0], normalizedCoords[1]);
    this.focusPointX = normalizedCoords[0].toFixed(2);
    this.focusPointY = normalizedCoords[1].toFixed(2);
    console.info('Set focus point:', this.focusPointX, this.focusPointY);
  }
}

Auto-focus on faces

The ARTC SDK provides an API to configure the auto-focus on faces feature. On supported devices, enabling this feature causes the camera to automatically detect faces in the video frame and adjust the focus to keep them sharp.

Use cases: This feature is useful for face recognition, portrait optimization, and enhancing visual quality in video calls.

Note

Before starting, call isCameraAutoFocusFaceModeSupported to check if the current device supports this feature.

API reference

/**
 * @brief Checks whether the camera supports the auto-focus on faces feature.
 * @return
 * - true: Supported.
 * - false: Not supported.
 * @note This API is available only on iOS and Android. It returns false if the camera is off. 
 *       If the camera is on and supports both face detection and auto-focus, it returns true.
 */
public abstract boolean isCameraAutoFocusFaceModeSupported();

/**
 * @brief Enables or disables the auto-focus on faces feature.
 * @param enable
 * - true: Enable.
 * - false: Disable.
 * @return
 * - true: Success.
 * - false: Failure.
 * @note This API is available only on iOS and Android. If {@link AliRtcEngine#isCameraAutoFocusFaceModeSupported} returns true
 *       and you set enable to true, the camera continuously focuses on the detected faces.
 */
public abstract boolean setCameraAutoFocusFaceModeEnabled(boolean enable);

Examples

Android

if (mAliRtcEngine.isCameraAutoFocusFaceModeSupported()) {
    mAliRtcEngine.setCameraAutoFocusFaceModeEnabled(isChecked);
}

iOS

@IBAction func onCameraAudoFocusSwitch(_ sender: UISwitch) {
    if ((self.rtcEngine?.isCameraAutoFocusFaceModeSupported()) != nil) {
        self.rtcEngine?.setCameraAutoFocusFaceModeEnabled(sender.isOn)
    }
}

Toggle the flashlight

The ARTC SDK allows you to turn the camera's flashlight on or off. This is useful for adjusting brightness in low-light conditions, during video recording, or for other special lighting needs.

Note
  • This feature is available only on iOS and Android and requires a hardware flashlight.

  • The flashlight is typically available only for the rear camera. Front-facing cameras usually do not have a physical flashlight. Although some devices simulate a flash effect using the screen, this API does not control that function.

API reference

/**
 * @brief Turns the camera flashlight on or off.
 * @param flash Specifies whether to turn on the flashlight.
 * @return
 * - 0: Success.
 * - A non-zero value: Failure.
 * @note This API is available only on iOS and Android. Typically, only the rear camera has a flashlight.
 */
public abstract int setCameraFlash(boolean flash);

Examples

Android

mCameraFlashSwitch = findViewById(R.id.camera_flash_switch);
mCameraFlashSwitch.setEnabled(false);
mCameraFlashSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
    if (mAliRtcEngine != null) {
        mAliRtcEngine.setCameraFlash(isChecked);
    }
});

iOS

@IBOutlet weak var cameraFlashSwitch: UISwitch!
@IBAction func onCameraFlashSwitch(_ sender: UISwitch) {
    if self.rtcEngine?.getCurrentCameraDirection() == .back {
        self.rtcEngine?.setCameraFlash(sender.isOn)
    }
}

Harmony

private handleFlashChange(value: boolean): void {
  if (!this.rtcEngine) {
    return;
  }

  this.rtcEngine.setCameraFlash(value);
}