반응형

https://ryu-earth.tistory.com/entry/Python-JS-WebRTC-%EC%98%88%EC%A0%9C-%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4-%EC%98%88%EC%8B%9C

 

[Python & JS] WebRTC 예제 & 시나리오 예시

WebRTC가 궁금하면 여기에 참고 https://ryu-earth.tistory.com/entry/WebRTC-vs-WebSocket WebRTC vs WebSocketWebRTC와 WebSocket은 둘 다 브라우저 간 실시간 데이터 전송을 가능하게 해주지만, 목적과 동작 방식이 다르다

ryu-earth.tistory.com

  • 브라우저 또는 앱 간 P2P 실시간 통신 기술
  • 영상, 음성, 데이터 스트림 전송 가능
  • Python에서는 aiortc 라이브러리로 구현 가능

 


Python WebRTC 개발 구조

  1. PeerConnection 생성
  2. DataChannel or MediaTrack 설정
  3. off/answer 교환 (시그널링 필요)
  4. P2P 통신 실행


설치

pip install aiortc websockets

 

https://github.com/aiortc/aiortc

 

GitHub - aiortc/aiortc: WebRTC and ORTC implementation for Python using asyncio

WebRTC and ORTC implementation for Python using asyncio - aiortc/aiortc

github.com

 


Python WebRTC DataChannel P2P 예제

peer_a.py (initiator)

import asyncio
from aiortc import RTCPeerConnection, RTCSessionDescription

async def run_offer():
    pc = RTCPeerConnection()
    channel = pc.createDataChannel("chat")

    @channel.on("open")
    def on_open():
        print("DataChannel open!")
        channel.send("Hello from A!")

    @channel.on("message")
    def on_message(message):
        print(f"Received: {message}")

    offer = await pc.createOffer()
    await pc.setLocalDescription(offer)
    print("=== Offer ===")
    print(pc.localDescription.sdp)

    sdp = input("Paste answer SDP:\n")
    await pc.setRemoteDescription(RTCSessionDescription(sdp, type="answer"))

    await asyncio.sleep(10)

asyncio.run(run_offer())

 

peer_b.py (receiver)

import asyncio
from aiortc import RTCPeerConnection, RTCSessionDescription

async def run_answer():
    pc = RTCPeerConnection()

    @pc.on("datachannel")
    def on_datachannel(channel):
        @channel.on("message")
        def on_message(message):
            print(f"Received: {message}")
            channel.send("Hello from B!")

    sdp = input("Paste offer SDP:\n")
    await pc.setRemoteDescription(RTCSessionDescription(sdp, type="offer"))

    answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)
    print("=== Answer ===")
    print(pc.localDescription.sdp)

    await asyncio.sleep(10)

asyncio.run(run_answer())

 

  • pc = RTCPeerConnection()개발구조 1번
  • createDataChannel() 또는 @pc.on("datachannel") 개발구조 2번
  • createOffer(), setLocalDescription(), setRemoteDescription()개발구조 3번
  • DataChannel의 open/메시지 주고받기 → 개발구조 4번
개발구조 단계 코드 위치
1. PeerConnection 생성 pc = RTCPeerConnection()
2. DataChannel 설정 createDataChannel() & @pc.on("datachannel")
3. offer/answer 교환 createOffer(), setLocalDescription(), setRemoteDescription()
4. 통신 실행 DataChannel on_open, on_message 핸들러

 


Python WebSocket 시그널링 서버 예제

import asyncio
import websockets

clients = set()

async def signaling_handler(websocket, path):
    clients.add(websocket)
    try:
        async for message in websocket:
            await asyncio.wait([ws.send(message) for ws in clients if ws != websocket])
    finally:
        clients.remove(websocket)

start_server = websockets.serve(signaling_handler, "localhost", 9999)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

 

 


개발 시 주의사항

이슈 원인 해결
P2P 연결 안 됨 STUN 서버 미설정, NAT 환경 STUN 서버 추가 설정
시그널링 기능 없음 aiortc에는 기본 시그널링 서버 없음 WebSocket 서버 직접 구현
DataChannel 연결 안 됨 offer/answer 교환 전 DataChannel 생성 문제 생성 순서 및 이벤트 핸들러 확인
영상 전송 시 지연/버벅임 프레임 크기, 캡처 성능 이슈 비동기 처리 최적화, 프레임 크기 조절

STUN 서버 등록 예시

*STUN 서버: NAT 환경에서 클라이언트가 공인 IP 주소와 포트를 확인하여 다른 피어와 직접 통신하도록 돕는 서버
 
pc = RTCPeerConnection(configuration={"iceServers": [{"urls": "stun:stun.l.google.com:19302"}]})

 


WebRTC 특징 정리

  • WebRTC API가 브라우저처럼 내장되어 있지 않음
  • aiortc 라이브러리로 P2P 실시간 통신 가능
  • 시그널링 서버, STUN/TURN 서버 직접 구성 필요
  • 영상, 음성, 데이터 전송 모두 구현 가능
  • 데스크탑, 서버, IoT 환경에 적합

 

용도 구현 방식
데이터 전송 DataChannel 사용
영상/음성 스트림 MediaStreamTrack 상속 & 커스텀 구현
시그널링 서버 Python WebSocket 직접 구현
NAT 통과 STUN/TURN 서버 설정
반응형

+ Recent posts