Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.
Menerbitkan & Berlangganan dengan Siaran IVS Android SDK | Streaming Waktu Nyata
Dokumen ini membawa Anda melalui langkah-langkah yang terlibat dalam penerbitan dan berlangganan ke panggung menggunakan siaran SDK Android streaming IVS waktu nyata.
Konsep
Tiga konsep inti mendasari fungsionalitas real-time: panggung, strategi, dan penyaji. Tujuan desain adalah meminimalkan jumlah logika sisi klien yang diperlukan untuk membangun produk yang berfungsi.
Stage
Stage
Kelas adalah titik utama interaksi antara aplikasi host danSDK. Ini mewakili panggung itu sendiri dan digunakan untuk bergabung dan meninggalkan panggung. Membuat dan menggabungkan tahap membutuhkan string token yang valid dan belum kedaluwarsa dari bidang kontrol (direpresentasikan sebagaitoken
). Bergabung dan meninggalkan panggung itu sederhana.
Stage stage = new Stage(context, token, strategy); try { stage.join(); } catch (BroadcastException exception) { // handle join exception } stage.leave();
Stage
Kelas juga di mana StageRenderer
dapat dilampirkan:
stage.addRenderer(renderer); // multiple renderers can be added
Strategi
Stage.Strategy
Antarmuka menyediakan cara bagi aplikasi host untuk mengkomunikasikan keadaan panggung yang diinginkan keSDK. Tiga fungsi perlu diimplementasikan:shouldSubscribeToParticipant
,shouldPublishFromParticipant
, danstageStreamsToPublishForParticipant
. Semua dibahas di bawah ini.
Berlangganan Peserta
Stage.SubscribeType shouldSubscribeToParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo);
Ketika peserta jarak jauh bergabung dengan panggung, SDK pertanyaan aplikasi host tentang status langganan yang diinginkan untuk peserta tersebut. Pilihannya adalahNONE
,AUDIO_ONLY
, danAUDIO_VIDEO
. Saat mengembalikan nilai untuk fungsi ini, aplikasi host tidak perlu khawatir tentang status publikasi, status langganan saat ini, atau status koneksi tahap. Jika AUDIO_VIDEO
dikembalikan, SDK menunggu hingga peserta jarak jauh mempublikasikan sebelum berlangganan, dan memperbarui aplikasi host melalui penyaji selama proses berlangsung.
Berikut adalah contoh implementasi:
@Override Stage.SubscribeType shouldSubscribeToParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) { return Stage.SubscribeType.AUDIO_VIDEO; }
Ini adalah implementasi lengkap dari fungsi ini untuk aplikasi host yang selalu ingin semua peserta saling bertemu; misalnya, aplikasi obrolan video.
Implementasi yang lebih maju juga dimungkinkan. Gunakan userInfo
properti ParticipantInfo
untuk berlangganan peserta secara selektif berdasarkan atribut yang disediakan server:
@Override Stage.SubscribeType shouldSubscribeToParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) { switch(participantInfo.userInfo.get(“role”)) { case “moderator”: return Stage.SubscribeType.NONE; case “guest”: return Stage.SubscribeType.AUDIO_VIDEO; default: return Stage.SubscribeType.NONE; } }
Ini dapat digunakan untuk membuat panggung di mana moderator dapat memantau semua tamu tanpa terlihat atau didengar sendiri. Aplikasi host dapat menggunakan logika bisnis tambahan untuk membiarkan moderat melihat satu sama lain tetapi tetap tidak terlihat oleh tamu.
Konfigurasi untuk Berlangganan Peserta
SubscribeConfiguration subscribeConfigurationForParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo);
Jika peserta jarak jauh sedang berlangganan (lihat Berlangganan Peserta), akan SDK menanyakan aplikasi host tentang konfigurasi langganan khusus untuk peserta tersebut. Konfigurasi ini bersifat opsional dan memungkinkan aplikasi host untuk mengontrol aspek-aspek tertentu dari perilaku pelanggan. Untuk informasi tentang apa yang dapat dikonfigurasi, lihat SubscribeConfiguration
Berikut adalah contoh implementasi:
@Override public SubscribeConfiguration subscribeConfigrationForParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) { SubscribeConfiguration config = new SubscribeConfiguration(); config.jitterBuffer.setMinDelay(JitterBufferConfiguration.JitterBufferDelay.MEDIUM()); return config; }
Implementasi ini memperbarui penundaan minimum jitter-buffer untuk semua peserta berlangganan ke preset. MEDIUM
Seperti halnyashouldSubscribeToParticipant
, implementasi yang lebih maju dimungkinkan. Yang diberikan ParticipantInfo
dapat digunakan untuk memperbarui konfigurasi berlangganan secara selektif untuk peserta tertentu.
Sebaiknya gunakan perilaku default. Tentukan konfigurasi khusus hanya jika ada perilaku tertentu yang ingin Anda ubah.
Publikasi
boolean shouldPublishFromParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo);
Setelah terhubung ke panggung, SDK kueri aplikasi host untuk melihat apakah peserta tertentu harus mempublikasikan. Ini hanya dipanggil pada peserta lokal yang memiliki izin untuk mempublikasikan berdasarkan token yang disediakan.
Berikut adalah contoh implementasi:
@Override boolean shouldPublishFromParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) { return true; }
Ini untuk aplikasi obrolan video standar di mana pengguna selalu ingin mempublikasikan. Mereka dapat membisukan dan menonaktifkan audio dan video mereka, untuk langsung disembunyikan atau seen/heard. (They also can use publish/unpublish, but that is much slower. Mute/unmute lebih disukai untuk kasus penggunaan di mana mengubah visibilitas sering diinginkan.)
Memilih Streaming untuk Publikasikan
@Override List<LocalStageStream> stageStreamsToPublishForParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo); }
Saat menerbitkan, ini digunakan untuk menentukan aliran audio dan video apa yang harus dipublikasikan. Ini dibahas secara lebih rinci nanti di Publish a Media Stream.
Memperbarui Strategi
Strategi ini dimaksudkan untuk menjadi dinamis: nilai yang dikembalikan dari salah satu fungsi di atas dapat diubah kapan saja. Misalnya, jika aplikasi host tidak ingin mempublikasikan sampai pengguna akhir mengetuk tombol, Anda dapat mengembalikan variabel dari shouldPublishFromParticipant
(sesuatu sepertihasUserTappedPublishButton
). Ketika variabel itu berubah berdasarkan interaksi oleh pengguna akhir, panggil stage.refreshStrategy()
untuk memberi sinyal kepada SDK bahwa ia harus menanyakan strategi untuk nilai terbaru, hanya menerapkan hal-hal yang telah berubah. Jika SDK mengamati bahwa shouldPublishFromParticipant
nilainya telah berubah, itu akan memulai proses publikasi. Jika SDK kueri dan semua fungsi mengembalikan nilai yang sama seperti sebelumnya, refreshStrategy
panggilan tidak akan melakukan modifikasi apa pun pada panggung.
Jika nilai pengembalian shouldSubscribeToParticipant
perubahan dari AUDIO_VIDEO
keAUDIO_ONLY
, aliran video akan dihapus untuk semua peserta dengan nilai yang dikembalikan diubah, jika aliran video ada sebelumnya.
Umumnya, tahap menggunakan strategi untuk menerapkan perbedaan antara strategi sebelumnya dan saat ini secara efisien, tanpa aplikasi host perlu khawatir tentang semua keadaan yang diperlukan untuk mengelolanya dengan benar. Karena itu, anggap menelepon stage.refreshStrategy()
sebagai operasi yang murah, karena tidak melakukan apa-apa kecuali strateginya berubah.
Penyaji
StageRenderer
Antarmuka mengkomunikasikan keadaan panggung ke aplikasi host. Pembaruan pada UI aplikasi host biasanya dapat didukung sepenuhnya oleh peristiwa yang disediakan oleh perender. Penyaji menyediakan fungsi-fungsi berikut:
void onParticipantJoined(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo); void onParticipantLeft(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo); void onParticipantPublishStateChanged(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull Stage.PublishState publishState); void onParticipantSubscribeStateChanged(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull Stage.SubscribeState subscribeState); void onStreamsAdded(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull List<StageStream> streams); void onStreamsRemoved(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull List<StageStream> streams); void onStreamsMutedChanged(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull List<StageStream> streams); void onError(@NonNull BroadcastException exception); void onConnectionStateChanged(@NonNull Stage stage, @NonNull Stage.ConnectionState state, @Nullable BroadcastException exception);
Untuk sebagian besar metode ini, yang sesuai Stage
dan ParticipantInfo
disediakan.
Tidak diharapkan bahwa informasi yang diberikan oleh penyaji berdampak pada nilai pengembalian strategi. Misalnya, nilai pengembalian shouldSubscribeToParticipant
tidak diharapkan berubah ketika onParticipantPublishStateChanged
dipanggil. Jika aplikasi host ingin berlangganan ke peserta tertentu, itu harus mengembalikan jenis langganan yang diinginkan terlepas dari status publikasi peserta tersebut. Bertanggung SDK jawab untuk memastikan bahwa keadaan strategi yang diinginkan ditindaklanjuti pada waktu yang tepat berdasarkan keadaan panggung.
StageRenderer
Dapat dilampirkan ke kelas panggung:
stage.addRenderer(renderer); // multiple renderers can be added
Perhatikan bahwa hanya peserta penerbitan yang dipicuonParticipantJoined
, dan setiap kali peserta berhenti menerbitkan atau meninggalkan sesi panggung, onParticipantLeft
dipicu.
Publikasikan Aliran Media
Perangkat lokal seperti mikrofon dan kamera internal ditemukan melaluiDeviceDiscovery
. Berikut adalah contoh memilih kamera yang menghadap ke depan dan mikrofon default, lalu mengembalikannya seperti yang akan LocalStageStreams
dipublikasikan oleh: SDK
DeviceDiscovery deviceDiscovery = new DeviceDiscovery(context); List<Device> devices = deviceDiscovery.listLocalDevices(); List<LocalStageStream> publishStreams = new ArrayList<LocalStageStream>(); Device frontCamera = null; Device microphone = null; // Create streams using the front camera, first microphone for (Device device : devices) { Device.Descriptor descriptor = device.getDescriptor(); if (!frontCamera && descriptor.type == Device.Descriptor.DeviceType.Camera && descriptor.position = Device.Descriptor.Position.FRONT) { front Camera = device; } if (!microphone && descriptor.type == Device.Descriptor.DeviceType.Microphone) { microphone = device; } } ImageLocalStageStream cameraStream = new ImageLocalStageStream(frontCamera); AudioLocalStageStream microphoneStream = new AudioLocalStageStream(microphoneDevice); publishStreams.add(cameraStream); publishStreams.add(microphoneStream); // Provide the streams in Stage.Strategy @Override @NonNull List<LocalStageStream> stageStreamsToPublishForParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) { return publishStreams; }
Tampilkan dan Hapus Peserta
Setelah berlangganan selesai, Anda akan menerima array StageStream
objek melalui fungsi renderer. onStreamsAdded
Anda dapat mengambil pratinjau dari: ImageStageStream
ImagePreviewView preview = ((ImageStageStream)stream).getPreview(); // Add the view to your view hierarchy LinearLayout previewHolder = findViewById(R.id.previewHolder); preview.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); previewHolder.addView(preview);
Anda dapat mengambil statistik tingkat audio dari: AudioStageStream
((AudioStageStream)stream).setStatsCallback((peak, rms) -> { // handle statistics });
Ketika peserta berhenti menerbitkan atau berhenti berlangganan, onStreamsRemoved
fungsi dipanggil dengan aliran yang telah dihapus. Aplikasi host harus menggunakan ini sebagai sinyal untuk menghapus aliran video peserta dari hierarki tampilan.
onStreamsRemoved
dipanggil untuk semua skenario di mana aliran mungkin dihapus, termasuk:
-
Peserta jarak jauh berhenti menerbitkan.
-
Perangkat lokal berhenti berlangganan atau mengubah langganan dari ke
AUDIO_VIDEO
.AUDIO_ONLY
-
Peserta jarak jauh meninggalkan panggung.
-
Peserta lokal meninggalkan panggung.
Karena onStreamsRemoved
dipanggil untuk semua skenario, tidak diperlukan logika bisnis khusus untuk menghapus peserta dari UI selama operasi cuti jarak jauh atau lokal.
Bisukan dan Bunyikan Streaming Media
LocalStageStream
objek memiliki setMuted
fungsi yang mengontrol apakah aliran diredam. Fungsi ini dapat dipanggil pada aliran sebelum atau sesudah dikembalikan dari fungsi streamsToPublishForParticipant
strategi.
Penting: Jika instance LocalStageStream
objek baru dikembalikan streamsToPublishForParticipant
setelah panggilan kerefreshStrategy
, status bisu objek aliran baru diterapkan ke panggung. Hati-hati saat membuat LocalStageStream
instance baru untuk memastikan status bisu yang diharapkan dipertahankan.
Pantau Status Bisu Media Peserta Jarak Jauh
Saat peserta mengubah status bisu aliran video atau audio mereka, onStreamMutedChanged
fungsi penyaji dipanggil dengan daftar aliran yang telah berubah. Gunakan getMuted
metode ini StageStream
untuk memperbarui UI Anda sesuai dengan itu.
@Override void onStreamsMutedChanged(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull List<StageStream> streams) { for (StageStream stream : streams) { boolean muted = stream.getMuted(); // handle UI changes } }
Dapatkan RTC Statistik Web
Untuk mendapatkan RTC statistik Web terbaru untuk aliran penerbitan atau aliran berlangganan, gunakan requestRTCStats
terusStageStream
. Ketika koleksi selesai, Anda akan menerima statistik melalui StageStream.Listener
yang dapat diaturStageStream
.
stream.requestRTCStats(); @Override void onRTCStats(Map<String, Map<String, String>> statsMap) { for (Map.Entry<String, Map<String, string>> stat : statsMap.entrySet()) { for(Map.Entry<String, String> member : stat.getValue().entrySet()) { Log.i(TAG, stat.getKey() + “ has member “ + member.getKey() + “ with value “ + member.getValue()); } } }
Dapatkan Atribut Peserta
Jika Anda menentukan atribut dalam permintaan CreateParticipantToken
titik akhir, Anda dapat melihat atribut di ParticipantInfo
properti:
@Override void onParticipantJoined(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) { for (Map.Entry<String, String> entry : participantInfo.userInfo.entrySet()) { Log.i(TAG, “attribute: “ + entry.getKey() + “ = “ + entry.getValue()); } }
Lanjutkan Sesi di Latar Belakang
Saat aplikasi memasuki latar belakang, Anda mungkin ingin berhenti menerbitkan atau berlangganan hanya audio peserta jarak jauh lainnya. Untuk mencapai hal ini, perbarui Strategy
implementasi Anda untuk menghentikan penerbitan, dan berlangganan AUDIO_ONLY
(atauNONE
, jika ada).
// Local variables before going into the background boolean shouldPublish = true; Stage.SubscribeType subscribeType = Stage.SubscribeType.AUDIO_VIDEO; // Stage.Strategy implementation @Override boolean shouldPublishFromParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) { return shouldPublish; } @Override Stage.SubscribeType shouldSubscribeToParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) { return subscribeType; } // In our Activity, modify desired publish/subscribe when we go to background, then call refreshStrategy to update the stage @Override void onStop() { super.onStop(); shouldPublish = false; subscribeTpye = Stage.SubscribeType.AUDIO_ONLY; stage.refreshStrategy(); }
Aktifkan/Nonaktifkan Layered Encoding dengan Simulcast
Saat menerbitkan aliran media, SDK mentransmisikan aliran video berkualitas tinggi dan berkualitas rendah, sehingga peserta jarak jauh dapat berlangganan streaming meskipun mereka memiliki bandwidth downlink terbatas. Pengkodean berlapis dengan simulcast aktif secara default. Anda dapat menonaktifkannya dengan menggunakan StageVideoConfiguration.Simulcast
kelas:
// Disable Simulcast StageVideoConfiguration config = new StageVideoConfiguration(); config.simulcast.setEnabled(false); ImageLocalStageStream cameraStream = new ImageLocalStageStream(frontCamera, config); // Other Stage implementation code
Batasan Konfigurasi Video
SDKTidak mendukung pemaksaan mode potret atau mode lanskap menggunakanStageVideoConfiguration.setSize(BroadcastConfiguration.Vec2 size)
. Dalam orientasi potret, dimensi yang lebih kecil digunakan sebagai lebar; dalam orientasi lanskap, tinggi. Ini berarti bahwa dua panggilan berikut setSize
memiliki efek yang sama pada konfigurasi video:
StageVideo Configuration config = new StageVideo Configuration(); config.setSize(BroadcastConfiguration.Vec2(720f, 1280f); config.setSize(BroadcastConfiguration.Vec2(1280f, 720f);
Menangani Masalah Jaringan
Ketika koneksi jaringan perangkat lokal terputus, SDK internal mencoba untuk menyambung kembali tanpa tindakan pengguna. Dalam beberapa kasus, SDK tidak berhasil dan tindakan pengguna diperlukan. Ada dua kesalahan utama yang terkait dengan kehilangan koneksi jaringan:
-
Kode kesalahan 1400, pesan: "PeerConnection hilang karena kesalahan jaringan yang tidak diketahui”
-
Kode kesalahan 1300, pesan: “Coba lagi upaya habis”
Jika kesalahan pertama diterima tetapi yang kedua tidak, SDK masih terhubung ke panggung dan akan mencoba membangun kembali koneksinya secara otomatis. Sebagai pengaman, Anda dapat memanggil refreshStrategy
tanpa perubahan apa pun pada nilai pengembalian metode strategi, untuk memicu upaya penyambungan kembali manual.
Jika kesalahan kedua diterima, upaya penyambungan kembali gagal dan perangkat lokal tidak lagi terhubung ke panggung. SDK Dalam hal ini, cobalah untuk bergabung kembali dengan panggung dengan menelepon join
setelah koneksi jaringan Anda dibangun kembali.
Secara umum, menemukan kesalahan setelah bergabung dengan tahap berhasil menunjukkan bahwa tidak SDK berhasil dalam membangun kembali koneksi. Buat Stage
objek baru dan cobalah untuk bergabung ketika kondisi jaringan membaik.
Menggunakan Mikrofon Bluetooth
Untuk mempublikasikan menggunakan perangkat mikrofon Bluetooth, Anda harus memulai SCO koneksi Bluetooth:
Bluetooth.startBluetoothSco(context); // Now bluetooth microphones can be used … // Must also stop bluetooth SCO Bluetooth.stopBluetoothSco(context);