본문 바로가기
프로그래밍/WebRTC

[Mediasoup] communication-between-client-and-server - 1

by YuminK 2023. 9. 20.

https://mediasoup.org/documentation/v3/communication-between-client-and-server/

 

Communication Between Client and Server
미디어 수프튼 클라와 서버간 통신하기 위해 어떤 시그널링 프로토콜도 제공하지 않는다. 웹소켓, HTTP 혹은 기타 수단을 가지고 통신하고, 미디어수프 관련 파라미터를 교환하며, 요청과 응답을 받는 것은
어플리케이션에 달려 있습니다. 대부분의 상황에서 양방향 통신이 이루져야 하므로 전이중(Full-duflex) 채널이 되어야 합니다. 그러나 어플리케이션은 같은 채널을 재활용할 수 있습니다.
(미디어수프와 관련되지 않은 메시지의 교환용으로, 인증 프로듀스, 챗 메시지, 파일 전송 등등)

Guidelines for mediasoup-client and libmediasoupclient
미디어수프 클라이언트 Device나 libmediasoupclient Device 오브젝트를 초기화하는 자바스크립트나 C++ 클라이언트 사이드 어플리케이션을 가정해봅시다.
이들은 서버에서 이미 생성된 미디어수프 라우터 연결과 WebRTC위에서 미디어 정보를 주고 받기 위해 사용됩니다.

두 미디어수프 클라이언트는 적절한 RTP 파라미터를 생성합니다. 따라서 클라이언트 개발이 단순해집니다.

Signaling and Peers
어플리케이션은 WebSocket을 사용하며, 각각의 인증된 웹 소켓을 Peer로 연결지을 것입니다.

peers는 미디어 수프에 없습니다. 그러나 어플리케이션은 유저 계정을 검증하고 연관짓는 peer를 정의하길 원할 겁니다. 
웹 소켓 연결, 메타더이터, 미디어 스프 전송의 set, 프로듀서, 컨슈머

Device Loading
클라이언트 사이드 어플리케이션은 미디어 수프를 로드합니다. 서버쪽 미디어 수프 라우터에 RTP capabilities를 제공하면서

Creating Transports
두 미디어 수프 클라이언트는 분리된 webRTC transports가 필요합니다. for sending and receiving. 
주로 클라이언트 어플리케이션은 이러한 transports를 데이터를 받기 전에 미리 생성합니다. 

Sending Media의 경우
1. WebRTC transport는 미디어 수프 라우터에서 처음 생성되어야 합니다. router.createWebRtcTransport()
2. 그런다음 클라이언트 사이드 어플리케이션에서 복제합니다. device.createSendTransport()
3. 클라이언트 어플리케이션은 connect와 produce 이벤트를 local tranport에 등록해야 합니다.

Receiving Media의 경우
1. WebRTC transport는 미디어 수프 라우터에서 처음 생성되어야 합니다. router.createWebRtcTransport()
2. 그런다음 클라이언트 사이드 어플리케이션에서 복제합니다. device.createRecvTransport()
3. 클라이언트 어플리케이션은 connect 이벤트를 local transport에 등록해야 합니다.

SCTP(WebRTC Datachannel 내에서)을 사용하길 원하는 경우 enableSctp를 활성화하고 적절한 numSctpStreams과 설정을 추가해야 합니다.

 

Producing Media
일단 transport가 생성되면, 클라이언트 사이드 어플리케이션은 다양한 오디오와 비디오 트랙을 처리할 수 있다.

1. 어플리케이션은 트랙을 소유한다. (navigator.mediaDevices.getUserMedia() API를 통해)
2. transport.call()을 local send transport에서 호출한다.
transport.produce()를 처리하기 위한 첫 호출의 경우에는 connect를 처리한다.
transport는 produce를 처리할 것이다. 그래서 어플리케이션은 서버로 이벤트 파라미터를 전송할 것이며, 서버쪽에 Producer 인스턴스를 생성하게 된다.

3. 마지막으로 transport.produce()는 클라이언트 사이드 Producer 인스턴스로 해결될 것이다.

Consuming Media
일단 receive transport가 생성되면, 클라이언트 사이트 어플리케이션은 다양한 오디오와 비디오 트랙을 소비할 수 있다. 그러나 순서는 반대이다.
(consumer는 서버에서 먼저 생성되어야 한다.)

1. 클라이언트 어플리케이션은 자신의 device.rtpCapabilities를 서버에 신호로 보낸다. (미리 처리했을 수도 있음)
2. 서버 어플리케이션은 원격 디바이스가 구체적인 프로듀서를 소비할 수 있는지 확인해야 한다. (원격 디바이스가 미디어코덱을 지원하는지 여부)
이는 router.canConsume() 메소드를 통해 확인할 수 있다.

