Manajemen perangkat video merupakan fitur inti ApsaraVideo Real-time Communication (ARTC). SDK ARTC menyediakan serangkaian API lengkap untuk mengelola perangkat di berbagai platform. Topik ini menjelaskan fitur manajemen perangkat video dari mesin ARTC.
Pengenalan fitur
Fitur manajemen perangkat video pada SDK ARTC Alibaba Cloud memberikan kontrol komprehensif kepada developer atas perangkat kamera. Anda dapat menyesuaikan parameter kamera secara detail di berbagai platform, seperti iOS dan Android, termasuk mengonfigurasi panjang fokus, kontrol eksposur, serta fokus manual atau otomatis untuk meningkatkan kualitas tangkapan video.
Kode contoh
Kelola perangkat tangkap video di Android: Android/ARTCExample/BasicUsage/src/main/java/com/aliyun/artc/api/basicusage/CameraCommonControl/CameraActivity.java.
Kelola perangkat tangkap video di iOS: iOS/ARTCExample/BasicUsage/CameraCommonSetting/CameraCommonControlVC.swift.
Prasyarat
Anda memiliki Akun Alibaba Cloud yang valid dan telah membuat aplikasi ApsaraVideo Real-time Communication. Untuk informasi selengkapnya, lihat Buat aplikasi. Dapatkan App ID dan App Key dari Konsol ApsaraVideo Real-time Communication.
Integrasi SDK dan implementasi fitur dasar:
Anda telah mengintegrasikan SDK ARTC ke dalam proyek Anda dan mengimplementasikan fitur audio dan video real-time dasar. Untuk informasi selengkapnya, lihat Unduh dan integrasikan SDK dan Implementasikan panggilan audio dan video.
Kamera telah dijalankan. Misalnya, Anda telah memulai pratinjau dengan memanggil
startPreview, atau Anda telah bergabung ke channel dengan memanggiljoinChannel.
Implementasi
Atur tingkat zoom
SDK ARTC mendukung fitur zoom kamera.
Referensi API
/**
* @brief Mengatur tingkat zoom kamera.
* @param zoom Tingkat zoom. Nilainya berkisar dari 1 hingga nilai zoom maksimum yang didukung oleh kamera.
* @return
* - 0: Berhasil.
* - Nilai selain 0: Gagal.
* @note API ini hanya tersedia di iOS dan Android.
*/
public abstract int setCameraZoom(float zoom);
/**
* @brief Mendapatkan faktor zoom maksimum kamera.
* @return Faktor zoom maksimum kamera.
*/
public abstract float GetCameraMaxZoomFactor();
/**
* @brief Mendapatkan faktor zoom saat ini dari kamera.
* @return Faktor zoom kamera.
*/
public abstract float GetCurrentZoom();Contoh
Android
// Dapatkan informasi zoom.
private void initZoomSeekBar() {
if (mAliRtcEngine != null) {
zoomSeekBar.setEnabled(true);
// Dapatkan nilai zoom maksimum.
float maxZoom = mAliRtcEngine.GetCameraMaxZoomFactor();
float currZoom = mAliRtcEngine.GetCurrentZoom();
// Atur rentang SeekBar (dari 1.0 hingga maxZoom, dengan langkah 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);
}
}
}
// Atur tingkat 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
// Dapatkan informasi zoom.
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)"
}
// Atur tingkat 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;
}
// Hitung nilai zoom berdasarkan progres: zoom = 1.0 + (value / 10.0).
const newZoom = 1.0 + (value / 10.0);
// Batasi nilai zoom dalam rentang 1.0 hingga 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}`);
}Atur eksposur
SDK ARTC memungkinkan Anda mengatur eksposur kamera untuk mengontrol kecerahan selama perekaman.
Referensi API
/**
* @brief Mengatur eksposur kamera.
* @param exposure Nilai eksposur.
* @return
* - 0: Berhasil.
* - Nilai selain 0: Gagal.
*/
public abstract int SetExposure(float exposure);
/**
* @brief Mendapatkan eksposur kamera.
* @return Eksposur kamera.
*/
public abstract float GetCurrentExposure();
/**
* @brief Mendapatkan eksposur minimum kamera.
* @return Eksposur minimum kamera.
*/
public abstract float GetMinExposure();
/**
* @brief Mendapatkan eksposur maksimum kamera.
* @return Eksposur maksimum kamera.
*/
public abstract float GetMaxExposure();Contoh
Android
// Dapatkan informasi eksposur.
private void initExposureSeekBar() {
if (mAliRtcEngine != null) {
exposureSeekBar.setEnabled(true);
// Dapatkan nilai eksposur maksimum.
float maxExposure = mAliRtcEngine.GetMaxExposure();
// Dapatkan nilai eksposur minimum.
float minExposure = mAliRtcEngine.GetMinExposure();
float currExposure = mAliRtcEngine.GetCurrentExposure();
if(maxExposure > minExposure) {
// Atur ulang rentang SeekBar.
int maxProgress = (int)(maxExposure - minExposure) * 10;
exposureSeekBar.setMax(maxProgress);
int currProgress = (int)((currExposure - minExposure) * 10);
exposureSeekBar.setProgress(currProgress);
} else {
exposureSeekBar.setEnabled(false);
}
}
}
// Atur eksposur.
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
// Dapatkan informasi eksposur perangkat.
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)"
}
// Atur eksposur.
@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
// Tangani perubahan eksposur.
private handleExposureChange(value: number): void {
if (!this.rtcEngine) {
return;
}
// Rumus konversi: nilai eksposur = nilai progres / 10.
const actualValue = value / 10.0;
// Batasi nilai eksposur dalam rentang -12.0 hingga 12.0.
const clampedExposure = Math.max(-12.0, Math.min(12.0, actualValue));
// Perbarui status.
this.exposureSliderValue = value;
this.exposureValue = this.formatExposureValue(clampedExposure);
// Panggil mesin RTC untuk mengatur kompensasi eksposur.
try {
this.rtcEngine.setExposure(clampedExposure);
console.info(`Set kompensasi eksposur: ${clampedExposure}`);
} catch (error) {
console.error('Gagal mengatur kompensasi eksposur:', error);
}
}Atur titik eksposur secara manual
ARTC memungkinkan Anda mengatur titik eksposur kamera secara manual. Saat pengguna menentukan posisi—biasanya dengan mengetuk titik di layar—kamera akan menyesuaikan kecerahan untuk area tersebut.
Sebelum mengatur titik eksposur, panggil API
isCameraExposurePointSupporteduntuk memeriksa apakah fitur ini didukung.Parameter input berupa koordinat ternormalisasi.
Informasi antarmuka
/**
* @brief Memeriksa apakah pengaturan titik eksposur kamera didukung.
* @return
* - true: Didukung.
* - false: Tidak didukung.
* @note API ini hanya tersedia di iOS dan Android. Gunakan API ini untuk memeriksa apakah Anda dapat mengatur titik eksposur untuk kamera saat ini.
*/
public abstract boolean isCameraExposurePointSupported();
/**
* @brief Mengatur titik eksposur kamera.
* @param x Nilai koordinat sumbu-x (ternormalisasi). Nilai valid: [0, 1].
* @param y Nilai koordinat sumbu-y (ternormalisasi). Nilai valid: [0, 1].
* @return
* - 0: Berhasil.
* - Nilai selain 0: Gagal.
* @note API ini hanya tersedia di iOS dan Android. Setelah memanggil API ini, kamera melakukan penyesuaian eksposur pada titik yang ditentukan dan mempertahankan nilai eksposur tersebut.
*/
public abstract int setCameraExposurePoint(float x, float y);Contoh
Android
// Atur titik eksposur secara manual.
mLocalViewGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(@NonNull MotionEvent e) {
// Tangani ketukan ganda.
// ...
return true;
}
@Override
public boolean onSingleTapConfirmed(@NonNull MotionEvent e) {
// Tangani ketukan tunggal.
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)
// Konversi koordinat ketukan menjadi koordinat ternormalisasi (dalam rentang 0 hingga 1) dari frame video.
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;
}
// Dapatkan koordinat ternormalisasi.
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 titik eksposur:', this.exposurePointX, this.exposurePointY);
}
}Atur titik fokus secara manual
ARTC memungkinkan Anda mengatur titik fokus manual untuk kamera. Ini mirip dengan pengaturan titik eksposur, tetapi menyesuaikan posisi fokus kamera. Sebelum menggunakan fitur ini, panggil isCameraFocusPointSupported untuk memeriksa apakah fitur ini didukung.
Setelah Anda mengatur titik fokus secara manual, fokus menjadi statis dan tidak terus-menerus melacak area atau menyesuaikan secara dinamis saat objek bergerak. Untuk pelacakan dinamis, pertimbangkan penggunaan pengenalan wajah yang dikombinasikan dengan fokus otomatis.
Referensi API
/**
* @brief Memeriksa apakah kamera mendukung fokus manual.
* @return
* - true: Didukung.
* - false: Tidak didukung.
* @note API ini hanya tersedia di iOS dan Android. Gunakan API ini untuk memeriksa apakah Anda dapat mengatur titik fokus untuk kamera saat ini.
*/
public abstract boolean isCameraFocusPointSupported();
/**
* @brief Mengatur titik fokus manual untuk kamera.
* @param x Nilai koordinat sumbu-x.
* @param y Nilai koordinat sumbu-y.
* @return
* - 0: Berhasil.
* - Nilai selain 0: Gagal.
* @note API ini hanya tersedia di iOS dan Android. Setelah memanggil API ini, kamera melakukan penyesuaian fokus pada titik yang ditentukan dan mempertahankan nilai fokus tersebut.
*/
public abstract int setCameraFocusPoint(float x, float y);Contoh
Kode contoh menunjukkan cara mengatur titik eksposur pada ketukan tunggal dan mengatur titik fokus pada ketukan ganda.
Android
mLocalViewGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(@NonNull MotionEvent e) {
// Tangani ketukan ganda.
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) {
// Tangani ketukan tunggal.
// ...
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)
// Konversi koordinat ketukan menjadi koordinat ternormalisasi (dalam rentang 0 hingga 1) dari frame video.
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;
}
// Dapatkan koordinat ternormalisasi.
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 titik fokus:', this.focusPointX, this.focusPointY);
}
}Fokus otomatis pada wajah
ARTC menyediakan API untuk mengonfigurasi fitur fokus otomatis pada wajah kamera. Jika perangkat mendukung fitur ini, Anda dapat mengaktifkannya agar kamera secara otomatis mendeteksi wajah dalam frame dan memfokuskannya, sehingga area wajah tetap tajam.
Skenario: Fitur ini digunakan untuk pengenalan wajah, optimasi fotografi potret, dan peningkatan efek visual dalam panggilan video.
Sebelum mengaktifkan fitur ini, panggil isCameraAutoFocusFaceModeSupported untuk memeriksa apakah perangkat saat ini mendukungnya.
Informasi antarmuka
/**
* @brief Memeriksa apakah fokus otomatis pada wajah didukung.
* @return
* - true: Didukung.
* - false: Tidak didukung.
* @note API ini hanya tersedia di iOS dan Android. Mengembalikan false jika kamera tidak dinyalakan.
* Jika kamera dinyalakan dan mendukung fitur pengenalan wajah serta fokus, maka mengembalikan true.
*/
public abstract boolean isCameraAutoFocusFaceModeSupported();
/**
* @brief Mengatur fokus wajah kamera.
* @param enable
* - true: Aktifkan.
* - false: Nonaktifkan.
* @return
* - true: Berhasil.
* - false: Gagal.
* @note API ini hanya tersedia di iOS dan Android. Jika {@link AliRtcEngine#isCameraAutoFocusFaceModeSupported} mengembalikan true
* dan enable diatur ke true dalam pemanggilan ini, kamera akan memfokuskan wajah yang terdeteksi secara real-time.
*/
public abstract boolean setCameraAutoFocusFaceModeEnabled(boolean enable);Contoh
Android
if (mAliRtcEngine.isCameraAutoFocusFaceModeSupported()) {
mAliRtcEngine.setCameraAutoFocusFaceModeEnabled(isChecked);
}iOS
@IBAction func onCameraAudoFocusSwitch(_ sender: UISwitch) {
if ((self.rtcEngine?.isCameraAutoFocusFaceModeSupported()) != nil) {
self.rtcEngine?.setCameraAutoFocusFaceModeEnabled(sender.isOn)
}
}Nyalakan atau matikan senter
SDK ARTC memungkinkan Anda mengontrol senter kamera. Fitur ini sering digunakan dalam skenario yang memerlukan penyesuaian kecerahan, seperti pengambilan gambar dalam kondisi cahaya rendah, perekaman video, atau kebutuhan pencahayaan khusus.
API ini hanya didukung di platform iOS dan Android, serta hanya dapat digunakan jika perangkat keras mendukung senter.
Fitur senter biasanya hanya tersedia untuk kamera belakang. Kamera depan umumnya tidak memiliki senter fisik. Beberapa perangkat mungkin mensimulasikan efek kilat menggunakan layar, tetapi API ini tidak mengontrol fungsi tersebut.
Referensi API
/**
* @brief Menyalakan atau mematikan senter kamera.
* @param flash Menentukan apakah senter akan dinyalakan.
* @return
* - 0: Berhasil.
* - Nilai selain 0: Gagal.
* @note API ini hanya tersedia di iOS dan Android. Umumnya, hanya kamera belakang yang memiliki senter.
*/
public abstract int setCameraFlash(boolean flash);Contoh
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);
}