I am trying to use OpenCV to combine two .AVI videos, but having little success. I want a combined final video that plays the two videos sequentially.
The two input videos were created with Fiji's TrackMate algorithm. They are 6.6 and 6.2 MB, each only 10 seconds, but the output file is only 14 KB and does not play at all in VLC Media Player, so I am surely doing something wrong. Any input would be greatly appreciated: How do I combine two .AVI videos into a single one?
My code is below; it is adapted from this answer with what I think is the correct FourCC:
import cv2
path = '/Volumes/GQA HD/GQA Experiments/2023_01_27/'
file1 = 'TrackMate capture of 1.avi'
file2 = 'TrackMate capture of 2.avi'
file_combined = 'TrackMate Combined captures of IMG_0240.avi'
# Paths of videos
videos = [path+file1, path+file2]
# Create new video
fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
frameSize=(720,1280)
fps=30
video = cv2.VideoWriter(path+file_combined, fourcc, fps, frameSize)
# Write all frames sequentially to new video
for v in videos:
curr_v = cv2.VideoCapture(v)
while curr_v.isOpened():
r, frame = curr_v.read() # Get return value and curr frame of curr video
if not r:
break
video.write(frame) # Write the frame
video.release() # Save the video
frameSize
should probably be (1280, 720)
instead of (720, 1280)
.
OpenCV size conventions is (width
, height
), when width is the number of columns in the horizontal dimension, and height is the number of row in the vertical dimension.
We may resize frame
to (width, height)
, before writing it, just in case:
if frame.shape[0] != height or frame.shape[1] != width:
frame = cv2.resize(frame, (width, height))
video.write(frame)
Complete code sample:
import cv2
do_create_sample_video_files = False
if do_create_sample_video_files:
# Create sample video files for testing (use FFmpeg CLI for creating synthetic video files).
import subprocess as sp
import shlex
sp.run(shlex.split('ffmpeg -y -f lavfi -i testsrc=1280x720:rate=1:duration=300 -vcodec libx264 sample1.avi'))
sp.run(shlex.split('ffmpeg -y -f lavfi -i testsrc=640x360:rate=1:duration=300 -vcodec libx264 sample2.avi')) # Use other resolution for testing
path = './'
file1 = 'sample1.avi'
file2 = 'sample2.avi'
file_combined = 'CombinedSample1Sample2.avi'
# Paths of videos
videos = [path+file1, path+file2]
# Create new video
width, height = 1280, 720
fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
frameSize = (width, height) #(720,1280) <-- Probably supposed to be (1280, 720).
fps=30
video = cv2.VideoWriter(path+file_combined, fourcc, fps, frameSize)
# Write all frames sequentially to new video
for v in videos:
curr_v = cv2.VideoCapture(v)
while curr_v.isOpened():
r, frame = curr_v.read() # Get return value and curr frame of curr video
if not r:
break
if frame.shape[0] != height or frame.shape[1] != width:
# Resize frame to the resolution of the destination video if required.
frame = cv2.resize(frame, (width, height))
video.write(frame) # Write the frame
video.release()