Dokumen ini menjelaskan cara mengintegrasikan kit pengembangan perangkat lunak (SDK) Alibaba Real-Time Communication (ARTC) ke dalam proyek iOS Anda untuk membuat aplikasi interaktif sederhana berbasis audio. Aplikasi ini dapat digunakan untuk skenario seperti panggilan suara dan ruang obrolan suara.
Pengenalan fungsi
Sebelum memulai, pahami konsep dasar berikut mengenai interaksi audio dan video real-time:
SDK ARTC: Kit pengembangan perangkat lunak untuk ApsaraVideo Real-time Communication. Ini merupakan Produk Alibaba Cloud yang membantu pengembang menerapkan interaksi audio dan video real-time dengan cepat.
Saluran: Konsep yang mirip dengan ruangan. Pengguna dalam saluran yang sama dapat berinteraksi secara real-time.
Streamer: Pengguna yang dapat mempublikasikan aliran audio dan video dalam suatu saluran serta berlangganan aliran yang dipublikasikan oleh streamer lain.
Penonton: Pengguna yang dapat berlangganan aliran audio dan video dalam suatu saluran tetapi tidak dapat mempublikasikannya.
Gambar berikut menunjukkan alur dasar untuk menerapkan panggilan suara atau ruang obrolan suara:
Pengguna harus memanggil
joinChanneluntuk bergabung ke saluran sebelum mereka dapat melakukan pengambilan aliran atau menarik aliran:Skenario panggilan hanya audio: Semua pengguna adalah streamer dan dapat melakukan pengambilan serta menarik aliran.
Skenario ruang obrolan suara: Pengguna yang perlu melakukan pengambilan aliran dalam saluran harus memiliki peran streamer. Jika pengguna hanya perlu menarik aliran, Anda dapat mengatur perannya sebagai penonton.
Anda dapat menggunakan
setClientRoleuntuk mengatur peran berbeda bagi pengguna.
Setelah bergabung ke saluran, perilaku pengambilan dan penarikan aliran bervariasi tergantung pada peran pengguna:
Semua pengguna dalam saluran dapat menerima aliran audio dan video dari pengguna lain dalam saluran yang sama.
Streamer dapat melakukan pengambilan aliran audio dan video ke dalam saluran.
Jika penonton perlu melakukan pengambilan aliran, mereka harus memanggil metode
setClientRoleuntuk mengubah perannya menjadi streamer sebelum dapat melakukan pengambilan aliran.
Proyek contoh
SDK ARTC menyediakan proyek contoh sumber terbuka sebagai referensi Anda. Anda dapat mengunduh atau melihat kode sumber contoh.
Prasyarat
Sebelum memulai, pastikan lingkungan pengembangan Anda memenuhi persyaratan berikut:
Alat pengembangan: Xcode 14.0 atau versi lebih baru. Kami merekomendasikan menggunakan versi resmi terbaru.
Konfigurasi yang direkomendasikan: CocoaPods 1.9.3 atau versi lebih baru.
Perangkat uji: Perangkat uji yang menjalankan iOS 9.0 atau versi lebih baru.
Kami merekomendasikan menggunakan perangkat fisik untuk pengujian. Simulator mungkin tidak memiliki fitur tertentu.
Lingkungan jaringan: Diperlukan koneksi jaringan yang stabil.
Persiapan aplikasi: Dapatkan AppID dan AppKey untuk aplikasi ARTC Anda. Untuk informasi selengkapnya, lihat Buat aplikasi.
Pembuatan dan konfigurasi proyek: Anda telah membuat proyek, menambahkan izin yang diperlukan untuk interaksi audio dan jaringan, serta mengintegrasikan SDK ARTC. Untuk informasi selengkapnya, lihat Menerapkan panggilan audio dan video.
Langkah-langkah implementasi
Bagian berikut menggunakan skenario ruang obrolan suara sebagai contoh. Prosesnya adalah sebagai berikut:
Fitur utama dalam skenario ruang obrolan suara adalah sebagai berikut:
Hanya audio: Saluran hanya berisi audio, bukan video.
Peran streamer dan penonton: Peran dalam saluran dibagi menjadi streamer dan penonton. Streamer dapat melakukan pengambilan dan menarik aliran audio. Penonton hanya dapat menarik aliran audio yang diambil oleh streamer. Penonton dapat mengubah perannya menjadi streamer.
Menerapkan interaksi hanya audio
1. Meminta izin
Meskipun SDK memeriksa izin yang diperlukan saat Anda memulai panggilan, kami merekomendasikan memeriksa izin mikrofon sebelum memulai panggilan untuk memastikan pengalaman pengguna yang lancar.
func checkMicrophonePermission(completion: @escaping (Bool) -> Void) {
let status = AVCaptureDevice.authorizationStatus(for: .audio)
switch status {
case .notDetermined:
AVCaptureDevice.requestAccess(for: .audio) { granted in
completion(granted)
}
case .authorized:
completion(true)
default:
completion(false)
}
}
func checkCameraPermission(completion: @escaping (Bool) -> Void) {
let status = AVCaptureDevice.authorizationStatus(for: .video)
switch status {
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { granted in
completion(granted)
}
case .authorized:
completion(true)
default:
completion(false)
}
}
// Contoh penggunaan
checkMicrophonePermission { granted in
if granted {
print("Akses mikrofon diberikan.")
} else {
print("Akses mikrofon ditolak.")
}
}
checkCameraPermission { granted in
if granted {
print("Akses kamera diberikan.")
} else {
print("Akses kamera ditolak.")
}
}
2. Dapatkan Token otentikasi
Bergabung ke saluran ARTC memerlukan Token otentikasi untuk memverifikasi identitas pengguna. Untuk detail tentang cara pembuatan token, lihat Menerapkan otentikasi berbasis token. Token dapat dihasilkan menggunakan metode parameter tunggal atau metode multi-parameter. Metode yang Anda gunakan menentukan API joinChannel mana yang perlu Anda panggil.
Untuk lingkungan produksi:
Karena pembuatan token memerlukan AppKey Anda, menyematkannya langsung di sisi klien menimbulkan risiko keamanan. Di lingkungan produksi, kami sangat menyarankan agar token dihasilkan di server Anda dan dikirim ke klien.
Untuk pengembangan dan debugging:
Saat pengembangan, jika server bisnis Anda belum memiliki logika untuk menghasilkan token, Anda dapat sementara menggunakan logika pembuatan token dari APIExample untuk membuat token sementara. Kode referensinya adalah sebagai berikut:
class ARTCTokenHelper: NSObject {
/**
* RTC AppId
*/
public static let AppId = "<RTC AppId>"
/**
* RTC AppKey
*/
public static let AppKey = "<RTC AppKey>"
/**
* Hasilkan token multi-parameter untuk bergabung ke saluran berdasarkan channelId, userId, dan timestamp.
*/
public func generateAuthInfoToken(appId: String = ARTCTokenHelper.AppId, appKey: String = ARTCTokenHelper.AppKey, channelId: String, userId: String, timestamp: Int64) -> String {
let stringBuilder = appId + appKey + channelId + userId + "\(timestamp)"
let token = ARTCTokenHelper.GetSHA256(stringBuilder)
return token
}
/**
* Hasilkan token parameter tunggal untuk bergabung ke saluran berdasarkan channelId, userId, dan nonce.
*/
public func generateJoinToken(appId: String = ARTCTokenHelper.AppId, appKey: String = ARTCTokenHelper.AppKey, channelId: String, userId: String, timestamp: Int64, nonce: String = "") -> String {
let token = self.generateAuthInfoToken(appId: appId, appKey: appKey, channelId: channelId, userId: userId, timestamp: timestamp)
let tokenJson: [String: Any] = [
"appid": appId,
"channelid": channelId,
"userid": userId,
"nonce": nonce,
"timestamp": timestamp,
"token": token
]
if let jsonData = try? JSONSerialization.data(withJSONObject: tokenJson, options: []),
let base64Token = jsonData.base64EncodedString() as String? {
return base64Token
}
return ""
}
/**
* Tandatangani string menggunakan SHA256.
* Penandatanganan string (SHA256)
*/
private static func GetSHA256(_ input: String) -> String {
// Konversi string input ke data.
let data = Data(input.utf8)
// Buat buffer untuk menyimpan hasil hash.
var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
// Hitung hash SHA-256.
data.withUnsafeBytes {
_ = CC_SHA256($0.baseAddress, CC_LONG(data.count), &hash)
}
// Konversi hash ke string heksadesimal.
return hash.map { String(format: "%02hhx", $0) }.joined()
}
}
3. Buat dan inisialisasi mesin
Buat mesin RTC
Anda dapat memanggil getInstance untuk membuat objek mesin RTC.
private var rtcEngine: AliRtcEngine? = nil
// Buat mesin dan atur callback.
let engine = AliRtcEngine.sharedInstance(self, extras:nil)
self.rtcEngine = engineInisialisasi mesin
Anda dapat memanggil metode
setChannelProfileuntuk mengatur profil saluran ke mode interaktif.Anda dapat memanggil metode
setClientRoleuntuk mengatur peran pengguna sebagai streamer atau penonton sesuai skenario.Anda dapat memanggil metode
setAudioProfileuntuk mengatur kualitas audio dan mode skenario.
// Atur profil saluran ke live interaktif. AliRtcInteractivelive digunakan untuk semua skenario RTC.
engine.setChannelProfile(AliRtcChannelProfile.interactivelive)
// Atur peran.
if self.isAnchor {
// Untuk mode streamer, yang memerlukan pengambilan aliran audio dan video, atur peran ke AliRtcClientRoleInteractive.
engine.setClientRole(AliRtcClientRole.roleInteractive)
}
else {
// Untuk mode penonton, yang tidak memerlukan pengambilan aliran audio dan video, atur peran ke AliRtcClientRolelive.
engine.setClientRole(AliRtcClientRole.rolelive)
}
// Atur profil audio. Secara default, mode berkualitas tinggi (AliRtcEngineHighQualityMode) dan mode musik (AliRtcSceneMusicMode) digunakan.
engine.setAudioProfile(AliRtcAudioProfile.engineHighQualityMode, audio_scene: AliRtcAudioScenario.sceneMusicMode)Terapkan callback umum
Selama operasi, SDK pertama-tama mencoba memulihkan diri secara otomatis dari pengecualian menggunakan mekanisme percobaan ulang internalnya. Untuk kesalahan yang tidak dapat diselesaikan secara internal, SDK memberi tahu aplikasi Anda melalui callback yang telah ditentukan.
Berikut adalah callback utama untuk kesalahan yang tidak dapat ditangani SDK. Lapisan aplikasi Anda harus mendengarkan dan merespons callback ini:
Penyebab | Callback dan parameter | Solusi | Deskripsi |
Otentikasi gagal | Parameter | Jika kesalahan ini terjadi, aplikasi perlu memeriksa apakah token benar. | Ketika pengguna memanggil API, jika otentikasi gagal, sistem mengembalikan pesan kesalahan dalam callback API. |
Token akan segera kedaluwarsa |
| Jika pengecualian ini terjadi, aplikasi perlu mendapatkan informasi otentikasi terbaru lalu memanggil | Kesalahan kedaluwarsa token dapat terjadi dalam dua situasi: saat pengguna memanggil API atau selama eksekusi program. Oleh karena itu, kesalahan dilaporkan melalui callback API atau callback kesalahan terpisah. |
Token telah kedaluwarsa |
| Jika pengecualian ini terjadi, aplikasi perlu meminta pengguna untuk bergabung kembali ke saluran. | Kesalahan kedaluwarsa token dapat terjadi dalam dua situasi: saat pengguna memanggil API atau selama eksekusi program. Oleh karena itu, kesalahan dilaporkan melalui callback API atau callback kesalahan terpisah. |
Kesalahan konektivitas jaringan | Callback | Jika pengecualian ini terjadi, aplikasi perlu meminta pengguna untuk bergabung kembali ke saluran. | SDK dapat memulihkan diri secara otomatis dari pemutusan jaringan dalam periode tertentu. Namun, jika waktu pemutusan melebihi ambang batas yang telah ditentukan, terjadi timeout dan koneksi terputus. Dalam kasus ini, aplikasi harus memeriksa status jaringan dan memandu pengguna untuk bergabung kembali ke saluran. |
Dikeluarkan dari jaringan |
|
| Layanan RTC memungkinkan administrator menghapus peserta. |
Pengecualian perangkat lokal |
| Jika pengecualian ini terjadi, aplikasi perlu memeriksa izin dan apakah perangkat keras berfungsi dengan baik. | Layanan RTC mendukung pendeteksian perangkat dan diagnostik. Saat terjadi pengecualian perangkat lokal, layanan RTC memberi tahu klien melalui callback. Jika SDK tidak dapat menyelesaikan masalah tersebut, aplikasi perlu melakukan intervensi untuk memeriksa status perangkat. |
extension VideoCallMainVC: AliRtcEngineDelegate {
func onJoinChannelResult(_ result: Int32, channel: String, elapsed: Int32) {
"onJoinChannelResult1 result: \(result)".printLog()
}
func onJoinChannelResult(_ result: Int32, channel: String, userId: String, elapsed: Int32) {
"onJoinChannelResult2 result: \(result)".printLog()
}
func onRemoteUser(onLineNotify uid: String, elapsed: Int32) {
// Pengguna jarak jauh online.
"onRemoteUserOlineNotify uid: \(uid)".printLog()
}
func onRemoteUserOffLineNotify(_ uid: String, offlineReason reason: AliRtcUserOfflineReason) {
// Pengguna jarak jauh offline.
"onRemoteUserOffLineNotify uid: \(uid) reason: \(reason)".printLog()
}
func onRemoteTrackAvailableNotify(_ uid: String, audioTrack: AliRtcAudioTrack, videoTrack: AliRtcVideoTrack) {
"onRemoteTrackAvailableNotify uid: \(uid) audioTrack: \(audioTrack) videoTrack: \(videoTrack)".printLog()
}
func onAuthInfoWillExpire() {
"onAuthInfoWillExpire".printLog()
/* TODO: Anda harus menangani callback ini. Token akan segera kedaluwarsa. Aplikasi Anda harus mendapatkan token baru untuk saluran dan pengguna saat ini, lalu memanggil refreshAuthInfo. */
}
func onAuthInfoExpired() {
"onAuthInfoExpired".printLog()
/* TODO: Anda harus menangani callback ini. Beri tahu pengguna bahwa token telah kedaluwarsa, lalu tinggalkan saluran dan lepaskan mesin. */
}
func onBye(_ code: Int32) {
"onBye code: \(code)".printLog()
/* TODO: Anda harus menangani callback ini. Bisnis Anda mungkin memicu skenario di mana perangkat berbeda dengan ID pengguna yang sama bersaing untuk akses. */
}
func onLocalDeviceException(_ deviceType: AliRtcLocalDeviceType, exceptionType: AliRtcLocalDeviceExceptionType, message msg: String?) {
"onLocalDeviceException deviceType: \(deviceType) exceptionType: \(exceptionType)".printLog()
/* TODO: Anda harus menangani callback ini. Kami merekomendasikan agar aplikasi Anda memberi tahu pengguna tentang kesalahan perangkat. Callback ini dipicu hanya setelah SDK telah mencoba semua kebijakan pemulihan namun masih tidak dapat melanjutkan. */
}
func onConnectionStatusChange(_ status: AliRtcConnectionStatus, reason: AliRtcConnectionStatusChangeReason) {
"onConnectionStatusChange status: \(status) reason: \(reason)".printLog()
if status == .failed {
/* TODO: Anda harus menangani callback ini. Kami merekomendasikan agar aplikasi Anda memberi tahu pengguna. Callback ini dipicu hanya setelah SDK telah mencoba semua kebijakan pemulihan namun masih tidak dapat melanjutkan. */
}
else {
/* TODO: Opsional. Tambahkan logika bisnis, biasanya untuk statistik data atau perubahan UI. */
}
}
}4. Konfigurasi properti pengambilan dan penarikan aliran
Secara default, SDK secara otomatis melakukan pengambilan dan menarik aliran audio dan video dalam saluran.
Setelah Anda mengatur peran menjadi penonton, pengguna hanya dapat menarik aliran. Metode publishLocalAudioStream menjadi tidak berlaku.
Konfigurasi berikut dapat diatur baik untuk streamer maupun penonton.
// Atur profil audio. Secara default, mode berkualitas tinggi (AliRtcEngineHighQualityMode) dan mode musik (AliRtcAudioScenario.sceneMusicMode) digunakan.
engine.setAudioProfile(AliRtcAudioProfile.engineHighQualityMode, audio_scene: AliRtcAudioScenario.sceneMusicMode)
// Untuk skenario obrolan suara, Anda tidak perlu mempublikasikan aliran video.
engine.publishLocalVideoStream(false)
// Atur langganan default ke aliran audio jarak jauh.
engine.setDefaultSubscribeAllRemoteAudioStreams(true)
engine.subscribeAllRemoteAudioStreams(true)5. Bergabung ke saluran untuk memulai interaksi hanya audio
Anda dapat memanggil metode joinChannel untuk bergabung ke saluran.
Catatan:
Jika token dihasilkan menggunakan aturan parameter tunggal, Anda harus memanggil metode joinChannel[1/3] parameter tunggal SDK. Jika token dihasilkan menggunakan aturan multi-parameter, Anda harus memanggil metode joinChannel[2/3] multi-parameter SDK. Setelah Anda memanggil metode untuk bergabung ke saluran, Anda dapat mengambil hasilnya dari callback onJoinChannelResult. Jika hasilnya 0, pengguna berhasil bergabung ke saluran. Jika tidak, periksa apakah token valid.
self.rtcEngine?.joinChannel(joinToken, channelId: nil, userId: nil, name: nil) 6. Mengakhiri interaksi hanya audio
Saat interaksi audio berakhir, Anda perlu meninggalkan saluran dan menghapus mesin. Untuk mengakhiri interaksi audio dan video, lakukan langkah-langkah berikut:
Panggil
leaveChanneluntuk meninggalkan saluran.Panggil
destroyuntuk menghapus mesin dan melepaskan sumber dayanya.
self.rtcEngine?.leaveChannel()
AliRtcEngine.destroy()
self.rtcEngine = nil7. (Opsional) Izinkan penonton mengaktifkan dan menonaktifkan mikrofon
Dalam skenario bisnis Anda, jika pengguna dengan peran penonton ingin melakukan pengambilan aliran, Anda dapat memanggil metode setClientRole untuk mengubah perannya menjadi streamer.
// Ubah ke peran streamer.
self.rtcEngine?.setClientRole(AliRtcClientRole.roleInteractive)
// Ubah ke peran penonton.
self.rtcEngine?.setClientRole(AliRtcClientRole.rolelive)Referensi
Untuk informasi selengkapnya tentang operasi audio, seperti pemantauan in-ear, pengaturan volume, dan callback speaker, lihat Operasi dan konfigurasi audio umum.
Untuk mengatur efek vokal, seperti pengubah suara, pemercantik, dan gema, lihat Atur pengubah suara, gema, dan pemercantik.
Untuk memutar file audio musik latar atau iringan, lihat Putar dan ambil input audio eksternal (termasuk efek suara dan iringan).