Reputation: 87
I want to write a video file using two videos side-by-side, but at the end the output file is not playable in any video player. This is my code:
from __future__ import print_function
import numpy as np
import argparse
import cv2
import tkinter as tk
from tkinter import filedialog
import os
import os.path
ap = argparse.ArgumentParser()
ap.add_argument("-o", "--output", type=str, default="sample.avi",
help="path to output video file")
ap.add_argument("-f", "--fps", type=int, default=100.0,
help="FPS of output video")
ap.add_argument("-c", "--codec", type=str, default="MJPG",
help="codec of output video")
args = vars(ap.parse_args())
root = tk.Tk()
root.withdraw()
source_video = filedialog.askopenfilename(title="Select file")
sign = filedialog.askopenfilename(title="Select file")
print("[INFO] Capturing video...")
cap1 = cv2.VideoCapture(source_video)
cap2 = cv2.VideoCapture(sign)
fourcc = cv2.VideoWriter_fourcc(*args["codec"])
writer = None
(h, w) = (None, None)
zeros = None
i = 0
try:
while cap1.isOpened():
ret, frame1 = cap1.read()
if ret:
frame1 = cv2.resize(frame1, (0, 0), fx=0.5, fy=0.5)
(h, w) = frame1.shape[:2]
ret, frame2 = cap2.read()
if ret:
frame2 = cv2.resize(frame2, (w, h))
else:
break
if writer is None:
writer = cv2.VideoWriter(args["output"], fourcc, args["fps"],
(h, w*2), True)
zeros = np.zeros((h, w*2), dtype="uint8")
output = np.zeros((h, w*2, 3), dtype="uint8")
if frame2 is None:
output[0:h, 0:w] = frame1
writer.write(output)
else:
output[0:h, 0:w] = frame1
output[0:h, w:w * 2] = frame2
writer.write(output)
cv2.imshow('output', output)
if cv2.waitKey(25) & 0xFF == ord('q'):
break
writer.release()
cv2.destroyAllWindows()
except Exception as e:
print(str(e))
I don't get any error all the things going well but when I try to play output video file from the directory it will not play. I also check file size which is about 16KB. I don't know where the problem exist. please help me. I'm using: Windows 10 64-bit Python3.7 Pycharm as IDE
Upvotes: 5
Views: 8727
Reputation: 31
** Solved ** The problem happens when your camera generates a video size different than the video size of the file you are trying to create.
For example: my IP camera generates frames of size(1920,1080) and in the tutorial i found the code they are trying to write a file with the size (640,480).
What i did for solving the problem is to take the width and height from the video camera and put them into the videoWriter method.
Here you have the code that will work with any size of video:
import cv2
# desde la vídeo cámara: indicar ruta IP del stream
# desde file, indicar ruta de archivo
# desde cámara web: usar el número 0,1 ó -1
cap = cv2.VideoCapture('rtsp://admin:[email protected]:554/Streaming/Channels/1')
# fourcc es el código del tipo de vídeo XVID = MPEG4
fourcc = cv2.VideoWriter_fourcc(*'XVID')
print("vídeo operativo: ",cap.isOpened())
videoWidth = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
videoHeight = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
print("ancho: ",videoWidth)
print("altura: ",videoHeight)
# 20= frames x segundo, (640x480) = tamaño del vídeo que grabaremos
# el tamaño del vídeo que se grabará debe ser igual al capturado de la cámara
out = cv2.VideoWriter('output_file.avi',fourcc, 20.0,(videoWidth,videoHeight))
while(cap.isOpened()): # si el file no existe, o no hay vídeo de la fuente indicada, dará False
# en este bucle se captura el vídeo frame por frame (cuadro por cuadro)
ret,frame = cap.read() # "ret" puede ser t/f dependiendo si se captura vídeo o no, "frame" contendrá el vídeo
if ret == True:
out.write(frame) # escribir en el file
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # convertir a gris el vídeo
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
Upvotes: 3
Reputation: 11301
The frameSize
parameter for VideoWriter
is (width, height), which is somewhat hidden in the docs (e.g., here). So in your code, it should be
writer = cv2.VideoWriter(args["output"], fourcc, args["fps"], (w*2, h), True)
After this fix, your code produced working videos for me.
I noticed that your code "learns" the frame size from the input video but not the frame rate, but I assume this is intentional.
Upvotes: 10