pythonopencvvideo-processingvideo-compression

OpenCV/Python: FFMPEG: tag is not supported with codec id 12 and format 'mp4 / MP4


I would like to use OpenCV in Python to compile a video from a number of images. I get the error

OpenCV: FFMPEG: tag is not supported with codec id 12 and format 'mp4 / MP4

I searched here for an answer how to fix it. I got an answer in this post, but it does not generate a video, the file is just 5.7kB, no matter which number of images I add.

Here is an example code:

import os
import numpy as np
from glob import glob
import cv2

path = "where to find some images"
fname_video="where the video should go"
os.chdir(path)

size=(1024,768)
fps=20

files = [y for x in os.walk(path) for y in glob(os.path.join(x[0], '*.JPG'))][0:10] # just 10 images

image_array = []
for file in files:
    frame = cv2.imread(os.path.join(path,file),0)
    frame = cv2.resize(frame,size)
    image_array.append(frame)

fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(fname_video, fourcc, fps, size)
for i in range(len(image_array)):
    out.write(image_array[i])
out.release()

Maybe somebody can give me a hint how to get a valid video file?


Solution

    1. File Path Handling: The files list is being created using os.walk and glob, but the os.path.join(path, file) in the loop is redundant because files already contains the full paths.

    2. Grayscale vs. Color: You're reading the images in grayscale (cv2.IMREAD_GRAYSCALE), but the VideoWriter expects color images (3 channels). If you want to create a grayscale video, you need to convert the grayscale images to 3-channel images.

    3. Filename: My file name end with *.jpg. Both are worked after change name from *.JPG to *.jpg.

    New Method:-

    Instead of 'mp4v', try using a more widely supported codec like 'XVID' or 'MJPG'

    import os
    import numpy as np
    from glob import glob
    import cv2
    
    path = os.path.join(os.getcwd(), 'media', 'images')
    fname_video = os.path.join(os.getcwd(), 'media', 'video', 'go.avi')  # Save as AVI
    os.chdir(path)
    
    size = (1024, 768)
    fps = 20
    
    # Get the list of image files (only the first 10 images)
    files = [y for x in os.walk(path) for y in glob(os.path.join(x[0], '*.jpg'))][0:10]
    
    image_array = []
    for file in files:
        frame = cv2.imread(file, cv2.IMREAD_GRAYSCALE)  # Read image in grayscale
        frame = cv2.resize(frame, size)
        frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)  # Convert grayscale to 3-channel image
        image_array.append(frame)
    
    # Create a video writer object
    fourcc = cv2.VideoWriter_fourcc(*'XVID')  # Use XVID codec
    out = cv2.VideoWriter(fname_video, fourcc, fps, size, isColor=True)
    
    # Write frames to the video
    for i in range(len(image_array)):
        out.write(image_array[i])
    

    Edited Code:-

    import os
    import numpy as np
    from glob import glob
    import cv2
    
    path = os.path.join(os.getcwd(), 'media', 'images')
    fname_video = os.path.join(os.getcwd(), 'media', 'video', 'go.mp4')  # Ensure the file has a .mp4 extension
    os.chdir(path)
    
    size = (1024, 768)
    fps = 20
    
    # Get the list of image files (only the first 10 images)
    files = [y for x in os.walk(path) for y in glob(os.path.join(x[0], '*.jpg'))][0:10]
    
    image_array = []
    for file in files:
        frame = cv2.imread(file, cv2.IMREAD_GRAYSCALE)  # Read image in grayscale
        frame = cv2.resize(frame, size)
        frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)  # Convert grayscale to 3-channel image
        image_array.append(frame)
    
    # Create a video writer object
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = cv2.VideoWriter(fname_video, fourcc, fps, size, isColor=True)
    
    # Write frames to the video
    for i in range(len(image_array)):
        out.write(image_array[i])
    
    # Release the video writer
    out.release()
    
    print(f"Video saved to {fname_video}")