WebRTC는 Peer to Peer로 두 피어 간 영상, 음성, 데이터를 주고받는 통신 프로토콜이다.
두 피어는 서로의 멀티미디어 세션(Session Description Protocol) 을 주고 받고, 서로의 연결 정보(Ice Canditates) 를 주고 받아 연결을 확립한다.

먼저 위에서 설명한 SDP와 Ice Candidates를 교환할 때 사용되는 Signaling Server가 필요하다.
두 정보를 교환할 때만 쓰이므로 비교적 자유롭게 구현이 가능하다고 생각된다.
본인은 Signaling Server를 AWS Iot MQTT를 사용해 구현하였다.
다음으로 STUN 서버라 불리는 서버가 필요하다.
두 Peer가 같은 네트워크에 있을 때에는 HOST 타입의 Ice Candidate를 사용해 별도의 서버 없이 구현 가능하지만, 다른 네트워크에 속해 있을때는 STUN 서버가 필요하다.
STUN 서버는 Google 같은 곳에서 무료로 지원하는 것들이 있으니 이를 사용하였다(stun:stun.l.google.com:19302).
마지막으로 TURN 서버가 있다.
TURN 서버는 STUN 서버를 사용해도 방화벽/NAT 등의 이유로 외부망과의 통신이 불가능 할 때 사용된다. 그럴때 TURN 서버는 직접 데이터를 중계하는 역할을 한다.
본인은 TURN 서버를 AWS EC2에 Coturn 서버를 구축하여 사용하였다.
찾아본 바로는 안드로이드에서 WebRTC를 사용하는 방법은 두 가지 있다.
https://github.com/ALEXGREENCH/google-webrtc
위 링크의 repository를 사용하면 1.0.30039 버전의 WebRTC 라이브러리를 사용할 수 있다.
settings.gradle.kts
pluginManagement { repositories { google { content { includeGroupByRegex("com\\.android.*") includeGroupByRegex("com\\.google.*") includeGroupByRegex("androidx.*") } } mavenCentral() gradlePluginPortal() // ----- 추가 코드 ----- maven { url = uri("https://raw.githubusercontent.com/alexgreench/google-webrtc/master") } } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() // ----- 추가 코드 ----- maven { url = uri("https://raw.githubusercontent.com/alexgreench/google-webrtc/master") } } }
build.gradle.kts(Module :app)
dependencies { implementation("org.webrtc:google-webrtc:1.0.30039@aar") }
https://github.com/getstream/webrtc-android?tab=readme-ov-file
위 링크의 repository를 사용하면 지원이 끊기기 전 가장 최신 버전의 WebRTC 라이브러리를 사용할 수 있으며, 그외에도 제작자가 추가한 기능들을 사용할 수 있다.
build.gradle.kts(Module :app)
dependencies { implementation("io.getstream:stream-webrtc-android:1.1.3") }
PeerConnectionFactory
PeerConnection, VideoSource, VideoTrack 등의 객체를 만들고 관리한다.
public void createPeerConnectionFactory() {
PeerConnectionFactory.InitializationOptions initializationOptions = PeerConnectionFactory
.InitializationOptions.builder(context)
.createInitializationOptions();
PeerConnectionFactory.initialize(initializationOptions);
DefaultVideoEncoderFactory defaultVideoEncoderFactory = new DefaultVideoEncoderFactory(
eglBase.getEglBaseContext(), /* enableIntelVp8Encoder */true, /* enableH264HighProfile */true);
DefaultVideoDecoderFactory defaultVideoDecoderFactory = new DefaultVideoDecoderFactory(eglBase.getEglBaseContext());
peerConnectionFactory = PeerConnectionFactory.builder().setVideoEncoderFactory(defaultVideoEncoderFactory).setVideoDecoderFactory(defaultVideoDecoderFactory).createPeerConnectionFactory();
Log.d(TAG, "PeerConnectionFactory 생성됨");
}
...
peerConnection = peerConnectionFactory.createPeerConnection(...);
videoCapturer = createVideoCapturer();
videoSource = peerConnectionFactory.createVideoSource(videoCapturer.isScreencast());
localVideoTrack = peerConnectionFactory.createVideoTrack("100", videoSource);
PeerConnection
두 피어 간 실시간 오디오, 비디오, 데이터 통신을 설정하고 관리하는 역할을 한다.
PeerConnection.RTCConfiguration config = new PeerConnection.RTCConfiguration(Collections.singletonList(new PeerConnection.IceServer("stun:stun.l.google.com:19302")));
config.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
PeerConnection peerConnection = peerConnectionFactory.createPeerConnection(config, new PeerConnection.Observer(){...});
SDP를 사용하여 피어 간의 미디어 설정을 협상한다.
// 다른 피어에게 전송할 오퍼 SDP 생성
peerConnection.createOffer(new SdpObserver(){...}, new MediaConstraints());
// 원격 피어의 오퍼에 대한 응답 SDP 생성
peerConnection.createAnswer(new SdpObserver(){...}, new MediaConstraints());
// 로컬 피어의 SDP 설정
peerConnection.setLocalDescription(new SdpObserver(){...}, SessionDescription);
// 원격 피어로부터 받은 SDP 설정
peerConnection.setRemoteDescription(new SdpObserver(){...}, SessionDescription);
ICE 후보들을 수집하여 최적의 네트워크 경로를 선택한다.
peerConnection.addIceCandidate(IceCandidate);
비디오 트랙, 데이터 채널 등을 관리한다.
dataChannel = peerConnection.createDataChannel("myDataChannel", dcInit);
peerConnection.addTrack(localVideoTrack);
SessionDescription
IceCandidate
addIceCandidate() 메소드를 통해 추가한다.RTCConfiguration
SurfaceViewRenderer
remoteVideoTrack.addSink(surfaceViewRenderer);
저도 GetStream 쪽 레포받아서 돌려보는데, 아래와 같은 에러발생하면서 크래시 안나시나요?
(https://github.com/GetStream/webrtc-in-jetpack-compose)
No implementation found for long org.webrtc.SoftwareVideoDecoderFactory.nativeCreateDecoder(long, org.webrtc.VideoCodecInfo) (tried Java_org_webrtc_SoftwareVideoDecoderFactory_nativeCreateDecoder and Java_org_webrtc_SoftwareVideoDecoderFactory_nativeCreateDecoder__JLorg_webrtc_VideoCodecInfo_2) - is the library loaded, e.g. System.loadLibrary?