4

I'm on windows 10 using python 3.6.4, installed opencv (3.4) through pip. Here's the code I'm using:

import numpy as np
import cv2
cap = cv2.VideoCapture("rtsp://192.168.0.100:554/onvif1")
while(True):
    ret, frame = cap.read()
    print(frame)
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

[rtsp @ 0000016f6d5995a0] Nonmatching transport in server reply warning: Error opening file (/build/opencv/modules/videoio/src/cap_ffmpeg_impl.hpp:834) warning: rtsp://192.168.0.100:554/onvif1 (/build/opencv/modules/videoio/src/cap_ffmpeg_impl.hpp:835)

But when I'm using ffmpeg code:

ffplay rtsp://192.168.0.100:554/onvif1 --> Capture oke
ffplay -rtsp_transport udp rtsp://192.168.0.100:554/onvif1 --> Capture oke
ffplay -rtsp_transport tcp rtsp://192.168.0.100:554/onvif1 --> Nonmatching transport in server reply

Can you help me, please?

Mozillaa
  • 51
  • 1
  • 1
  • 5
  • Possible duplicate of [Getting RTSP stream with Opencv and python](https://stackoverflow.com/questions/43743592/getting-rtsp-stream-with-opencv-and-python) – Ollie Graham Oct 24 '19 at 05:07

4 Answers4

12

As mentionned, I tried to put in the python code the following:

import os
  os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;0"

or

import os
  os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;udp"

or

import os
  os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "dummy"

unfortunately none was working as I was still running my program in the same cmd window.

I simply opened a new cmd window and gave a try for a new run... and it works (with "rtsp_transport;0" :)

SoSpoon
  • 156
  • 2
  • 6
  • I don't get it ? please explain your solution ? – Haha TTpro Mar 16 '21 at 17:42
  • os.environ is setting an environment variable, the same as you use the export cmd. And to use it, you have to open a new window so that the new environment variable is taken in account. – SoSpoon Mar 17 '21 at 21:30
4

To force the RTSP to use UDP insted TCP, you can change the enviroment variable OPENCV_FFMPEG_CAPTURE_OPTIONS.

In C/C++ it can be done like that:

#if WIN32
    _putenv_s("OPENCV_FFMPEG_CAPTURE_OPTIONS", "rtsp_transport;udp");
#else
    setenv("OPENCV_FFMPEG_CAPTURE_OPTIONS", "rtsp_transport;udp", 1);
#endif

cap = VideoCapture("rtsp://192.168.0.100:554/onvif1", cv::CAP_FFMPEG);

On Python, I think you can change the environment variable doing that:

import os
os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;udp"

cap = cv2.VideoCapture("rtsp://192.168.0.100:554/onvif1", cv2.CAP_FFMPEG)

I tested only the C++ solution, the Python one I'm not sure. Please test.

Derzu
  • 7,011
  • 3
  • 57
  • 60
  • I tried to understand the problem you said (_putenv_s,setenv,OPENCV_FFMPEG_CAPTURE_OPTIONS) in python but nothing in google. Can you give me more suggestions on this, please ? – Mozillaa May 01 '18 at 16:02
  • @Mozillaa, I just edited my answer adding the python solution, try that. It was based on this answer: https://stackoverflow.com/questions/5971312/how-to-set-environment-variables-in-python – Derzu May 02 '18 at 03:32
  • Thanks for the reply. I followed your tutorial but don't work. Still "Nonmatching transport in server reply". I'm print(os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"]) ==> rtsp_transport;udp. It means environ successful? – Mozillaa May 02 '18 at 13:01
  • Some people suggest editing the file cap_ffmpeg_impl.hpp but I don't know where edit line exactly. – Mozillaa May 02 '18 at 13:10
  • @Mozillaa, if your print(os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"]) shows "rtsp_transport;udp" so the environment variable was set successfully. So now you have another problem, I don't know what is. – Derzu May 02 '18 at 19:46
  • I also no ideas now. If you know a way to solving this problem, please show me. Thanks so much. – Mozillaa May 03 '18 at 14:57
  • Try change cv2.VideoCapture("rtsp://192.168.0.100:554/onvif1") to cv2.VideoCapture("rtsp://192.168.0.100:554/onvif1", apiPreference=cv2.CAP_FFMPEG). I also edited my answer. – Derzu May 04 '18 at 03:57
  • Thanks so much. Good luck to you! – Mozillaa May 05 '18 at 14:23
  • @Mozillaa Does it works after setting the apiPreference to cv2.CAP_FFMPEG ? – Derzu May 05 '18 at 17:22
  • I have one issue with cv2.imshow(). That is on the Linux, cv2.imshow() doesn't work in threading python when I capture two camera source in a program. On the Window 10-64bit, it's work perfect (same the code). Can you help me, please !!! – Mozillaa May 12 '18 at 04:17
  • @Mozillaa, I'm not sure about the problem. But you can try to put the imshow method on the main thread, and just the capture frame process on the others threads, I did this way on my c++ system and is working with multiple cameras. I'm going to upload it to github this weekend, I tell you. – Derzu May 12 '18 at 15:26
  • @Mozillaa check my multi-cam c++ pcr solution. https://github.com/derzu/ONVIF-PVR – Derzu May 14 '18 at 02:55
  • Thank men. I will check it. – Mozillaa May 14 '18 at 04:19
  • I have one issue with cv2.VideoCapture("rtsp://192.168.0.100:554/onvif1"). After a time working perfect, the network has an error in 1 minute and don't capture camera. How to recapture without stop->start script python? – Mozillaa May 18 '18 at 04:12
  • @Mozillaa, what I did on my c++ solution, was after 10 empty reads, I break the read loop, and close the cap (VideoCapture), and then restart the VideoCapture. So I have another loop where the cap is re-initialized when necessary. Try that. – Derzu May 18 '18 at 11:19
  • @Mozillaa If this answer solved you UDP capture issue, please mark it as the correct answer. – Derzu May 18 '18 at 11:20
0

OpenCV defaults to using TCP for RTP transport, and it seems that your device does not support that (as can be seen with FFmpeg). OpenCV stie actually has a question on the same topic. Here is the github issue that mentions switching to TCP. There does not seem to be a way to force UDP in OpenCV. So you have two options:

  1. Recompile OpenCV and enable UDP in the sources by default (the question above mentions how to do that)
  2. Use an older version of OpenCV before this change was introduced
  3. Try to enable TCP on the device
Rudolfs Bundulis
  • 11,636
  • 6
  • 33
  • 71
  • Thank for your reply. I have done like instruction, change file cap_ffmpeg_impl.hpp. But don't know recompile opencv_ffmpeg.dll (what opencv calls). Can you tutorial me recompile. I still search google but it did not work as expected. – Mozillaa Apr 06 '18 at 02:02
  • Well, the OpenCV site has a tutorial - https://docs.opencv.org/3.2.0/d3/d52/tutorial_windows_install.html – Rudolfs Bundulis Apr 06 '18 at 07:56
  • Dear @Rudoff Bundulis. I tried to recompile Opencv from source but still "Nonmatching transport in server reply". The steps I follow: 1 - change cap_ffmpeg_impl.hpp (http://answers.opencv.org/question/120699/can-opencv-310-be-set-to-capture-an-rtsp-stream-over-udp/). 2 - recompile opencv (http://www.learnopencv.com/install-opencv3-on-windows/). What did i do wrong ? – Mozillaa Apr 09 '18 at 00:43
0
  1. Set env variable OPENCV_FFMPEG_CAPTURE_OPTIONS
  2. Create and start a process with video capture code
  3. Join the process
# file package/__main__.py

import os
from multiprocessing import Process
from package.main import run

if __name__ == '__main__':
    os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;udp"
    p = Process(target=run)
    p.start()
    p.join()

# file package/main.py

import numpy as np
import cv2


def run():
    capture = cv2.VideoCapture("rtsp://192.168.1.150/onvif1", cv2.CAP_FFMPEG)
    while True:
        result, frame = capture.read()
        cv2.imshow('video', frame)

        if cv2.waitKey(16) == ord("q"):
            break

lubosmato
  • 51
  • 5