すべてのプロダクト
Search
ドキュメントセンター

ApsaraVideo Live:映像キャプチャデバイスの管理

最終更新日:Jan 10, 2026

映像デバイス管理は、ApsaraVideo Real-time Communication (ARTC) のコア機能です。ARTC SDK は、さまざまなプラットフォーム上のデバイスを管理するための豊富な API セットを提供します。このトピックでは、ARTC エンジンの映像デバイス管理機能について説明します。

機能の概要

Alibaba Cloud ARTC SDK の映像デバイス管理機能により、開発者はデバイスを包括的に制御できます。iOS や Android などのさまざまなプラットフォームで、カメラパラメーターを微調整できます。また、焦点距離、露出コントロール、手動またはオートフォーカスなどのパラメーターを設定して、映像キャプチャの品質を向上させることもできます。

サンプルコード

Android での映像キャプチャデバイスの管理Android/ARTCExample/BasicUsage/src/main/java/com/aliyun/artc/api/basicusage/CameraCommonControl/CameraActivity.java

iOS での映像キャプチャデバイスの管理iOS/ARTCExample/BasicUsage/CameraCommonSetting/CameraCommonControlVC.swift

前提条件

  • 有効な Alibaba Cloud アカウントをお持ちで、ApsaraVideo Real-time Communication アプリケーションを作成済みであること。詳細については、「アプリケーションの作成」をご参照ください。ApsaraVideo Real-time Communication コンソールから App ID と App Key を取得します。

  • SDK の統合と基本機能の実装:

    • ARTC SDK をプロジェクトに統合し、基本的なリアルタイム音声・映像機能を実装済みであること。詳細については、「SDK のダウンロードと統合」および「音声・映像通話の実装」をご参照ください。

    • カメラが起動していること。たとえば、startPreview を呼び出してプレビューを開始したか、joinChannel を呼び出してチャンネルに参加した状態です。

実装

ズームレベルの設定

ARTC SDK は、カメラのズーム機能をサポートしています。

API リファレンス

/**
 * @brief カメラのズームレベルを設定します。
 * @param zoom ズームレベル。値の範囲は 1 からカメラがサポートする最大ズーム値までです。
 * @return
 * - 0:成功。
 * - 0 以外の値:失敗。
 * @note この API は iOS および Android でのみ利用可能です。
 */
public abstract int setCameraZoom(float zoom);

 /**
 * @brief カメラの最大ズーム係数を取得します。
 * @return カメラの最大ズーム係数。
 */
public abstract float GetCameraMaxZoomFactor();

/**
 * @brief カメラの現在のズーム係数を取得します。
 * @return カメラのズーム係数。
 */
public abstract float GetCurrentZoom();

Android

// ズーム情報を取得します。
private void initZoomSeekBar() {
    if (mAliRtcEngine != null) {
        zoomSeekBar.setEnabled(true);
        // 最大ズーム値を取得します。
        float maxZoom = mAliRtcEngine.GetCameraMaxZoomFactor();
        float currZoom = mAliRtcEngine.GetCurrentZoom();
        // SeekBar の範囲を設定します (1.0 から maxZoom まで、ステップは 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);
        }
    }
}
// ズームレベルを設定します。
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

// ズーム情報を取得します。
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)"
}

// ズームレベルを設定します。
@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;
  }

  // プログレスに基づいてズーム値を計算します:zoom = 1.0 + (value / 10.0)。
  const newZoom = 1.0 + (value / 10.0);

  // ズーム値を 1.0 から 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}`);
}

露出の設定

ARTC SDK を使用すると、カメラの露出を設定して、キャプチャ中の輝度を制御できます。

API リファレンス

/**
 * @brief カメラの露出を設定します。
 * @param exposure 露出値。
 * @return
 * - 0:成功。
 * - 0 以外の値:失敗。
 */
public abstract int SetExposure(float exposure);

/**
 * @brief カメラの露出を取得します。
 * @return カメラの露出。
 */
public abstract float GetCurrentExposure();

/**
 * @brief カメラの最小露出を取得します。
 * @return カメラの最小露出。
 */
public abstract float GetMinExposure();

/**
 * @brief カメラの最大露出を取得します。
 * @return カメラの最大露出。
 */