3. 그 이후 서버 어플리케이션은 transport.consume()을 클라이언트가 미디어를 받기 위해 생성되었던 webRTC transport에서 호출한다. 
따라서 서버 측 소비자를 생성한다. 
일단 원격 endpoint에서 생성된 이후에 서버사이드 컨슈머를 paused: true로 처리하고 다시 재개하는 것을 추천합니다.

4. 서버 어플리케이션은 원격 클라이언트 어플리케이션에 컨슈머 정보와 파라미터를 전송합니다. (transport.consume() in Local transport)
처음 transport.consume()을 호출하는 경우 connect가 발생된다.

5. 마지막으로 클라이언트 사이드에서 Consumer 인스턴스와 함께 transport.consume()이 해결된다.

Producing Data (DataChannels)
일단 send transport가 생성되면, 클라이언트 사이드 어플리케이션은 다양한 데이터채널을 produce할 수 있다. 
1. 어플리케이션은 local send transport에서 transport.produceData()를 호출한다.
transport.produceData()의 첫번째 호출인 경우 connect가 처리된다.
transport는 producedata를 호출할 것이며, 서버에 이벤트 파라미터를 전송하며 서버 사이드에서 DataProducer를 생성한다.

2. 마침내 transport.produceData()는 클라이언트 사이드에서 DataProducer 인스턴스와 해결된다.

Consuming Data (DataChannels)
일단 receive transport가 만들어지면 클라이언트 사이드 어플리케이션은 다양한 데이터채널을 소비할 수 있다. 그러나 순서는 반대이다.
(consumer는 서버에서 먼저 생성되어야 한다)

1. 서버 어플리케이션은 클라이언트가 데이터를 받기 위해 생성되었던 webRTC transport내에서 transport.consumeData()를 호출한다.
서버사이드에서 DataConsumer를 생성하며..

2. 서버 사이드 어플리케이션은 컨슈머 정보와 파라미터를 클라이언트 어플리케이션에게 전송한다. 
이는 로컬 receive transport 안에서 transport.consumeData()를 호출한다.
trnasport는 첫 transport.consumeData() 호출에 connect 이벤트를 호출한다.

3. 마지막으로 trasport.consumeData()는 클라이언트 사이드에서 DataConsumer와 함께 해결된다. 

Communicating Actions and Events
핵심 개념으로서, 미디어수프 인스턴스에서 메소드를 호출하는것은 해당 인스턴스에서 직접 이벤트가 생성하지 않는다. 
요약하면 router, transport, producer, consumer, data producer 또는 data consumer에서 close를 호출하는 것은
그 위에서 처리되지 않는다.

클라이언트나 서버에서 인스턴스가 close될 때, 어플리케이션은 그것의 closure를 close를 호출해야 하는 다른 사이드에게 신호로 보낸다.
서버 사이드 어플리케이션은 따라오는 closure 이벤트를 듣고 클라이언트에게 알려야 한다.

Transport “routerclose”. The client should call close() on the corresponding local transport.
Producer “transportclose”. The client should call close() on the corresponding local producer.
Consumer “transportclose”. The client should call close() on the corresponding local consumer.
Consumer “producerclose”. The client should call close() on the corresponding local consumer.
DataProducer “transportclose”. The client should call close() on the corresponding local data producer.
DataConsumer “transportclose”. The client should call close() on the corresponding local data consumer.
DataConsumer “dataproducerclose”. The client should call close() on the corresponding local data consumer.

클라이언트나 서버 사이드에서 RTP producer나 consumer가 멈췄을 때 역시 동일하게 일어난다. 이 액션은 다른 사이드에서 일어나야 한다.
추가적으로 서버 사디으 어플리케이션은 따라오는 이벤트를 받아서 클라이언트에게 알려줘야 한다.

Consumer “producerpause”. The client should call pause() on the corresponding local consumer.
Consumer “producerresume”. The client should call resume() on the corresponding local consumer (unless the consumer itself was also paused on purpose).

사이멀캐스트나 SVC가 사용될 때, 어플리케이션은 클라와 서버 사이드 컨슈머 사이에서 preferred layers와 effective layers에 관심을 가질 수 있다.
1. 서버 사이드 어플리케이션은 consumer preferred layers를 설정한다. consumer.setPreferredLayers()를 통해
2. 서버 사이드 consumer는 layerchange 이벤트를 구독하고 클라이언트 어플리케이션에게 effective layers가 전송되었음을 알린다.

댓글