// agent-renderer.js — 브라우저 환경에서 실행됨 → WebRTC 사용 가능 let peerConnection = null; let socket = null; let currentStream = null; // 메인 프로세스로부터 명령 수신 (IPC) console.log('electronAPI:', window.electronAPI); console.log('desktopCapturer:', window.desktopCapturer); window.electronAPI.send('displays', { types: ['screen'] }); window.electronAPI.receive('start-webrtc', async (payload) => { try { const { offer, displayId, signalingServer, targetId } = payload; console.log('start webrtc'); // 1. Socket 연결 (렌더러에서도 가능) socket = io(signalingServer); socket.on('availableDisplays', async (sources) => { const source = sources.find(s => { console.log(s.id, displayId) return s.id === displayId }); if (!source) throw new Error('디스플레이 없음'); const stream = await navigator.mediaDevices.getUserMedia({ audio: false, video: { mandatory: { chromeMediaSource: 'desktop', chromeMediaSourceId: source.id, minWidth: 1920, minHeight: 1080 } } }); currentStream = stream; // 3. WebRTC 연결 peerConnection = new RTCPeerConnection({ iceServers: [{urls: 'stun:stun.l.google.com:19302'}] }); stream.getTracks().forEach(track => { console.log('track', track, stream); peerConnection.addTrack(track, stream) }); await peerConnection.setRemoteDescription(new RTCSessionDescription(offer)); const answer = await peerConnection.createAnswer(); await peerConnection.setLocalDescription(answer); // 4. Answer 전송 socket.emit('webrtcSignal', { targetId: targetId, type: 'answer', answer }); // 5. ICE candidate peerConnection.onicecandidate = (e) => { if (e.candidate) { socket.emit('webrtcSignal', { targetId: targetId, type: 'icecandidate', candidate: e.candidate }); } }; // 6. 입력 이벤트 수신 (robotjs는 메인 프로세스에서 실행 권장) socket.on('inputEvent', (data) => { window.electronApi.send('input-event-from-renderer', data); }); console.log('✅ WebRTC 시작됨 (렌더러)'); }) // 2. 화면 스트림 캡처 socket.emit('requestDisplays', 'psn14020') // const sources = await window.desktopCapturer.getSources({ types: ['screen'] }); } catch (err) { console.error('❌ WebRTC 실패:', err); window.electronApi.send('webrtc-error', err.message); } }); window.electronAPI.receive('webrtcSignal', async (data) => { try { console.log('webrtcSignal', data) if (!peerConnection) return; if (data.type === 'icecandidate' && data.candidate) { await peerConnection.addIceCandidate(new RTCIceCandidate(data.candidate)); } } catch (err) { console.error('ICE candidate 처리 오류:', err); } }) // desktopCapturer 사용을 위해 preload 필요 // → 다음 단계에서 preload.js 설정