View a markdown version of this page

Penerbitan & Berlangganan dengan IVS Web Broadcast SDK | Streaming Real-Time - Amazon IVS

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Penerbitan & Berlangganan dengan IVS Web Broadcast SDK | Streaming Real-Time

Dokumen ini membawa Anda melalui langkah-langkah yang terlibat dalam penerbitan dan berlangganan ke panggung menggunakan SDK siaran Web streaming waktu nyata IVS.

Konsep

Tiga konsep inti mendasari fungsionalitas waktu nyata: panggung, strategi, dan acara. Tujuan desain adalah meminimalkan jumlah logika sisi klien yang diperlukan untuk membangun produk yang berfungsi.

Stage

StageKelas adalah titik utama interaksi antara aplikasi host dan SDK. Ini mewakili panggung itu sendiri dan digunakan untuk bergabung dan meninggalkan panggung. Membuat dan bergabung dengan tahap memerlukan string token yang valid dan belum kedaluwarsa dari bidang kontrol (direpresentasikan sebagaitoken). Bergabung dan meninggalkan panggung itu sederhana:

const stage = new Stage(token, strategy) try { await stage.join(); } catch (error) { // handle join exception } stage.leave();

Strategi

Antar StageStrategy muka menyediakan cara bagi aplikasi host untuk mengkomunikasikan keadaan panggung yang diinginkan ke SDK. Tiga fungsi perlu diimplementasikan:shouldSubscribeToParticipant,shouldPublishParticipant, danstageStreamsToPublish. Semua dibahas di bawah ini.

Untuk menggunakan strategi yang ditentukan, berikan ke Stage konstruktor. Berikut ini adalah contoh lengkap aplikasi yang menggunakan strategi untuk mempublikasikan webcam peserta ke panggung dan berlangganan semua peserta. Setiap tujuan fungsi strategi yang diperlukan dijelaskan secara rinci di bagian selanjutnya.

const devices = await navigator.mediaDevices.getUserMedia({ audio: true, video: { width: { max: 1280 }, height: { max: 720 }, } }); const myAudioTrack = new LocalStageStream(devices.getAudioTracks()[0]); const myVideoTrack = new LocalStageStream(devices.getVideoTracks()[0]); // Define the stage strategy, implementing required functions const strategy = { audioTrack: myAudioTrack, videoTrack: myVideoTrack, // optional updateTracks(newAudioTrack, newVideoTrack) { this.audioTrack = newAudioTrack; this.videoTrack = newVideoTrack; }, // required stageStreamsToPublish() { return [this.audioTrack, this.videoTrack]; }, // required shouldPublishParticipant(participant) { return true; }, // required shouldSubscribeToParticipant(participant) { return SubscribeType.AUDIO_VIDEO; } }; // Initialize the stage and start publishing const stage = new Stage(token, strategy); await stage.join(); // To update later (e.g. in an onClick event handler) strategy.updateTracks(myNewAudioTrack, myNewVideoTrack); stage.refreshStrategy();

Berlangganan Peserta

shouldSubscribeToParticipant(participant: StageParticipantInfo): SubscribeType

Ketika peserta jarak jauh bergabung dengan panggung, SDK menanyakan 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 menerbitkan sebelum berlangganan, dan memperbarui aplikasi host dengan memancarkan peristiwa selama proses berlangsung.

Berikut adalah contoh implementasi:

const strategy = { shouldSubscribeToParticipant: (participant) => { return SubscribeType.AUDIO_VIDEO; } // ... other strategy functions }

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. Misalnya, asumsikan aplikasi menyediakan role atribut saat membuat token dengan CreateParticipantToken. Aplikasi dapat menggunakan attributes properti StageParticipantInfo untuk secara selektif berlangganan peserta berdasarkan atribut yang disediakan server:

const strategy = { shouldSubscribeToParticipant(participant) { switch (participant.attributes.role) { case 'moderator': return SubscribeType.NONE; case 'guest': return SubscribeType.AUDIO_VIDEO; default: return SubscribeType.NONE; } } // . . . other strategies properties }

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 moderator melihat satu sama lain tetapi tetap tidak terlihat oleh tamu.

Konfigurasi untuk Berlangganan Peserta

subscribeConfiguration(participant: StageParticipantInfo): SubscribeConfiguration

Jika peserta jarak jauh sedang berlangganan (lihat Berlangganan Peserta), SDK menanyakan aplikasi host tentang konfigurasi langganan khusus untuk peserta tersebut. Konfigurasi ini opsional dan memungkinkan aplikasi host untuk mengontrol aspek-aspek tertentu dari perilaku pelanggan. Untuk informasi tentang apa yang dapat dikonfigurasi, lihat SubscribeConfiguration di dokumentasi referensi SDK.

Berikut adalah contoh implementasi:

const strategy = { subscribeConfiguration: (participant) => { return { jitterBuffer: { minDelay: JitterBufferMinDelay.MEDIUM } } // ... other strategy functions }

Implementasi ini memperbarui penundaan minimum jitter-buffer untuk semua peserta yang 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

shouldPublishParticipant(participant: StageParticipantInfo): boolean

Setelah terhubung ke panggung, SDK menanyakan 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:

const strategy = { shouldPublishParticipant: (participant) => { return true; } // . . . other strategies properties }

Ini untuk aplikasi obrolan video standar di mana pengguna selalu ingin mempublikasikan. Mereka dapat membisukan dan mematikan audio dan video mereka, untuk langsung disembunyikan atau seen/heard. (Mereka juga bisa menggunakan publish/unpublish, tetapi itu jauh lebih lambat. Mute/unmute lebih disukai untuk kasus penggunaan di mana perubahan visibilitas sering diinginkan.)

Memilih Streaming untuk Dipublikasikan

stageStreamsToPublish(): LocalStageStream[];

Saat menerbitkan, ini digunakan untuk menentukan aliran audio dan video apa yang harus dipublikasikan. Ini dibahas secara lebih rinci nanti di Publikasikan Aliran Media.

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 shouldPublishParticipant (sesuatu sepertihasUserTappedPublishButton). Ketika variabel itu berubah berdasarkan interaksi oleh pengguna akhir, panggil stage.refreshStrategy() untuk memberi sinyal ke SDK bahwa ia harus menanyakan strategi untuk nilai terbaru, hanya menerapkan hal-hal yang telah berubah. Jika SDK mengamati bahwa nil shouldPublishParticipant ainya telah berubah, itu memulai proses publikasi. Jika kueri SDK dan semua fungsi mengembalikan nilai yang sama seperti sebelumnya, refreshStrategy panggilan tidak mengubah stage.

Jika nilai pengembalian shouldSubscribeToParticipant berubah dari AUDIO_VIDEO keAUDIO_ONLY, aliran video dihapus untuk semua peserta dengan nilai yang dikembalikan yang diubah, jika aliran video ada sebelumnya.

Umumnya, tahap menggunakan strategi untuk paling efisien menerapkan perbedaan antara strategi sebelumnya dan saat ini, tanpa aplikasi host perlu khawatir tentang semua keadaan yang diperlukan untuk mengelolanya dengan benar. Karena itu, anggap menelepon stage.refreshStrategy() sebagai operasi murah, karena tidak ada gunanya kecuali strateginya berubah.

Peristiwa

Sebuah Stage contoh adalah pemancar peristiwa. Menggunakanstage.on(), keadaan panggung dikomunikasikan ke aplikasi host. Pembaruan pada UI aplikasi host biasanya dapat didukung sepenuhnya oleh acara. Peristiwa tersebut adalah sebagai berikut:

stage.on(StageEvents.STAGE_CONNECTION_STATE_CHANGED, (state) => {}) stage.on(StageEvents.STAGE_PARTICIPANT_JOINED, (participant) => {}) stage.on(StageEvents.STAGE_PARTICIPANT_LEFT, (participant) => {}) stage.on(StageEvents.STAGE_PARTICIPANT_PUBLISH_STATE_CHANGED, (participant, state) => {}) stage.on(StageEvents.STAGE_PARTICIPANT_SUBSCRIBE_STATE_CHANGED, (participant, state) => {}) stage.on(StageEvents.STAGE_PARTICIPANT_STREAMS_ADDED, (participant, streams) => {}) stage.on(StageEvents.STAGE_PARTICIPANT_STREAMS_REMOVED, (participant, streams) => {}) stage.on(StageEvents.STAGE_STREAM_ADAPTION_CHANGED, (participant, stream, isAdapting) => ()) stage.on(StageEvents.STAGE_STREAM_LAYERS_CHANGED, (participant, stream, layers) => ()) stage.on(StageEvents.STAGE_STREAM_LAYER_SELECTED, (participant, stream, layer, reason) => ()) stage.on(StageEvents.STAGE_STREAM_MUTE_CHANGED, (participant, stream) => {}) stage.on(StageEvents.STAGE_STREAM_SEI_MESSAGE_RECEIVED, (participant, stream) => {})

Untuk sebagian besar acara ini, yang sesuai ParticipantInfo disediakan.

Tidak diharapkan bahwa informasi yang diberikan oleh peristiwa berdampak pada nilai pengembalian strategi. Misalnya, nilai pengembalian tidak shouldSubscribeToParticipant diharapkan berubah saat STAGE_PARTICIPANT_PUBLISH_STATE_CHANGED dipanggil. Jika aplikasi host ingin berlangganan peserta tertentu, aplikasi tersebut harus mengembalikan jenis langganan yang diinginkan terlepas dari status publikasi peserta tersebut. SDK bertanggung jawab untuk memastikan bahwa keadaan strategi yang diinginkan ditindaklanjuti pada waktu yang tepat berdasarkan keadaan panggung.

Publikasikan Aliran Media

Perangkat lokal seperti mikrofon dan kamera diambil menggunakan langkah-langkah yang sama seperti yang diuraikan di atas dalam Mengambil MediaStream dari Perangkat. Dalam contoh yang kita gunakan MediaStream untuk membuat daftar LocalStageStream objek yang digunakan untuk penerbitan oleh SDK:

try { // Get stream using steps outlined in document above const stream = await getMediaStreamFromDevice(); let streamsToPublish = stream.getTracks().map(track => { new LocalStageStream(track) }); // Create stage with strategy, or update existing strategy const strategy = { stageStreamsToPublish: () => streamsToPublish } }

Publikasikan Screenshare

Aplikasi sering perlu mempublikasikan screenshare selain kamera web pengguna. Menerbitkan screenshare mengharuskan pembuatan token tambahan untuk panggung, khususnya untuk menerbitkan media screenshare. Gunakan getDisplayMedia dan batasi resolusi hingga maksimum 720p. Setelah itu, langkah-langkahnya mirip dengan menerbitkan kamera ke panggung.

// Invoke the following lines to get the screenshare's tracks const media = await navigator.mediaDevices.getDisplayMedia({ video: { width: { max: 1280, }, height: { max: 720, } } }); const screenshare = { videoStream: new LocalStageStream(media.getVideoTracks()[0]) }; const screenshareStrategy = { stageStreamsToPublish: () => { return [screenshare.videoStream]; }, shouldPublishParticipant: (participant) => { return true; }, shouldSubscribeToParticipant: (participant) => { return SubscribeType.AUDIO_VIDEO; } } const screenshareStage = new Stage(screenshareToken, screenshareStrategy); await screenshareStage.join();

Tampilkan dan Hapus Peserta

Setelah berlangganan selesai, Anda menerima array StageStream objek melalui STAGE_PARTICIPANT_STREAMS_ADDED acara. Acara ini juga memberi Anda info peserta untuk membantu saat menampilkan aliran media:

stage.on(StageEvents.STAGE_PARTICIPANT_STREAMS_ADDED, (participant, streams) => { let streamsToDisplay = streams; if (participant.isLocal) { // Ensure to exclude local audio streams, otherwise echo will occur streamsToDisplay = streams.filter(stream => stream.streamType === StreamType.VIDEO) } // Create or find video element already available in your application const videoEl = getParticipantVideoElement(participant.id); // Attach the participants streams videoEl.srcObject = new MediaStream(); streamsToDisplay.forEach(stream => videoEl.srcObject.addTrack(stream.mediaStreamTrack)); })

Ketika peserta berhenti menerbitkan atau berhenti berlangganan dari aliran, STAGE_PARTICIPANT_STREAMS_REMOVED fungsi dipanggil dengan aliran yang telah dihapus. Aplikasi host harus menggunakan ini sebagai sinyal untuk menghapus aliran video peserta dari DOM.

STAGE_PARTICIPANT_STREAMS_REMOVEDdipanggil untuk semua skenario di mana aliran dapat dihapus, termasuk:

  • Peserta jarak jauh berhenti menerbitkan.

  • Perangkat lokal berhenti berlangganan atau mengubah langganan dari AUDIO_VIDEO ke. AUDIO_ONLY

  • Peserta jarak jauh meninggalkan panggung.

  • Peserta lokal meninggalkan panggung.

Karena STAGE_PARTICIPANT_STREAMS_REMOVED dipanggil untuk semua skenario, tidak ada logika bisnis khusus yang diperlukan untuk menghapus peserta dari UI selama operasi cuti jarak jauh atau lokal.

Bisukan dan Aktifkan Aliran Media

LocalStageStreamobjek memiliki setMuted fungsi yang mengontrol apakah aliran dibisukan. Fungsi ini dapat dipanggil pada aliran sebelum atau setelah dikembalikan dari fungsi stageStreamsToPublish strategi.

Penting: Jika instance LocalStageStream objek baru dikembalikan stageStreamsToPublish setelah panggilan kerefreshStrategy, status bisu objek aliran baru diterapkan ke panggung. Berhati-hatilah saat membuat LocalStageStream instance baru untuk memastikan status bisu yang diharapkan dipertahankan.

Memantau Status Bisu Media Peserta Jarak Jauh

Saat peserta mengubah status bisu video atau audio mereka, STAGE_STREAM_MUTE_CHANGED acara dipicu dengan daftar aliran yang telah berubah. Gunakan isMuted properti aktif StageStream untuk memperbarui UI Anda sesuai dengan itu:

stage.on(StageEvents.STAGE_STREAM_MUTE_CHANGED, (participant, stream) => { if (stream.streamType === 'video' && stream.isMuted) { // handle UI changes for video track getting muted } })

Selain itu, Anda dapat melihat StageParticipantInfo informasi status tentang apakah audio atau video dibisukan:

stage.on(StageEvents.STAGE_STREAM_MUTE_CHANGED, (participant, stream) => { if (participant.videoStopped || participant.audioMuted) { // handle UI changes for either video or audio } })

Dapatkan Statistik WebRTC

requestQualityStats()Metode ini menyediakan akses ke statistik WebRTC terperinci untuk aliran lokal dan jarak jauh. Ini tersedia pada keduanya LocalStageStream dan RemoteStageStream objek. Ini mengembalikan metrik kualitas komprehensif termasuk kualitas jaringan, statistik paket, informasi bitrate, dan metrik terkait bingkai.

Ini adalah metode asinkron yang dengannya Anda dapat mengambil statistik baik melalui wait atau dengan merangkai janji. Ini kembali undefined ketika statistik tidak tersedia; misalnya, aliran tidak aktif atau statistik internal tidak tersedia. Jika statistik tersedia, dan tergantung pada aliran (jarak jauh atau lokal, video atau audio), metode mengembalikan sebuah LocalVideoStats, LocalAudioStats, RemoteVideoStats, atau RemoteAudioStats objek.

Perhatikan bahwa untuk streaming video dengan simulcast, array berisi beberapa objek stat (satu per lapisan).

Praktik Terbaik

  • Frekuensi polling — Panggil requestQualityStats() pada interval yang wajar (1-5 detik) untuk menghindari dampak kinerja

  • Penanganan kesalahan - Selalu periksa apakah nilai yang dikembalikan undefined sebelum diproses

  • Manajemen memori — Hapus intervals/timeouts saat streaming tidak lagi diperlukan

  • Kualitas jaringan — Gunakan networkQuality untuk umpan balik pengguna mengenai kemungkinan degradasi yang disebabkan oleh jaringan. Lihat perinciannya di NetworkQuality.

Contoh Penggunaan

// For local streams const localStats = await localVideoStream.requestQualityStats(); const audioStats = await localAudioStream.requestQualityStats(); // For remote streams const remoteVideoStats = await remoteVideoStream.requestQualityStats(); const remoteAudioStats = await remoteAudioStream.requestQualityStats(); // Example: Monitor stats every 10 seconds const statsInterval = setInterval(async () => { const stats = await localVideoStream.requestQualityStats(); if (stats) { // Note: If simulcast is enabled, you may receive multiple // stats records for each layer stats.forEach(layer => { const rid = layer.rid || 'default'; console.log(`Layer ${rid}:`, { active: layer.active, networkQuality: layer.networkQuality, packetsSent: layer.packetsSent, bytesSent: layer.bytesSent, resolution: `${layer.frameWidth}x${layer.frameHeight}`, fps: layer.framesPerSecond }); }); } }, 10000);

Mengoptimalkan Media

Disarankan untuk membatasi getUserMedia dan getDisplayMedia memanggil batasan berikut untuk kinerja terbaik:

const CONSTRAINTS = { video: { width: { ideal: 1280 }, // Note: flip width and height values if portrait is desired height: { ideal: 720 }, framerate: { ideal: 30 }, }, };

Anda dapat membatasi media lebih lanjut melalui opsi tambahan yang diteruskan ke LocalStageStream konstruktor:

const localStreamOptions = { minBitrate?: number; maxBitrate?: number; maxFramerate?: number; simulcast: { enabled: boolean } } const localStream = new LocalStageStream(track, localStreamOptions)

Dalam kode di atas:

  • minBitratemenetapkan bitrate minimum yang seharusnya digunakan browser. Namun, aliran video dengan kompleksitas rendah dapat mendorong encoder menjadi lebih rendah dari bitrate ini.

  • maxBitratemenetapkan bitrate maksimum yang seharusnya tidak melebihi browser untuk aliran ini.

  • maxFrameratemenetapkan kecepatan bingkai maksimum yang seharusnya tidak melebihi browser untuk aliran ini.

  • simulcastOpsi ini hanya dapat digunakan pada Chromium-based browser. Ini memungkinkan pengiriman tiga lapisan rendisi dari aliran.

    • Hal ini memungkinkan server untuk memilih rendisi mana yang akan dikirim ke peserta lain, berdasarkan keterbatasan jaringan mereka.

    • Ketika simulcast ditentukan bersama dengan maxBitrate and/or maxFramerate nilai, diharapkan lapisan rendisi tertinggi akan dikonfigurasi dengan mempertimbangkan nilai-nilai ini, asalkan maxBitrate tidak berada di bawah maxBitrate nilai default lapisan tertinggi kedua SDK internal 900 kbps.

    • Jika maxBitrate ditentukan terlalu rendah dibandingkan dengan nilai default lapisan tertinggi kedua, simulcast akan dinonaktifkan.

    • simulcasttidak dapat dinyalakan dan dimatikan tanpa menerbitkan ulang media melalui kombinasi kembali, meneleponfalse, shouldPublishParticipant shouldPublishParticipant kembali true dan menelep refreshStrategy on lagi. refreshStrategy

Dapatkan Atribut Peserta

Jika Anda menentukan atribut dalam permintaan CreateParticipantToken operasi, Anda dapat melihat atribut di StageParticipantInfo properti:

stage.on(StageEvents.STAGE_PARTICIPANT_JOINED, (participant) => { console.log(`Participant ${participant.id} info:`, participant.attributes); })

Informasi Peningkatan Tambahan (SEI)

Unit NAL Informasi Peningkatan Tambahan (SEI) digunakan untuk menyimpan metadata yang selaras dengan bingkai di samping video. Ini dapat digunakan saat menerbitkan dan berlangganan streaming H.264 video. Payload SEI tidak dijamin akan sampai ke pelanggan, terutama dalam kondisi jaringan yang buruk. Karena payload SEI menyimpan data langsung di dalam struktur H.264 bingkai, kemampuan ini tidak dapat dimanfaatkan untuk aliran audio saja.

Memasukkan Muatan SEI

Klien penerbitan dapat menyisipkan muatan SEI ke aliran tahap yang sedang dipublikasikan dengan mengonfigurasi video mereka LocalStageStream untuk mengaktifkan inBandMessaging dan kemudian memanggil metode. insertSeiMessage Perhatikan bahwa mengaktifkan inBandMessaging meningkatkan penggunaan memori SDK.

Muatan harus dari jen ArrayBuffer isnya. Ukuran payload harus lebih besar dari 0KB dan kurang dari 1KB. Jumlah pesan SEI yang dimasukkan per detik tidak boleh melebihi 10KB per detik.

const config = { inBandMessaging: { enabled: true } }; const vidStream = new LocalStageStream(videoTrack, config); const payload = new TextEncoder().encode('hello world').buffer; vidStream.insertSeiMessage(payload);

Berulang Payload SEI

Secara opsional berikan a repeatCount untuk mengulangi penyisipan muatan SEI untuk N frame berikutnya yang dikirim. Ini dapat membantu untuk mengurangi kerugian bawaan yang mungkin terjadi karena protokol transportasi UDP yang mendasari yang digunakan untuk mengirim video. Perhatikan nilai ini harus antara 0 dan 30. Klien penerima harus memiliki logika untuk menghapus duplikat pesan.

vidStream.insertSeiMessage(payload, { repeatCount: 5 }); // Optional config, repeatCount must be between 0 and 30

Membaca Muatan SEI

Klien yang berlangganan dapat membaca payload SEI dari penerbit yang menerbitkan H.264 video jika ada dengan mengonfigurasi pelanggan SubscribeConfiguration untuk mengaktifkan inBandMessaging dan mendengarkan StageEvents.STAGE_STREAM_SEI_MESSAGE_RECEIVED acara, seperti yang ditunjukkan dalam contoh berikut:

const strategy = { subscribeConfiguration: (participant) => { return { inBandMessaging: { enabled: true } } } // ... other strategy functions } stage.on(StageEvents.STAGE_STREAM_SEI_MESSAGE_RECEIVED, (participant, seiMessage) => { console.log(seiMessage.payload, seiMessage.uuid); });

Encoding Berlapis dengan Simulcast

Pengkodean berlapis dengan simulcast adalah fitur streaming real-time IVS yang memungkinkan penerbit mengirim beberapa lapisan kualitas video yang berbeda, dan pelanggan untuk mengubah lapisan tersebut secara dinamis atau manual. Fitur ini dijelaskan lebih lanjut dalam dokumen Pengoptim alan Streaming.

Mengkonfigurasi Pengkodean Berlapis (Penerbit)

Sebagai penerbit, untuk mengaktifkan pengkodean berlapis dengan simulcast, tambahkan konfigurasi berikut ke instantiasi LocalStageStream on Anda:

// Enable Simulcast let cameraStream = new LocalStageStream(cameraDevice, { simulcast: { enabled: true } })

Bergantung pada resolusi input perangkat kamera Anda, sejumlah lapisan akan dikodekan dan dikirim seperti yang didefinisikan di bagian Default Layers, Qu alitties, dan Framerates dari Pengoptimalan Streaming.

Selain itu, Anda dapat secara opsional mengonfigurasi lapisan individual dari dalam konfigurasi simulcast:

import { SimulcastLayerPresets } from ‘amazon-ivs-web-broadcast’ // Enable Simulcast let cameraStream = new LocalStageStream(cameraDevice, { simulcast: { enabled: true, layers: [ SimulcastLayerPresets.DEFAULT_720, SimulcastLayerPresets.DEFAULT_360, SimulcastLayerPresets.DEFAULT_180, } })

Sebagai alternatif, Anda dapat membuat konfigurasi lapisan kustom Anda sendiri hingga tiga lapisan. Jika Anda memberikan array kosong atau tidak ada nilai, default yang dijelaskan di atas digunakan. Lapisan dijelaskan dengan properti yang diperlukan berikut:

  • height: number;

  • width: number;

  • maxBitrateKbps: number;

  • maxFramerate: number;

Mulai dari preset, Anda dapat mengganti properti individual atau membuat konfigurasi yang sama sekali baru:

import { SimulcastLayerPresets } from ‘amazon-ivs-web-broadcast’ const custom720pLayer = { ...SimulcastLayerPresets.DEFAULT_720, maxFramerate: 15, } const custom360pLayer = { maxBitrateKbps: 600, maxFramerate: 15, width: 640, height: 360, } // Enable Simulcast let cameraStream = new LocalStageStream(cameraDevice, { simulcast: { enabled: true, layers: [ custom720pLayer, custom360pLayer, } })

Untuk nilai maksimum, batas, dan kesalahan yang dapat dipicu saat mengonfigurasi lapisan individual, lihat dokumentasi referensi SDK.

Mengkonfigurasi Pengkodean Berlapis (Pelanggan)

Sebagai pelanggan, tidak ada yang diperlukan untuk mengaktifkan pengkodean berlapis. Jika penerbit mengirim lapisan simulcast, maka secara default server secara dinamis beradaptasi di antara lapisan untuk memilih kualitas optimal berdasarkan perangkat pelanggan dan kondisi jaringan.

Atau, untuk memilih lapisan eksplisit yang dikirim penerbit, ada beberapa opsi, dijelaskan di bawah ini.

Opsi 1: Preferensi Kualitas Lapisan Awal

Dengan menggunakan subscribeConfiguration strategi ini, dimungkinkan untuk memilih lapisan awal apa yang ingin Anda terima sebagai pelanggan:

const strategy = { subscribeConfiguration: (participant) => { return { simulcast: { initialLayerPreference: InitialLayerPreference.LOWEST_QUALITY } } } // ... other strategy functions }

Secara default, pelanggan selalu dikirim lapisan kualitas terendah terlebih dahulu; ini perlahan naik ke lapisan kualitas tertinggi. Ini mengoptimalkan konsumsi bandwidth pengguna akhir dan memberikan waktu terbaik untuk video, mengurangi pembekuan video awal untuk pengguna di jaringan yang lebih lemah.

Opsi ini tersedia untukInitialLayerPreference:

  • LOWEST_QUALITY— Server memberikan lapisan video berkualitas terendah terlebih dahulu. Ini mengoptimalkan konsumsi bandwidth, serta waktu ke media. Kualitas didefinisikan sebagai kombinasi ukuran, bitrate, dan framerate video. Misalnya, kualitas video 720p lebih rendah daripada video 1080p.

  • HIGHEST_QUALITY— Server memberikan lapisan video kualitas tertinggi terlebih dahulu. Ini mengoptimalkan kualitas tetapi dapat meningkatkan waktu untuk media. Kualitas didefinisikan sebagai kombinasi ukuran, bitrate, dan framerate video. Misalnya, video 1080p memiliki kualitas lebih tinggi daripada video 720p.

Catatan: Agar preferensi lapisan awal (initialLayerPreferencepanggilan) berlaku, berlangganan ulang diperlukan karena pembaruan ini tidak berlaku untuk langganan aktif.

Opsi 2: Lapisan Pilihan untuk Stream

Setelah streaming dimulai, Anda dapat menggunakan metode preferredLayerForStream strategi. Metode strategi ini mengekspos peserta dan informasi aliran.

Metode strategi dapat dikembalikan dengan yang berikut:

  • Objek layer secara langsung, berdasarkan apa yang dikem RemoteStageStream.getLayers balikan

  • String label objek lapisan, berdasarkan StageStreamLayer.label

  • Tidak ditentukan atau nol, yang menunjukkan bahwa tidak ada lapisan yang harus dipilih, dan adaptasi dinamis lebih disukai

Misalnya, strategi berikut akan selalu membuat pengguna memilih lapisan video dengan kualitas terendah yang tersedia:

const strategy = { preferredLayerForStream: (participant, stream) => { return stream.getLowestQualityLayer(); } // ... other strategy functions }

Untuk mengatur ulang pemilihan lapisan dan kembali ke adaptasi dinamis, kembalikan null atau undefined dalam strategi. Dalam contoh ini appState adalah variabel dummy yang mewakili kemungkinan status aplikasi.

const strategy = { preferredLayerForStream: (participant, stream) => { if (appState.isAutoMode) { return null; } else { return appState.layerChoice } } // ... other strategy functions }

Opsi 3: Pemb RemoteStageStream antu Lapisan

RemoteStageStreammemiliki beberapa pembantu yang dapat digunakan untuk membuat keputusan tentang pemilihan lapisan dan menampilkan pilihan yang sesuai untuk pengguna akhir:

  • Peristiwa Lap isan - Di sampingStageEvents, RemoteStageStream objek itu sendiri memiliki peristiwa yang mengkomunikasikan perubahan adaptasi lapisan dan simulcast:

    • stream.on(RemoteStageStreamEvents.ADAPTION_CHANGED, (isAdapting) => {})

    • stream.on(RemoteStageStreamEvents.LAYERS_CHANGED, (layers) => {})

    • stream.on(RemoteStageStreamEvents.LAYER_SELECTED, (layer, reason) => {})

  • Layer Me RemoteStageStream thods — memiliki beberapa metode pembantu yang dapat digunakan untuk mendapatkan informasi tentang aliran dan lapisan yang disajikan. Metode-metode ini tersedia pada aliran jarak jauh yang disediakan dalam preferredLayerForStream strategi, serta aliran jarak jauh yang diekspos melaluiStageEvents.STAGE_PARTICIPANT_STREAMS_ADDED.

    • stream.getLayers

    • stream.getSelectedLayer

    • stream.getLowestQualityLayer

    • stream.getHighestQualityLayer

Untuk detailnya, lihat RemoteStageStream kelas dalam dokumentasi referensi SDK. Untuk LAYER_SELECTED alasannya, jika UNAVAILABLE dikembalikan, ini menunjukkan bahwa lapisan yang diminta tidak dapat dipilih. Pilihan upaya terbaik dibuat sebagai gantinya, yang biasanya merupakan lapisan kualitas lebih rendah untuk menjaga stabilitas aliran.

Menangani Masalah Jaringan

Ketika koneksi jaringan perangkat lokal hilang, SDK secara internal mencoba menyambung kembali tanpa tindakan pengguna apa pun. Dalam beberapa kasus, SDK tidak berhasil dan tindakan pengguna diperlukan.

Secara umum keadaan panggung dapat ditangani melalui STAGE_CONNECTION_STATE_CHANGED acara:

stage.on(StageEvents.STAGE_CONNECTION_STATE_CHANGED, (state) => { switch (state) { case StageConnectionState.DISCONNECTED: // handle disconnected UI return; case StageConnectionState.CONNECTING: // handle establishing connection UI return; case StageConnectionState.CONNECTED: // SDK is connected to the Stage return; case StageConnectionState.ERRORED: // SDK encountered an error and lost its connection to the stage. Wait for CONNECTED. return; } })

Secara umum, Anda dapat mengabaikan status kesalahan yang ditemui setelah berhasil bergabung dengan tahap, karena SDK akan mencoba memulihkan secara internal. Jika SDK melaporkan ERRORED status dan tahap tetap dalam CONNECTING status untuk jangka waktu yang lama (misalnya, 30 detik atau lebih), Anda mungkin terputus dari jaringan.

Siarkan Panggung ke Saluran IVS

Untuk menyiarkan panggung, buat IVSBroadcastClient sesi terpisah dan kemudian ikuti instruksi biasa untuk penyiaran dengan SDK, dijelaskan di atas. Daftar via yang StageStream diek STAGE_PARTICIPANT_STREAMS_ADDED spos dapat digunakan untuk mengambil aliran media peserta yang dapat diterapkan pada komposisi aliran siaran, sebagai berikut:

// Setup client with preferred settings const broadcastClient = getIvsBroadcastClient(); stage.on(StageEvents.STAGE_PARTICIPANT_STREAMS_ADDED, (participant, streams) => { streams.forEach(stream => { const inputStream = new MediaStream([stream.mediaStreamTrack]); switch (stream.streamType) { case StreamType.VIDEO: broadcastClient.addVideoInputDevice(inputStream, `video-${participant.id}`, { index: DESIRED_LAYER, width: MAX_WIDTH, height: MAX_HEIGHT }); break; case StreamType.AUDIO: broadcastClient.addAudioInputDevice(inputStream, `audio-${participant.id}`); break; } }) })

Secara opsional, Anda dapat menggabungkan panggung dan menyiarkannya ke saluran latensi rendah IVS, untuk menjangkau audiens yang lebih besar. Lihat Mengaktifkan Beberapa Host di Amazon IVS Streaming di Panduan Pengguna Stre Low-Latency aming IVS.