11"""
22Camera Stream to Virtual V4L2 Device
33------------------------------------
4- This script captures images from the Raspberry Pi camera and streams them
4+ This script captures images from the Raspberry Pi camera and streams them
55to a virtual V4L2 loopback device using OpenCV.
66
77Usage:
88 1. Install required dependencies:
99 pip install opencv-python picamera2
10-
10+
1111 2. Load v4l2loopback module (if not already loaded):
12- sudo modprobe v4l2loopback devices=1 video_nr=16 card_label=ProcessedCam max_buffers=4 exclusive_caps=1
13-
12+ sudo modprobe v4l2loopback devices=1 video_nr=8 card_label=ProcessedCam max_buffers=4 exclusive_caps=1
13+
1414 3. Run the script:
1515 python virtual_cam.py
1616
1717 4. Test the video output:
18- /path/to/pi-webrtc --camera=v4l2:16 --width=1920 --height=1080 ... # View the processed feed by WebRTC
19- ffplay /dev/video16 # View the processed feed by ffplay
18+ /path/to/pi-webrtc --camera=v4l2:8 --width=1920 --height=1080 ... # View the processed feed by WebRTC
19+ ffplay /dev/video8 # View the processed feed by ffplay
2020
2121Requirements:
2222 - Raspberry Pi with Camera Module
2929import fcntl
3030import v4l2
3131import logging
32+ import argparse
3233from picamera2 import Picamera2 , MappedArray
3334
3435logging .basicConfig (
3738
3839
3940class VirtualCameraStreamer :
40- def __init__ (self , video_nr , camera_id = 0 , width = 1920 , height = 1080 ):
41+ def __init__ (self , width , height , camera_id , virtual_camera ):
4142 self .width = width
4243 self .height = height
4344 self .camera_id = camera_id
44- self .virtual_camera = f"/dev/video { video_nr } "
45+ self .virtual_camera = virtual_camera
4546 self .fd = None
4647 self .picam2 = None
4748
@@ -88,13 +89,17 @@ def _process_frame(self, request):
8889 self .stop ()
8990
9091 def start (self ):
92+ logging .info (f"Starting streamer with:" )
93+ logging .info (f" Resolution: { self .width } x{ self .height } " )
94+ logging .info (f" Camera ID: { self .camera_id } " )
95+ logging .info (f" Output To Virtual Device: { self .virtual_camera } " )
96+
9197 if not self .fd :
9298 logging .error ("Cannot start streaming without virtual device." )
9399 return
94100
95101 self .picam2 .pre_callback = self ._process_frame
96102 self .picam2 .start ()
97- logging .info (f"Start streaming to { self .virtual_camera } ..." )
98103
99104 try :
100105 while True :
@@ -113,5 +118,23 @@ def stop(self):
113118
114119
115120if __name__ == "__main__" :
116- streamer = VirtualCameraStreamer (16 , camera_id = 1 )
121+ parser = argparse .ArgumentParser (description = "Start virtual camera streamer" )
122+ parser .add_argument ("--width" , type = int , default = 1920 , help = "Frame width" )
123+ parser .add_argument ("--height" , type = int , default = 1080 , help = "Frame height" )
124+ parser .add_argument ("--camera-id" , type = int , default = 0 , help = "Camera input ID" )
125+ parser .add_argument (
126+ "--virtual-device" ,
127+ type = str ,
128+ default = "/dev/video8" ,
129+ help = "Virtual video device path" ,
130+ )
131+ args = parser .parse_args ()
132+
133+ streamer = VirtualCameraStreamer (
134+ width = args .width ,
135+ height = args .height ,
136+ camera_id = args .camera_id ,
137+ virtual_camera = args .virtual_device ,
138+ )
139+
117140 streamer .start ()
0 commit comments