Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.
Integrasikan aplikasi web Anda dengan pengalihan WebRTC
Pengalihan WebRTC memungkinkan aplikasi web yang berjalan di dalam WorkSpaces sesi untuk menggunakan perangkat audio sisi klien asli. Topik ini menunjukkan kepada pengembang aplikasi web cara mendeteksi lingkungan pengalihan WebRTC dan mengintegrasikannya.
Saat pengalihan WebRTC diaktifkan pada a WorkSpace, ekstensi browser Pengalihan WebRTC Amazon DCV menyuntikkan SDK proxy ke halaman web. Aplikasi Anda dapat mendeteksi proxy ini dan menggunakannya untuk mengalihkan panggilan API WebRTC standar - termasuk get UserMedia and RTCPeerConnection - ke perangkat lokal pengguna daripada perangkat virtual remote WorkSpace. Ini memberikan kinerja yang jauh lebih baik dan latensi yang lebih rendah dibandingkan dengan media streaming melalui protokol tampilan DCV.
Aplikasi Anda harus menangani kedua kasus: saat berjalan di dalam WorkSpace dengan pengalihan WebRTC diaktifkan, dan saat berjalan di browser standar tanpa itu. Proxy bersifat opsional - jika tidak ada, aplikasi Anda dapat kembali ke WebRTC standar.
Prasyarat
Untuk pengguna akhir
Pengguna akhir membutuhkan yang berikut:
-
WorkSpace Menggunakan protokol DCV. Untuk informasi selengkapnya, lihat Protokol untuk Pri WorkSpaces badi.
catatan
Pengalihan WebRTC di sisi server saat ini hanya didukung di Windows. WorkSpaces
-
Klien yang didukung dari WorkSpaces clients.
amazonworkspaces.com. Platform yang didukung: Windows, macOS, Linux (Ubuntu 22.04 dan Ubuntu 24.04, amd64), dan Web. -
Pengalihan WebRTC diaktifkan melalui Kebijakan Grup. Saat diaktifkan, kebijakan secara otomatis menginstal ekstensi browser di Chrome dan Edge melalui registri. Untuk informasi selengkapnya, lihat Kelola Windows Anda WorkSpaces di WorkSpaces Personal. Jika diperlukan, pengguna dapat menginstal ekstensi secara manual: Chrome
dan Edge .
Untuk pengembang
Aplikasi web Anda harus:
-
Gunakan API WebRTC standar (seperti get UserMedia dan) RTCPeerConnection
-
Sertakan kode deteksi dan inisialisasi seperti yang dijelaskan dalam topik ini
Bagaimana mengintegrasikan
Integrasi melibatkan empat langkah: mendeteksi lingkungan pengalihan, mengganti API WebRTC, memetakan elemen audio, dan menangani koneksi ulang.
Langkah 1: Mendeteksi lingkungan pengalihan
Tambahkan kode inisialisasi ini ke aplikasi Anda. Panggilan balik berjalan saat proxy siap, atau setelah batas waktu jika pengalihan tidak tersedia.
let proxy = null; function handleInitCallback(result) { if (result.success) { // Redirection is available proxy = result.proxy; console.log('WebRTC redirection enabled, version:', proxy.getVersion()); console.log('Client info:', proxy.clientInfo); // Override WebRTC APIs to use redirection proxy.overrideWebRTC(); // Set up reconnection handling setupReconnectionHandling(); } else { // Not in a redirection environment - use standard WebRTC console.log('WebRTC redirection not available:', result.error); } } // Register the initialization callback if (globalThis.DCVWebRTCPeerConnectionProxyV2) { globalThis.DCVWebRTCPeerConnectionProxyV2.setInitCallback(handleInitCallback, 5000); }
Poin kunci:
-
Periksa
globalThis.DCVWebRTCPeerConnectionProxyV2untuk mendeteksi ekstensi -
Panggil
setInitCallback()dengan handler Anda dan batas waktu - 5000 ms disarankan -
Panggilan balik menerima objek hasil dengan
successboolean dan salah satu atauproxyerror -
Panggilan
proxy.overrideWebRTC()untuk mengalihkan API WebRTC standar
Langkah 2: Gunakan API WebRTC standar
Setelah meneleponoverrideWebRTC(), gunakan API WebRTC secara normal. Proxy secara transparan mengarahkan mereka ke klien lokal.
catatan
Pengalihan video saat ini tidak didukung. Tet video: false apkan getUserMedia permintaan.
// Get user media - automatically redirected const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false // Video redirection not yet supported }); // Create peer connection - automatically redirected const pc = new RTCPeerConnection(configuration); // Everything else works as standard WebRTC pc.addTrack(stream.getAudioTracks()[0], stream); const offer = await pc.createOffer(); await pc.setLocalDescription(offer);
Jika Anda perlu mengakses API browser asli (misalnya, untuk menangkap video dari browser jarak jauh daripada klien lokal), mereka disimpan diproxy.overridenApis:
// Get the original getUserMedia (runs in remote browser, not redirected) const originalGetUserMedia = proxy.overridenApis.get('navigator.mediaDevices.getUserMedia'); // Available original APIs: // 'navigator.mediaDevices.getUserMedia' // 'navigator.mediaDevices.addEventListener' // 'navigator.mediaDevices.removeEventListener' // 'navigator.mediaDevices.enumerateDevices' // 'navigator.mediaDevices.getDisplayMedia' // 'window.RTCPeerConnection' // 'window.RTCPeerConnection.generateCertificate' // 'window.AudioContext' // 'window.Worker' (experimental) const remoteStream = await originalGetUserMedia.call(navigator.mediaDevices, { audio: false, video: true });
Langkah 3: Memetakan elemen audio
Untuk pemutaran audio, hubungi mapAudioElement() sebelum mengatur srcObject elemen audio apa pun.
const audioElement = document.querySelector('audio#remote-audio'); // Map the audio element before setting srcObject proxy.mapAudioElement(audioElement); // Now use the audio element normally audioElement.srcObject = remoteStream; await audioElement.play(); // Control playback audioElement.pause(); audioElement.volume = 0.8; audioElement.muted = false; // Change output device await audioElement.setSinkId(deviceId);
Langkah 4: Tangani koneksi ulang
Layanan pengalihan dapat menjadi tidak tersedia sementara, misalnya karena masalah jaringan atau koneksi ulang klien.
penting
Setelah koneksi ulang, semua objek proxy yang dibuat sebelumnya menjadi tidak valid karena konteks browser klien dimuat ulang sepenuhnya. Anda harus menutup koneksi yang ada dan membuat objek WebRTC baru.
function setupReconnectionHandling() { proxy.addStatusChangeEventListener((event) => { switch (event.status) { case 'unavailable': console.error('Redirection lost'); handleRedirectionLost(); break; case 'available': console.info('Redirection restored'); handleRedirectionRestored(); break; } }); } function handleRedirectionLost() { // Try to close cleanly - proxies may throw exceptions after reconnection try { if (peerConnection) { peerConnection.close(); } } catch (error) { console.warn('Error closing peer connection (proxy may be invalid):', error); } showReconnectingMessage(); } function handleRedirectionRestored() { // IMPORTANT: All existing proxy objects are invalid after reconnection. // Create new RTCPeerConnection, MediaStream, and other WebRTC objects. hideReconnectingMessage(); restartCall(); // Must create fresh WebRTC objects }
Anda dapat menyesuaikan waktu detak jantung:
proxy.resetHeartbeat({ heartbeatTimeoutMs: 5000, // Time before marking unavailable heartbeatIntervalPeriodMs: 500 // How often to check });
Pencacatan perangkat
Perubahan perangkat - misalnya, pengguna yang mencolokkan headset - terdeteksi secara otomatis. Gunakan makeMediaDevicesProxy() untuk mendengarkan perubahan perangkat pada klien lokal:
const mediaDevices = proxy.makeMediaDevicesProxy(); mediaDevices.ondevicechange = async () => { const devices = await navigator.mediaDevices.enumerateDevices(); updateDeviceList(devices); };
Gunakan proxy.clientInfo untuk menentukan platform klien mana pengguna terhubung dari:
// clientInfo contains: // - platform: 'web' | 'windows' | 'macOS' | 'linux' // - version: SDK version string // - userAgent: browser user agent string // - browserDetails: { browser: string, version: string } switch (proxy.clientInfo.platform) { case 'web': console.log('Connecting from web client'); break; case 'windows': console.log('Connecting from Windows native client'); break; case 'macOS': console.log('Connecting from macOS native client'); break; case 'linux': console.log('Connecting from Linux native client'); break; }
Lanjutan: Pemrosesan audio dengan Web Audio API
Anda dapat menggunakan Web Audio API untuk memproses aliran audio sebelum mengirimnya melalui koneksi peer:
const audioContext = new AudioContext(); const source = audioContext.createMediaStreamSource(micStream); const gainNode = audioContext.createGain(); const destination = audioContext.createMediaStreamDestination(); source.connect(gainNode); gainNode.connect(destination); // Control microphone volume gainNode.gain.value = 0.5; // 50% volume // Use the processed stream pc.addTrack(destination.stream.getAudioTracks()[0], destination.stream);
Contoh lengkap
Contoh berikut menunjukkan integrasi lengkap dengan inisialisasi, penanganan rekoneksi, deteksi perubahan perangkat, dan pengaturan panggilan:
let proxy = null; let peerConnection = null; let localStream = null; function initializeRedirection() { if (globalThis.DCVWebRTCPeerConnectionProxyV2) { globalThis.DCVWebRTCPeerConnectionProxyV2.setInitCallback((result) => { if (result.success) { proxy = result.proxy; proxy.overrideWebRTC(); proxy.addStatusChangeEventListener(handleStatusChange); proxy.resetHeartbeat({ heartbeatTimeoutMs: 5000, heartbeatIntervalPeriodMs: 500 }); setupDeviceChangeListener(); } else { console.log('Redirection not available:', result.error); } }, 5000); } } function handleStatusChange(event) { if (event.status === 'unavailable') { try { if (peerConnection) { peerConnection.close(); peerConnection = null; } if (localStream) { localStream.getTracks().forEach(t => t.stop()); localStream = null; } } catch (error) { console.warn('Error cleaning up (proxies invalid):', error); peerConnection = null; localStream = null; } } else if (event.status === 'available') { startCall(); // Create fresh WebRTC objects } } function setupDeviceChangeListener() { const mediaDevices = proxy.makeMediaDevicesProxy(); mediaDevices.ondevicechange = async () => { const devices = await navigator.mediaDevices.enumerateDevices(); updateDeviceUI(devices); }; } async function startCall() { try { localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false }); peerConnection = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }); localStream.getTracks().forEach(track => peerConnection.addTrack(track, localStream)); peerConnection.ontrack = (event) => { const remoteAudio = document.querySelector('audio#remote'); if (proxy) { proxy.mapAudioElement(remoteAudio); } remoteAudio.srcObject = event.streams[0]; remoteAudio.play(); }; peerConnection.onicecandidate = (event) => { if (event.candidate) { sendToSignalingServer({ type: 'ice-candidate', candidate: event.candidate }); } }; const offer = await peerConnection.createOffer(); await peerConnection.setLocalDescription(offer); sendToSignalingServer({ type: 'offer', sdp: offer }); } catch (error) { console.error('Failed to start call:', error); } } initializeRedirection();
Menguji integrasi Anda
Tanpa pengalihan
Aplikasi Anda bekerja secara normal ketika ekstensi tidak diinstal, saat berjalan di luar WorkSpace, atau ketika pengalihan WebRTC tidak diaktifkan melalui Kebijakan Grup. Uji dengan membuka aplikasi Anda di browser biasa.
Dengan pengalihan
Untuk menguji dengan pengalihan diaktifkan:
-
Buat protokol WorkSpace menggunakan DCV dan aktifkan pengaturan Kebijakan Grup pengalihan WebRTC. Lihat Kelola Windows Anda WorkSpaces di WorkSpaces Personal.
-
Unduh dan instal WorkSpaces klien dari clients.amazonworkspaces.com
dan sambungkan ke. WorkSpace Verifikasi ekstensi Chrome atau Edge diinstal (otomatis saat GPO disetel). -
Buka aplikasi web Anda di WorkSpace browser. Periksa konsol untuk pesan “Pengalihan WebRTC diaktifkan”. Verifikasi fungsionalitas audio dengan perangkat lokal, uji enumerasi dan peralihan perangkat, dan verifikasi penanganan koneksi ulang.
Praktik terbaik
Ikuti rekomendasi ini saat mengintegrasikan dengan pengalihan WebRTC:
-
Selalu periksa ketersediaan pengalihan - jangan pernah menganggap proxy ada
-
Panggil
overrideWebRTC()lebih awal - sebelum membuat objek WebRTC apa pun -
Memetakan elemen audio sebelum digunakan - panggil
mapAudioElement()sebelum pengaturansrcObject -
Tangani koneksi ulang - setelah koneksi ulang, semua objek proxy tidak valid; selalu buat objek WebRTC baru
-
Uji kedua mode - pastikan aplikasi Anda berfungsi dengan benar dengan dan tanpa pengalihan
-
Gunakan API WebRTC standar - proxy mengalihkannya secara transparan; tidak ada API khusus yang diperlukan untuk penggunaan dasar
-
Bersihkan sumber daya - hapus pendengar acara dan tutup koneksi setelah selesai
Pemecahan masalah
Pengalihan tidak terdeteksi
-
Verifikasi ekstensi browser diinstal dan diaktifkan (periksa
chrome://extensions) -
Konfirmasikan Kebijakan Grup pengalihan WebRTC diaktifkan pada WorkSpace
-
Verifikasi Anda menjalankan di dalam protokol DCV yang WorkSpace menggunakan
-
Periksa konsol browser untuk pesan inisialisasi
-
Verifikasi versi WorkSpaces klien mendukung pengalihan WebRTC (Windows 5.21.0 atau lebih baru, macOS 5.31.0 atau lebih baru, Linux 2026.0 atau lebih baru, atau klien Web)
Audio atau video tidak berfungsi
-
Verifikasi
overrideWebRTC()dipanggil sebelum membuat objek WebRTC -
Verifikasi elemen audio dipetakan
mapAudioElement()sebelum pengaturansrcObject -
Periksa konsol browser untuk kesalahan
-
Verifikasi izin perangkat diberikan
Masalah koneksi ulang
-
Menerapkan
addStatusChangeEventListener()untuk mendeteksi perubahan ketersediaan -
Setelah koneksi ulang, selalu buat objek baru RTCPeerConnection dan MediaStream objek - proxy lama tidak valid dan akan melempar
-
Tinjau konfigurasi detak jantung jika ketidaktersediaan terdeteksi terlalu lambat atau terlalu cepat
Referensi API
Berikut ini merangkum API proxy:
interface DCVWebRTCProxy { // Version and client info getVersion(): string; clientInfo: { platform: 'web' | 'windows' | 'macOS' | 'linux'; version: string; userAgent: string; browserDetails: { browser: string; version: string; }; }; // Core methods overrideWebRTC(): void; mapAudioElement(element: HTMLAudioElement): void; // Device management makeMediaDevicesProxy(): MediaDevices; // Status monitoring addStatusChangeEventListener(callback: (event: StatusChangeEvent) => void): void; resetHeartbeat(config: { heartbeatTimeoutMs: number, heartbeatIntervalPeriodMs: number }): void; // Access original (non-redirected) browser APIs overridenApis: Map<string, Function>; } interface StatusChangeEvent { status: 'available' | 'unavailable'; lastHeartbeat?: number; }