본문 바로가기
소프트웨어/파이썬

[파이썬] Websocket 으로 영상 송수신하기

by 만들오 2021. 1. 23.

안녕하세요? 만들오 입니다.

 

오늘은 Websocket 통신으로 영상을 수신받아 화면에 보여주는것을 구현하겠습니다.

 

1. 필요한 모듈 설치

pip install opencv-python

위 모듈을 설치하면 자동으로 opencv와 numpy까지 설치가 됩니다.

 

2. 전체 코드

<!--videosender.html-->
<!DOCTYPE html>
<html>
<head>
	<title>Hello</title>
</head>
<body>
	<video id="videoInput" style="display:none"></video>
  <canvas id="videoOutput"></canvas>
  <button onclick=stream()>Send</button>
</body>
<script>
  var w = 320, h = 240;
	var url = "ws://localhost:3000"
	var ws = new WebSocket(url);
	ws.onopen = function(){
		console.log("Websocket is connected.");
	}
	ws.onmessage = function(msg){
		console.log(msg.data);
	}

	navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
  var constraints = {audio: false, video: true};
  var video = document.getElementById("videoInput");
  video.width = w;
  video.height = h;
  function successCallback(stream){
  	video.srcObject = stream;
  	video.play();
  }
  
  function errorCallback(error){
   	console.log(error);
  }
  navigator.getUserMedia(constraints, successCallback, errorCallback);
	var canvas = document.getElementById("videoOutput");
  canvas.width = w;
  canvas.height = h;
  var ctx = canvas.getContext("2d");
  function processImage(){
        ctx.drawImage(video, 0, 0, w, h);
        setTimeout(processImage, 1);
  }
  processImage();

  function stream(){
    setInterval(sendImage, 30);
  }

  function sendImage(){
    var rawData = canvas.toDataURL("image/jpeg", 0.5);
    ws.send(rawData);
  }
</script>
</html>
#video_server.py
from simple_websocket_server import WebSocketServer, WebSocket
import base64, cv2
import numpy as np
import warnings
warnings.simplefilter("ignore", DeprecationWarning)

class SimpleEcho(WebSocket):
    def handle(self):
        msg = self.data
        img = cv2.imdecode(np.fromstring(base64.b64decode(msg.split(',')[1]), np.uint8), cv2.IMREAD_COLOR)
        cv2.imshow('image', img)
        cv2.waitKey(1)
        

    def connected(self):
        print(self.address, 'connected')

    def handle_close(self):
        print(self.address, 'closed')


server = WebSocketServer('localhost', 3000, SimpleEcho)
server.serve_forever()

3. 작동 설명

3.1. videosender.html

  function processImage(){
        ctx.drawImage(video, 0, 0, w, h);
        setTimeout(processImage, 1);
  }

위 코드는 WebRTC를 이용해 카메라를 호출하고, 이를 <canvas> 태그로 복사합니다. 1 ms 마다 화면을 갱신합니다.

 

  function sendImage(){
    var rawData = canvas.toDataURL("image/jpeg", 0.5);
    ws.send(rawData);
  }

위 코드는 canvas의 이미지를 dataURL 형식으로 변경하고 웹소켓으로 보내는 코드입니다.

dataURL은 이미지를 문자열로 표현한 형태이기 때문에 웹소켓으로 전송이 가능합니다.

 

var url = "ws://localhost:3000"
var ws = new WebSocket(url);
ws.onopen = function(){
	console.log("Websocket is connected.");
}
ws.onmessage = function(msg){
	console.log(msg.data);
}

위 코드는 웹소켓 생성 및 설정부 입니다.

localhost를 실제 ip주소로 변경하면 다른 pc 혹은 모바일에서도 가능합니다.

 

3.2. video_server.py

def handle(self):
    msg = self.data
    img = cv2.imdecode(np.fromstring(base64.b64decode(msg.split(',')[1]), np.uint8), cv2.IMREAD_COLOR)
    cv2.imshow('image', img)
    cv2.waitKey(1)

웹소켓을 통해 메시지(dataURL)를 받으면 opencv로 읽을수 있는 형태로 변환합니다.

 

server = WebSocketServer('localhost', 3000, SimpleEcho)

웹소켓 서버를 생성합니다. localhost 부분은 ip주소(예를들면 192.168.0.1), 3000은 port 번호입니다.

 

3.1의 videosender의 ip주소와 port 번호를 동일하게 입력해야만 연결이 됩니다.

 

* 이 글은 티스토리 카카오계정 연동정책으로 인해 이전 블로그(오코취) 글을 옮겨왔습니다.

[].

728x90

댓글