public abstract float GetMaxExposure();

Android

// 露出情報を取得します。
private void initExposureSeekBar() {
    if (mAliRtcEngine != null) {
        exposureSeekBar.setEnabled(true);
        // 最大露出値を取得します。
        float maxExposure = mAliRtcEngine.GetMaxExposure();
        // 最小露出値を取得します。
        float minExposure = mAliRtcEngine.GetMinExposure();
        float currExposure = mAliRtcEngine.GetCurrentExposure();
        if(maxExposure > minExposure) {
            // SeekBar の範囲をリセットします。
            int maxProgress = (int)(maxExposure - minExposure) * 10;
            exposureSeekBar.setMax(maxProgress);
            int currProgress = (int)((currExposure - minExposure) * 10);
            exposureSeekBar.setProgress(currProgress);
        } else {
            exposureSeekBar.setEnabled(false);
        }
    }
}
// 露出を設定します。
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

// デバイスの露出情報を取得します。
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)"
}
// 露出を設定します。
@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

// 露出の変更を処理します。
private handleExposureChange(value: number): void {
  if (!this.rtcEngine) {
    return;
  }
  // 変換式:露出値 = プログレス値 / 10。
  const actualValue = value / 10.0;
  // 露出値を -12.0 から 12.0 の範囲に制限します。
  const clampedExposure = Math.max(-12.0, Math.min(12.0, actualValue));
  // ステータスを更新します。
  this.exposureSliderValue = value;
  this.exposureValue = this.formatExposureValue(clampedExposure);
  // RTC エンジンを呼び出して露出補正を設定します。
  try {
    this.rtcEngine.setExposure(clampedExposure);
    console.info(`Set exposure compensation: ${clampedExposure}`);
  } catch (error) {
    console.error('Failed to set exposure compensation:', error);
  }
}

露出ポイントの手動設定

ARTC を使用すると、カメラの露出ポイントを手動で設定できます。ユーザーが位置を指定すると (通常は画面上の点をタップする)、カメラはその領域の輝度を調整します。

説明
  • 露出ポイントを設定する前に、isCameraExposurePointSupported API を呼び出して、この機能がサポートされているかどうかを確認してください。

  • 入力パラメーターは正規化された座標です。

インターフェース情報

/**
 * @brief カメラの露出ポイントの設定がサポートされているかどうかを確認します。
 * @return
 * - true:サポートされています。
 * - false:サポートされていません。
 * @note この API は iOS および Android でのみ利用可能です。この API を使用して、現在のカメラで露出ポイントを設定できるかどうかを確認します。
 */
public abstract boolean isCameraExposurePointSupported();
/**
 * @brief カメラの露出ポイントを設定します。
 * @param x x 軸座標の値 (正規化)。有効値:[0, 1]。
 * @param y y 軸座標の値 (正規化)。有効値:[0, 1]。
 * @return
 * - 0:成功。
 * - 0 以外の値:失敗。
 * @note この API は iOS および Android でのみ利用可能です。この API を呼び出すと、カメラは指定されたポイントで露出調整を行い、この露出値を維持します。
 */
public abstract int setCameraExposurePoint(float x, float y);

Android

// 露出ポイントを手動で設定します。
mLocalViewGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
    @Override
    public boolean onDoubleTap(@NonNull MotionEvent e) {
        // ダブルタップを処理します。
        // ...
        return true;
    }
    @Override
    public boolean onSingleTapConfirmed(@NonNull MotionEvent e) {
        // シングルタップを処理します。
        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)
    // タップ座標をビデオフレームの正規化された座標 (0 から 1 の範囲) に変換します。
    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;
  }
  // 正規化された座標を取得します。
  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);
  }
}

フォーカスポイントの手動設定

ARTC を使用すると、カメラの手動フォーカスポイントを設定できます。これは露出ポイントの設定と似ていますが、カメラのフォーカス位置を調整します。この機能を使用する前に、isCameraFocusPointSupported を呼び出して、サポートされているかどうかを確認してください。

説明

フォーカスポイントを手動で設定すると、フォーカスは静的になります。オブジェクトが移動しても、その領域を継続的に追跡したり、動的に調整したりすることはありません。動的な追跡には、顔認識とオートフォーカスを組み合わせることを検討してください。

