기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
웹 애플리케이션을 WebRTC 리디렉션과 통합
WebRTC 리디렉션을 사용하면 WorkSpaces 세션 내에서 실행되는 웹 애플리케이션이 네이티브 클라이언트 측 오디오 디바이스를 사용할 수 있습니다. 이 주제에서는 웹 애플리케이션 개발자가 WebRTC 리디렉션 환경을 감지하고 통합하는 방법을 보여줍니다.
WorkSpace에서 WebRTC 리디렉션이 활성화되면 Amazon DCV WebRTC 리디렉션 브라우저 확장이 프록시 SDK를 웹 페이지에 삽입합니다. 애플리케이션은이 프록시를 감지하고 이를 사용하여 getUserMedia 및 RTCPeerConnection을 포함한 표준 WebRTC API 호출을 원격 WorkSpace의 가상 디바이스가 아닌 사용자의 로컬 디바이스로 리디렉션할 수 있습니다. 이렇게 하면 DCV 디스플레이 프로토콜을 통한 미디어 스트리밍에 비해 성능이 크게 향상되고 지연 시간이 줄어듭니다.
애플리케이션은 WebRTC 리디렉션이 활성화된 WorkSpace 내에서 실행되는 경우와 리디렉션이 활성화되지 않은 표준 브라우저에서 실행되는 경우 모두 처리해야 합니다. 프록시는 선택 사항입니다. 프록시가 없으면 애플리케이션이 표준 WebRTC로 돌아갈 수 있습니다.
사전 조건
최종 사용자의 경우
최종 사용자에게는 다음이 필요합니다.
-
DCV 프로토콜을 사용하는 WorkSpace. 자세한 내용은 WorkSpaces Personal용 프로토콜 단원을 참조하십시오.
참고
서버 측 WebRTC 리디렉션은 현재 Windows WorkSpaces에서만 지원됩니다.
-
clients.amazonworkspaces.com
지원되는 WorkSpaces 클라이언트입니다. 지원되는 플랫폼: Windows, macOS, Linux(Ubuntu 22.04 및 Ubuntu 24.04, amd64) 및 Web. -
그룹 정책을 통해 활성화된 WebRTC 리디렉션입니다. 활성화되면 정책은 레지스트리를 통해 Chrome 및 Edge에 브라우저 확장을 자동으로 설치합니다. 자세한 내용은 WorkSpaces Personal에서 Windows WorkSpaces 관리 단원을 참조하십시오. 필요한 경우 사용자는 확장 프로그램을 Chrome
및 Edge 와 같이 수동으로 설치할 수 있습니다.
개발자용
웹 애플리케이션은 다음을 수행해야 합니다.
-
표준 WebRTC APIs 사용(예: getUserMedia 및 RTCPeerConnection)
-
이 주제에 설명된 대로 탐지 및 초기화 코드 포함
통합 방법
통합에는 리디렉션 환경 감지, WebRTC APIs 재정의, 오디오 요소 매핑, 재연결 처리의 네 단계가 포함됩니다.
1단계: 리디렉션 환경 감지
이 초기화 코드를 애플리케이션에 추가합니다. 프록시가 준비되면 콜백이 실행되고 리디렉션을 사용할 수 없는 경우 제한 시간이 지나면 콜백이 실행됩니다.
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); }
중요 사항:
-
가 확장을 감지
globalThis.DCVWebRTCPeerConnectionProxyV2하는지 확인 -
핸들러
setInitCallback()로 호출 및 제한 시간 - 5000ms 권장 -
콜백은 부울 및
proxy또는success가 있는 결과 객체를 수신합니다.error -
를 호출
proxy.overrideWebRTC()하여 표준 WebRTC APIs리디렉션
2단계: 표준 WebRTC APIs 사용
를 호출한 후 WebRTC APIs 정상적으로 overrideWebRTC()사용합니다. 프록시는 이를 로컬 클라이언트로 투명하게 리디렉션합니다.
참고
비디오 리디렉션은 현재 지원되지 않습니다. getUserMedia 요청에 video: false를 설정합니다.
// 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);
원래 브라우저 APIs에 액세스해야 하는 경우(예: 로컬 클라이언트가 아닌 원격 브라우저에서 비디오를 캡처하기 위해) proxy.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 });
3단계: 오디오 요소 매핑
오디오 재생의 경우 오디오 요소에를 설정mapAudioElement()하기 전에 srcObject를 호출합니다.
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);
4단계: 재연결 처리
네트워크 문제 또는 클라이언트 재연결 등으로 인해 리디렉션 서비스를 일시적으로 사용할 수 없게 될 수 있습니다.
중요
다시 연결하면 클라이언트 브라우저 컨텍스트가 완전히 다시 로드되므로 이전에 생성된 모든 프록시 객체가 무효화됩니다. 기존 연결을 닫고 새 WebRTC 객체를 생성해야 합니다.
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 }
하트비트 타이밍을 사용자 지정할 수 있습니다.
proxy.resetHeartbeat({ heartbeatTimeoutMs: 5000, // Time before marking unavailable heartbeatIntervalPeriodMs: 500 // How often to check });
디바이스 열거
헤드셋을 꽂는 사용자와 같은 디바이스 변경 사항이 자동으로 감지됩니다. makeMediaDevicesProxy()를 사용하여 로컬 클라이언트에서 디바이스 변경 사항을 수신 대기합니다.
const mediaDevices = proxy.makeMediaDevicesProxy(); mediaDevices.ondevicechange = async () => { const devices = await navigator.mediaDevices.enumerateDevices(); updateDeviceList(devices); };
proxy.clientInfo를 사용하여 사용자가 연결할 클라이언트 플랫폼을 결정합니다.
// 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; }
고급: 웹 오디오 API를 사용한 오디오 처리
웹 오디오 API를 사용하여 피어 연결을 통해 전송하기 전에 오디오 스트림을 처리할 수 있습니다.
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);
전체 예제
다음 예제에서는 초기화, 재연결 처리, 디바이스 변경 감지 및 통화 설정과의 완전한 통합을 보여줍니다.
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();
통합 테스트
리디렉션 없음
확장 프로그램이 설치되지 않았거나, WorkSpace 외부에서 실행되거나, 그룹 정책을 통해 WebRTC 리디렉션이 활성화되지 않은 경우 애플리케이션이 정상적으로 작동합니다. 일반 브라우저에서 애플리케이션을 열어 테스트합니다.
리디렉션 사용
리디렉션이 활성화된 상태에서 테스트하려면:
-
DCV 프로토콜을 사용하여 WorkSpace를 생성하고 WebRTC 리디렉션 그룹 정책 설정을 활성화합니다. WorkSpaces Personal에서 Windows WorkSpaces 관리을(를) 참조하세요.
-
clients.amazonworkspaces.com
WorkSpaces 클라이언트를 다운로드하여 설치하고 WorkSpace에 연결합니다. Chrome 또는 Edge 확장이 설치되어 있는지 확인합니다(GPO가 설정된 경우 자동). -
WorkSpace 브라우저에서 웹 애플리케이션을 엽니다. 콘솔에서 "WebRTC 리디렉션 활성화" 메시지를 확인합니다. 로컬 디바이스를 사용하여 오디오 기능을 확인하고, 디바이스 열거 및 전환을 테스트하고, 재연결 처리를 확인합니다.
모범 사례
WebRTC 리디렉션과 통합할 때 다음 권장 사항을 따르세요.
-
항상 리디렉션 가용성 확인 - 프록시가 있다고 가정하지 않음
-
WebRTC 객체를 생성하기 전에
overrideWebRTC()조기 호출 -
사용 전 오디오 요소 매핑 - 설정
mapAudioElement()전 호출srcObject -
재연결 처리 - 재연결 후 모든 프록시 객체가 유효하지 않습니다. 항상 새 WebRTC 객체를 생성합니다.
-
두 모드 모두 테스트 - 리디렉션 유무에 관계없이 앱이 올바르게 작동하는지 확인합니다.
-
표준 WebRTC APIs 사용 - 프록시가 투명하게 리디렉션합니다. 기본 사용에 사용자 지정 APIs가 필요하지 않습니다.
-
리소스 정리 - 이벤트 리스너를 제거하고 완료되면 연결을 닫습니다.
문제 해결
리디렉션이 감지되지 않음
-
브라우저 확장이 설치 및 활성화되어 있는지 확인합니다( 확인
chrome://extensions). -
WorkSpace에서 WebRTC 리디렉션 그룹 정책이 활성화되었는지 확인
-
DCV 프로토콜을 사용하여 WorkSpace 내에서 실행 중인지 확인
-
브라우저 콘솔에서 초기화 메시지를 확인합니다.
-
WorkSpaces 클라이언트 버전이 WebRTC 리디렉션을 지원하는지 확인(Windows 5.21.0 이상, macOS 5.31.0 이상, Linux 2026.0 이상 또는 웹 클라이언트)
오디오 또는 비디오가 작동하지 않음
-
WebRTC 객체를 생성하기 전에가 호출
overrideWebRTC()되었는지 확인 -
설정
mapAudioElement()하기 전에 오디오 요소가에 매핑되었는지 확인srcObject -
브라우저 콘솔에서 오류 확인
-
디바이스 권한이 부여되었는지 확인
재연결 문제
-
가용성 변경을 감지
addStatusChangeEventListener()하기 위한 구현 -
다시 연결한 후에는 항상 새 RTCPeerConnection 및 MediaStream 객체를 생성합니다. 이전 프록시는 유효하지 않으며 발생합니다.
-
사용 불가가 너무 느리게 또는 너무 빨리 감지되는 경우 하트비트 구성 검토
API 참조
다음은 프록시 API를 요약한 것입니다.
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; }