face-censor / src /processors /stream_processor.py
Spring-0's picture
Synced repo using 'sync_with_huggingface' Github Action
2012550 verified
import cv2
from .processor import MediaProcessor
import subprocess
class LiveStreamProcessor:
def __init__(self, detector, censor):
self.detector = detector
self.censor = censor
self.processor = MediaProcessor(detector, censor)
def process_stream(self,
source,
output_type=None,
output_dest=None,
conf_thresh=0.4,
preview_stream=False):
capture = cv2.VideoCapture(source)
if not capture.isOpened():
raise ValueError(f"Could not open video source {source}")
width = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = int(capture.get(cv2.CAP_PROP_FPS))
output = self.initialize_output(output_type, output_dest, width, height, fps)
try:
while True:
ret, frame = capture.read()
if not ret:
break
detections = self.detector.detect(frame)
for bbox in detections:
if bbox[4] >= conf_thresh:
frame = self.censor.apply(frame, bbox)
if output_type == "rtmp":
output.stdin.write(frame.tobytes())
else:
raise ValueError(f"Invalid output_type: {output_type}, try 'rtmp'?")
if preview_stream:
cv2.imshow("Stream Preview", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
finally:
capture.release()
if output:
self.cleanup_output(output, output_type)
cv2.destroyAllWindows()
def initialize_output(self, output_type, output_dest, width, height, fps):
if output_dest == None:
raise ValueError("output_dest cannot be None, provide valid output destination.")
if output_type == "rtmp":
command = [
"ffmpeg",
"-y", # Overwrite output files
"-f", "rawvideo",
"-vcodec", "rawvideo",
"-pix_fmt", "bgr24",
"-s", f"{width}x{height}",
"-r", str(fps),
"-i", "-", # Input from pipe
"-c:v", "libx264",
"-pix_fmt", "yuv420p",
"-preset", "ultrafast",
"-f", "flv",
output_dest # RTMP URL
]
return subprocess.Popen(command, stdin=subprocess.PIPE)
return None
def cleanup_output(self, output, output_type):
if output_type == "rtmp":
output.stdin.close()
output.wait()