|
import uuid |
|
from pathlib import Path |
|
|
|
import cv2 |
|
import streamlit as st |
|
from aiortc.contrib.media import MediaRecorder |
|
from streamlit_webrtc import WebRtcMode, webrtc_streamer |
|
|
|
from sample_utils.turn import get_ice_servers |
|
from cvzone.HandTrackingModule import HandDetector |
|
import numpy as np |
|
|
|
RECORD_DIR = Path("./records") |
|
RECORD_DIR.mkdir(exist_ok=True) |
|
|
|
|
|
keys = [ |
|
["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"], |
|
["A", "S", "D", "F", "G", "H", "J", "K", "L", ";"], |
|
["Z", "X", "C", "V", "B", "N", "M", ",", ".", "/"], |
|
] |
|
|
|
|
|
class Button: |
|
def __init__(self, pos, text, size=(100, 100)): |
|
self.pos = pos |
|
self.size = size |
|
self.text = text |
|
|
|
def draw(self, img): |
|
x, y = self.pos |
|
w, h = self.size |
|
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 255), cv2.FILLED) |
|
cv2.putText(img, self.text, (x + 20, y + 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 255, 255), 3) |
|
|
|
|
|
button_list = [] |
|
for i, row in enumerate(keys): |
|
for j, key in enumerate(row): |
|
button_list.append(Button((j * 105 + 50, i * 120 + 50), key)) |
|
|
|
|
|
def video_frame_callback(frame): |
|
""" |
|
Process video frames: Overlay a virtual keyboard on the video. |
|
""" |
|
img = frame.to_ndarray(format="bgr24") |
|
|
|
|
|
for button in button_list: |
|
button.draw(img) |
|
|
|
return av.VideoFrame.from_ndarray(img, format="bgr24") |
|
|
|
|
|
def virtual_keyboard_app(): |
|
""" |
|
Streamlit application for displaying a virtual keyboard. |
|
""" |
|
if "prefix" not in st.session_state: |
|
st.session_state["prefix"] = str(uuid.uuid4()) |
|
prefix = st.session_state["prefix"] |
|
|
|
|
|
in_file = RECORD_DIR / f"{prefix}_input.flv" |
|
out_file = RECORD_DIR / f"{prefix}_output.flv" |
|
|
|
|
|
def in_recorder_factory() -> MediaRecorder: |
|
return MediaRecorder( |
|
str(in_file), format="flv" |
|
) |
|
|
|
def out_recorder_factory() -> MediaRecorder: |
|
return MediaRecorder(str(out_file), format="flv") |
|
|
|
|
|
webrtc_streamer( |
|
key="record", |
|
mode=WebRtcMode.SENDRECV, |
|
rtc_configuration={"iceServers": get_ice_servers()}, |
|
media_stream_constraints={ |
|
"video": True, |
|
"audio": True, |
|
}, |
|
video_frame_callback=video_frame_callback, |
|
in_recorder_factory=in_recorder_factory, |
|
out_recorder_factory=out_recorder_factory, |
|
) |
|
|
|
|
|
if in_file.exists(): |
|
with in_file.open("rb") as f: |
|
st.download_button( |
|
"Download the recorded video without video filter", f, "input.flv" |
|
) |
|
if out_file.exists(): |
|
with out_file.open("rb") as f: |
|
st.download_button( |
|
"Download the recorded video with virtual keyboard", f, "output.flv" |
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
virtual_keyboard_app() |
|
|