API リファレンス

/**
 * @brief カメラが手動フォーカスをサポートしているかどうかを確認します。
 * @return
 * - true:サポートされています。
 * - false:サポートされていません。
 * @note この API は iOS および Android でのみ利用可能です。この API を使用して、現在のカメラでフォーカスポイントを設定できるかどうかを確認します。
 */
public abstract boolean isCameraFocusPointSupported();
/**
 * @brief カメラの手動フォーカスポイントを設定します。
 * @param x x 軸座標の値。
 * @param y y 軸座標の値。
 * @return
 * - 0:成功。
 * - 0 以外の値:失敗。
 * @note この API は iOS および Android でのみ利用可能です。この API を呼び出すと、カメラは指定されたポイントでフォーカス調整を行い、このフォーカス値を維持します。
 */
public abstract int setCameraFocusPoint(float x, float y);

サンプルコードは、シングルタップで露出ポイントを設定し、ダブルタップでフォーカスポイントを設定する方法を示しています。

Android

mLocalViewGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
    @Override
    public boolean onDoubleTap(@NonNull MotionEvent e) {
        // ダブルタップを処理します。
        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) {
        // シングルタップを処理します。
        // ...
        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)
    // タップ座標をビデオフレームの正規化された座標 (0 から 1 の範囲) に変換します。
    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;
  }
  // 正規化された座標を取得します。
  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);
  }
}

顔へのオートフォーカス

ARTC は、カメラの顔へのオートフォーカス機能を設定するための API を提供します。デバイスがこの機能をサポートしている場合、有効にすると、カメラはフレーム内の顔を自動的に検出し、フォーカスを合わせます。これにより、顔の領域がシャープに保たれます。

シナリオ: この機能は、顔認識、ポートレート撮影の最適化、ビデオ通話での視覚効果の向上に使用されます。

説明

この機能を有効にする前に、isCameraAutoFocusFaceModeSupported を呼び出して、現在のデバイスがサポートしているかどうかを確認してください。

インターフェース情報

/**
 * @brief 顔へのオートフォーカスがサポートされているかどうかを確認します。
 * @return
 * - true:サポートされています。
 * - false:サポートされていません。
 * @note この API は iOS および Android でのみ利用可能です。カメラがオンになっていない場合は false を返します。
 *       カメラがオンで、顔認識とフォーカス機能の両方をサポートしている場合は true を返します。
 */
public abstract boolean isCameraAutoFocusFaceModeSupported();

/**
 * @brief カメラの顔フォーカスを設定します。
 * @param enable
 * - true:有効にする。
 * - false:無効にする。
 * @return
 * - true:成功。
 * - false:失敗。
 * @note この API は iOS および Android でのみ利用可能です。{@link AliRtcEngine#isCameraAutoFocusFaceModeSupported} が true を返し、
 *       この呼び出しで enable が true に設定されている場合、カメラは検出された顔にリアルタイムでフォーカスを合わせます。
 */
public abstract boolean setCameraAutoFocusFaceModeEnabled(boolean enable);

Android

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

iOS

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

フラッシュライトのオン/オフ

ARTC SDK を使用すると、カメラのフラッシュライトを制御できます。この機能は、低照度条件下での撮影、ビデオ録画、または特別な照明が必要なシナリオなど、輝度調整が必要な場合によく使用されます。

説明
  • この API は iOS および Android プラットフォームでのみサポートされています。デバイスのハードウェアがフラッシュライトをサポートしている場合にのみ使用できます。

  • フラッシュライト機能は、通常、背面カメラでのみ利用可能です。前面カメラには通常、物理的なフラッシュライトはありません。一部のデバイスでは画面を使用してフラッシュ効果をシミュレートする場合がありますが、この API はその機能を制御しません。

API リファレンス

/**
 * @brief カメラのフラッシュライトをオンまたはオフにします。
 * @param flash フラッシュライトをオンにするかどうかを指定します。
 * @return
 * - 0:成功。
 * - 0 以外の値:失敗。
 * @note この API は iOS および Android でのみ利用可能です。通常、背面カメラにのみフラッシュライトがあります。
 */
public abstract int setCameraFlash(boolean flash);

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);
}