Search code examples
pythonopencvasynchronousimage-processingvideo-capture

Open two videos simultaneously using open cv? 2nd started abit later


I need to trigger a video play when a specific condition is true in my original video

Example: I have a video playing using open CV. During that video when a certain condition is true, I want another video to pop up and also start playing.

Given that the first video will continue playing without any problem.

This doesn't work, using:

cap=cv2.VideoCapture(path)
while(cap.isOpen()):
    ret,frame=cap.read()
    if(condition):
        cap2=cv2.VideoCapture(path2)
        while(cap2.isOpen()):
            ret2,frame2=cap2.read()
            cv2.imshow("2nd video",frame2)
cv2.imshow('1st video',frame)

Solution

  • You should initialize both VideoCapture classes before the while loop.

    import cv2
    
    cap1 = cv2.VideoCapture("/Movies/B/ex1.mp4")
    cap2 = cv2.VideoCapture("/Movies/B/ex2.mp4")
    

    Assume your condition is:

    • play second video after first 5 frame of the the first video.

    • Therefore I initialize the count variable

      • count = 0
        
    • Then check if whether the first video is opened, and play.

      • while cap1.isOpened():
             ret1, frm1 = cap1.read()
             if ret1:
                  cv2.imshow("frm1", frm1)
                  cv2.waitKey(1)
             else:
                 break
             count += 1
        
        cv2.destroyAllWindows()
        
    • Now we will add our condition. Before we apply our condition criteria, we will set the second frame to None. If the condition is set, then get the input from the cap2 variable

      • while cap1.isOpened():
            ret1, frm1 = cap1.read()
        
            if ret1:
                # condition
                if count > 5:
                    if cap2.isOpened():
                        _, frm2 = cap2.read()
        
                if frm2 is not None:
                    cv2.imshow("frm2", frm2)
                    cv2.waitKey(3)
        
                if frm1 is not None:
                    cv2.imshow("frm1", frm1)
                    cv2.waitKey(3)
        
             count += 1
        
        cv2.destroyAllWindows()
        

    Output:


    enter image description here

    Please note that you don't have to use cv2.waitKey(1). I used it to check whether my code is working or not.

    Code


    import cv2
    
    cap1 = cv2.VideoCapture("b/b19.mp4")
    cap2 = cv2.VideoCapture("b/b22.mp4")
    
    count = 0
    
    frm2 = None
    
    while cap1.isOpened():
        ret1, frm1 = cap1.read()
    
        if ret1:
            # condition
            if count > 5:
                if cap2.isOpened():
                    _, frm2 = cap2.read()
    
            if frm2 is not None:
                cv2.imshow("frm2", frm2)
                cv2.waitKey(3)
    
            if frm1 is not None:
                cv2.imshow("frm1", frm1)
                cv2.waitKey(3)
    
        count += 1
    
    cv2.destroyAllWindows()
    

    Second Option


    You can also use FileVideoStream class for speeding up the video encoding, decoding, and displaying operations, by using Queue structure. As a result, FileVideoStream concurrently handles all the operations. Where VideoCapture class blocks the entire-application during frame encoding, decoding, or displaying.

    import cv2
    from imutils.video import FileVideoStream
    
    cap1 = FileVideoStream("b/b19.mp4").start()
    cap2 = FileVideoStream("b/b22.mp4").start()
    
    count = 0
    
    frm2 = None
    
    while cap1.more():
        frm1 = cap1.read()
    
        if count > 5:
            if cap2.more():
                frm2 = cap2.read()
    
        if frm2 is not None:
            cv2.imshow("frm2", frm2)
            cv2.waitKey(3)
    
        if frm1 is not None:
            cv2.imshow("frm1", frm1)
            cv2.waitKey(3)
        count += 1
    
    cv2.destroyAllWindows()