You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV裁剪视频保存为MP4仅1KB?求代码排查与解决方案

问题排查与解决方法

核心错误点

  • 帧率参数错误:创建VideoWriter时误将视频总帧数(CAP_PROP_FRAME_COUNT)当作帧率传入,正确参数应为视频实际帧率(CAP_PROP_FPS)。
  • 帧尺寸顺序颠倒:OpenCV要求VideoWriter的尺寸格式为(宽度, 高度),但代码中传入的是(高度, 宽度)(first_frame_roi.shape[0]对应高度,shape[1]对应宽度)。
  • 首帧丢失:初始化阶段已读取第一帧,但后续循环未将该帧写入输出文件,导致视频开头缺帧。

修复后的完整代码

import numpy as np
import cv2
import matplotlib.pyplot as plt


ORIGINAL_WINDOW_TITLE = 'Original'
FIRST_FRAME_WINDOW_TITLE = 'First Frame'
DIFFERENCE_WINDOW_TITLE = 'Difference'


canvas = None
drawing = False # true if mouse is pressed

#Retrieve first frame
def initialize_camera(cap):
    _, frame = cap.read()
    return frame


# mouse callback function
def mouse_draw_rect(event,x,y,flags, params):
    global drawing, canvas

    if drawing:
        canvas = params[0].copy()

    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        params.append((x,y)) #Save first point

    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing:
            cv2.rectangle(canvas, params[1],(x,y),(0,255,0),2)

    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        params.append((x,y)) #Save second point
        cv2.rectangle(canvas,params[1],params[2],(0,255,0),2)


def select_roi(frame):
    global canvas

    #here, it is the copy of the first frame. 
    canvas = frame.copy()
    params = [frame]
    
    ROI_SELECTION_WINDOW = 'Select ROI'
    cv2.namedWindow(ROI_SELECTION_WINDOW)
    
    cv2.setMouseCallback(ROI_SELECTION_WINDOW, mouse_draw_rect, params)
    roi_selected = False
    while True:
        cv2.imshow(ROI_SELECTION_WINDOW, canvas)
        key = cv2.waitKey(10)

        #Press Enter to break the loop
        if key == 13:
            break;


    cv2.destroyWindow(ROI_SELECTION_WINDOW)
    roi_selected = (3 == len(params))
    print(len(params))

    if roi_selected:
        p1 = params[1]
        p2 = params[2]
        if (p1[0] == p2[0]) and (p1[1] == p2[1]):
            roi_selected = False

    #Use whole frame if ROI has not been selected
    if not roi_selected:
        print('ROI Not Selected. Using Full Frame')
        p1 = (0,0)
        p2 = (frame.shape[1] - 1, frame.shape[0] -1)


    return roi_selected, p1, p2




if __name__ == '__main__':

    cap = cv2.VideoCapture(r'E:\cardiovascular\brad1low.mp4')

    #Grab first frame
    first_frame = initialize_camera(cap)

    #Select ROI for processing. Hit Enter after drawing the rectangle to finalize selection
    roi_selected, point1, point2 = select_roi(first_frame)    

    #Grab ROI of first frame
    first_frame_roi = first_frame[point1[1]:point2[1], point1[0]:point2[0]]
    print(f'first frame roi is {first_frame_roi}')

    # 获取视频实际帧率
    fps = cap.get(cv2.CAP_PROP_FPS)
    # 修正尺寸顺序:(宽度, 高度)
    roi_width = first_frame_roi.shape[1]
    roi_height = first_frame_roi.shape[0]
    # 使用兼容性更好的AVC1编码
    out = cv2.VideoWriter(r'E:\cardiovascular\filename2.mp4', cv2.VideoWriter_fourcc(*'AVC1'), fps, (roi_width, roi_height))

    # 写入首帧的ROI内容
    out.write(first_frame_roi)

    while cap.isOpened():

        ret, frame = cap.read()


        if ret:

            #ROI of current frame
            roi = frame[point1[1]:point2[1], point1[0]:point2[0]]
            print(f'roi is {roi}')

            cv2.imshow(DIFFERENCE_WINDOW_TITLE, roi)
            out.write(roi)
            
            key = cv2.waitKey(30) & 0xff
            if key == 27:
                break
        else:
            break

    cap.release()
    out.release()
    cv2.destroyAllWindows()

额外说明

  • 若AVC1编码仍无法生成有效视频,可尝试替换为XVID(需将输出文件后缀改为.avi)或MP4V,不同系统对编码的支持存在差异。
  • 确保输出路径具备写入权限,避免因权限问题导致文件写入失败。

内容的提问来源于stack exchange,提问作者Vijith Kumar V

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 09:35:22