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

[파이썬] 윈도우 화면 캡처 웹 스트리밍(with flask, dxcam, opencv)

by 만들오 2024. 5. 22.

윈도우 화면 캡처는 여러 버전으로 글을 쓰고 있습니다.

이번 글은, 캡처한 윈도우 화면을 웹으로 스트리밍하는 버전입니다.


라이브러리 설치
pip install Flask Flask-Cors opencv-python dxcam pywin32

 

 

app.py
#!/usr/bin/env python
from flask import Flask, Response
from flask_cors import CORS
import io
import cv2
import dxcam
import win32gui
import os

win_hwnd = 0

#윈도우에 실행중인 프로그램 목록 가져오기
def get_win_list():
    def callback(hwnd, hwnd_list: list):
        title = win32gui.GetWindowText(hwnd)
        if win32gui.IsWindowEnabled(hwnd) and win32gui.IsWindowVisible(hwnd) and title:
            hwnd_list.append((title, hwnd))
        return True
    output = []
    win32gui.EnumWindows(callback, output)
    return output

#특정 윈도우가 있는 위치 및 크기 가져오기
def get_win_size(hwnd):
    left, top, right, bottom = win32gui.GetWindowRect(hwnd)
    return left, top, right, bottom

#플라스크 웹서버 생성
app = Flask(__name__)

#화면캡처 생성
cam = dxcam.create(output_color="BGR")
cam.start(target_fps=5)

#스트리밍 구현부
def gen():
    while True:
        frame = cam.get_latest_frame()
        if win_hwnd != 0:
            x1, y1, x2, y2 = get_win_size(win_hwnd)
            frame = frame[y1:y2, x1:x2]
        # frame = cv2.resize(frame, dsize=(0,0), fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
        encode_return_code, image_buffer = cv2.imencode('.jpg', frame)
        io_buf = io.BytesIO(image_buffer)
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + io_buf.read() + b'\r\n')

#라우팅 구성
@app.route('/')
def video_feed():
    return Response(
        gen(),
        mimetype='multipart/x-mixed-replace; boundary=frame'
    )

#command line으로 입력받는 부분
while True:
    win_list = get_win_list()
    win_list.insert(0, ('전체화면', 0))
    os.system("cls")
    for i in range(len(win_list)):
        print(f'{i} - {win_list[i][0]}')
    user_input = input("캡처할 윈도우의 숫자를 입력하세요 : ")
    select = int(user_input)
    #잘못된 숫자입력 처리
    if select < 0 or select >= len(win_list):
        print("올바른 숫자를 입력하세요.")
    else: break

win_hwnd = win_list[select][1]
print(f'{win_list[select][0]}의 스트리밍을 시작합니다.')
app.run(host="0.0.0.0", port=8000, debug=False, threaded=True)

 

실행하면 현재 실행중인 윈도우 목록을 나열하고 선택하도록 합니다.

선택한 윈도우만 캡처하여 브라우저로 스트리밍 하도록 코드를 구성했습니다.

 

다음과 같이 스트리밍 URL이 나오는데, http://127.0.0.1:8000 주소가 내부전용으로 좀 더 빠른 것 같습니다.

 

[끝].

728x90

댓글