Capture from local device vs tcpstream

I’m just getting started with opencv.

Can I capture a video stream directly from the camera with:

cap = cv.VideoCapture(0, cv.CAP_V4L2)

If I start a stream using libcamera-vid first I can capture the stream.
Terminal 1

pi@dev:~/ $ libcamera-vid -t 0 --nopreview --inline --listen -o tcp://0.0.0.0:9994

Termina2

pi@dev:~/ $ ./test.py
Capture opened
FFMPEG
1900.0
0.0
Got frame
Got frame
Got frame

However, when I use cap = cv.VideoCapture(0, cv.CAP_V4L2) I get

pi@dev:~/ $ ./test.py
Capture opened
V4L2
200.0
-1.0
Can't receive frame (stream end?). Exiting ...

Here’s my test.py

#!/usr/bin/python3

import os
import numpy as np
import cv2 as cv

RTSP_URL = 'tcp://172.16.1.3:9994'
os.environ['OPENCV_FFMPEG_CAPTURE_OPTIONS'] = 'rtsp_transport;udp'
# start stream first!
cap = cv.VideoCapture(RTSP_URL, cv.CAP_FFMPEG)
#cap = cv.VideoCapture(0, cv.CAP_V4L2)

if not cap.isOpened():
    print("Cannot open camera")
    exit()
else:
    print("Capture opened")
    print(cap.getBackendName())
    print(cap.get(cv.CAP_PROP_BACKEND))
    print(cap.get(cv.CAP_PROP_VIDEO_STREAM))

while True:
    # Capture frame-by-frame
    ret, frame = cap.read()
    # if frame is read correctly ret is True
    if not ret:
        print("Can't receive frame (stream end?). Exiting ...")
        break
    print("Got frame")

cap.release()