[TIL] webRTC Mediasoup

최하온·2024년 4월 22일
0

TIL

목록 보기
66/71
post-thumbnail

[0] getUserMedia()를 통해 stream이 성공적으로 받아와 진다.

[1] 각 클라이언트는 new Device()를 통해 객체를 생성, 라우터로부터 rtpCapabilities를 받아 device.load() 실행

  • Device 객체 : 클라이언트 측에서 라우터와 연결하고 데이터를 주고 받는 엔드포인트 역할을 하는 객체. javascript 클라이언트 측에서의 진입점이 된다.
  • router.rtpCapabilities : mediasoup router 객체의 프로퍼티로서 mediasoup 또는 endpoint가 받을 수 있는 미디어 수준을 결정한다.
  • device.load() : device는 허용되는 미디어 코덱 정보 및 다른 설정 정보들을 불러옴
const createDevice = async () => {
  try {
    device = new mediasoupClient.Device();

    await device.load({
      routerRtpCapabilities: rtpCapabilities,
    });
// webRTCTransport 생성
    createSendTransport();

[2] 서버에선 webRTCTransport 를 producer, consumer 쪽으로 하나씩 생성. 이를 위해서는 listenIPs나 enableUdp 등등의 options 정보가 필요 함

  @SubscribeMessage('createWebRtcTransport')
  async handleCreateTransport(): Promise<void> {
    const initialAvailableOutgoingBitrate = config.mediasoup.WebRtcTransport.initialAvailableOutgoingBitrate;

    try {
      const transport = await router.createWebRtcTransport({
        listenIps: config.mediasoup.WebRtcTransport.listenIps,
        enableUdp: true,
        enableTcp: true,
        preferUdp: true,
        initialAvailableOutgoingBitrate,
      });
      console.log(`transport_id, ${transport.id}`);
      // 생성한 Transport 정보 클라이언트에 반환
      this.server.emit('createWebRtcTransport', {
        transport,
        params: {
          id: transport.id,
          iceParameters: transport.iceParameters,
          iceCandidates: transport.iceCandidates,
          dtlsParameters: transport.dtlsParameters,
        },
      });
    } catch (error) {
      console.error('Error creating transport:', error);
    }
  }

[3] 양쪽의 webRTCTransport로부터 parameter들을 받아와 Client로 전송 → SEND Transport와 RECV Transport를 생성
[4] producer 클라이언트가 SEND Transport에서 produce 메서드를 호출하는 경우 인자로 encodings, codecOptions 와 같은 파라미터들을 넣어주고, 이 메서드는 producer 를 반환

const createSendTransport = async () => {
  socket.emit('createWebRtcTransport');

  await socket.on('createWebRtcTransport', data => {

    const { transport, params } = data;
    if (params.error) {
      console.log(params.error);
      return;
    }
    producerTransport = device.createSendTransport(params);
    console.log('createSendTransport ~ producerTransport:', producerTransport);

    producerTransport.on('connect', async ({ dtlsParameters }, callback, errback) => {
      try {
        // 로컬 DTLS 매개변수를 서버 측 transport에 신호 전달
        socket.emit('transport-connect', { dtlsParameters });

        // transport에 parameters들이 전송되었다는 것을 알려주는 역할!
        callback();
      } catch (error) {
        errback(error);
      }
    });

    producerTransport.on('produce', async (parameters, callback, errback) => {
      try {
        // 서버에게 파라미터와 함께 Producer 생성 요청.
        // 생성하고 서버 측 Producer id받기
        socket.emit(
          'transport-produce',
          {
            kind: parameters.kind,
            rtpParameters: parameters.rtpParameters,
            appData: parameters.appData,
          },
          ({ id }) => {
            callback({ id });
          },
        );
      } catch (error) {
        errback(error);
      }
    });

    connectSendTransport();

다음 로직은 구현하지 못해 추후 구현 후 기술 예정

참고 자료
WebRTC: mediasoup (SFU) introduction - Part 1
MediaSoup 을 사용해서 SFU방식으로 VideoChat 구현하기(1/2) 이론
mediasoup-client documentation

0개의 댓글