映像デバイス管理は、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 を使用すると、カメラの露出ポイントを手動で設定できます。ユーザーが位置を指定すると (通常は画面上の点をタップする)、カメラはその領域の輝度を調整します。
露出ポイントを設定する前に、
isCameraExposurePointSupportedAPI を呼び出して、この機能がサポートされているかどうかを確認してください。入力パラメーターは正規化された座標です。
インターフェース情報
/**
* @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);
}