Skip to content

Commit 913cbe5

Browse files
committed
example: make a virtual v4l2 camera via picamera2 and opencv
1 parent f7d3e75 commit 913cbe5

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

example/virtual_cam.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
from picamera2 import Picamera2, MappedArray
2+
import cv2
3+
import time
4+
import subprocess
5+
6+
width = 1280
7+
height = 720
8+
video_nr = 9
9+
virtual_camera = f"/dev/video{video_nr}"
10+
11+
picam2 = Picamera2()
12+
config = picam2.create_preview_configuration(main={"size": (width, height)})
13+
picam2.configure(config)
14+
15+
ffmpeg_cmd = [
16+
"ffmpeg",
17+
"-f",
18+
"rawvideo",
19+
"-pix_fmt",
20+
"yuv420p",
21+
"-s",
22+
f"{width}x{height}",
23+
"-i",
24+
"-",
25+
"-f",
26+
"v4l2",
27+
virtual_camera,
28+
]
29+
ffmpeg_process = subprocess.Popen(ffmpeg_cmd, stdin=subprocess.PIPE)
30+
31+
32+
def reset_v4l2loopback():
33+
try:
34+
print("Resetting v4l2loopback...")
35+
subprocess.run(["sudo", "rmmod", "v4l2loopback"], check=True)
36+
subprocess.run(
37+
[
38+
"sudo",
39+
"modprobe",
40+
"v4l2loopback",
41+
"devices=1",
42+
f"video_nr={video_nr}",
43+
"card_label=ProcessedCam",
44+
"max_buffers=4",
45+
"exclusive_caps=1",
46+
],
47+
check=True,
48+
)
49+
print("v4l2loopback reset successfully.")
50+
except subprocess.CalledProcessError as e:
51+
print(f"Error resetting v4l2loopback: {e}")
52+
53+
54+
def process_frame(request):
55+
56+
timestamp = time.strftime("%Y-%m-%d %X")
57+
58+
with MappedArray(request, "main") as m:
59+
frame = m.array
60+
61+
font = cv2.FONT_HERSHEY_SIMPLEX
62+
font_scale = 1
63+
color = (0, 255, 0)
64+
thickness = 2
65+
position = (10, 30)
66+
cv2.putText(frame, timestamp, position, font, font_scale, color, thickness)
67+
yuv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_I420)
68+
69+
try:
70+
ffmpeg_process.stdin.write(yuv_frame.tobytes())
71+
except BrokenPipeError:
72+
print("ffmpeg pipe broken. Stopping frame processing.")
73+
exit()
74+
75+
76+
try:
77+
reset_v4l2loopback()
78+
79+
print(f"Streaming to {virtual_camera}...")
80+
picam2.pre_callback = process_frame
81+
picam2.start()
82+
83+
while True:
84+
time.sleep(1)
85+
86+
except KeyboardInterrupt:
87+
print("Stopping stream...")
88+
89+
finally:
90+
picam2.stop()
91+
if ffmpeg_process.stdin:
92+
ffmpeg_process.stdin.close()
93+
ffmpeg_process.terminate()
94+
ffmpeg_process.wait()
95+
print("Stream stopped.")

0 commit comments

Comments
 (0)