Python如何给视频添加滤镜且保证输出视频与原视频时长一致
解决思路
你猜测的方向是对的,核心问题出在输出参数和帧处理逻辑的问题上,具体可按以下步骤修正:
- 替换硬编码的输出帧率,匹配原视频实际帧率
视频时长 = 总帧数 ÷ 帧率,你直接写死输出帧率为30,如果原视频帧率不是30,相同帧数下时长必然不一致。你可以用cap.get(cv2.CAP_PROP_FPS)直接读取原视频的真实帧率,传给VideoWriter的第三个参数即可。 - 补全帧读取校验和写入逻辑,避免丢帧
你现有代码的循环里没有判断读取帧是否成功的ret返回值,也没有把处理后的帧写入输出视频,再加上cv2.waitKey的中断逻辑可能被误触发,很容易出现实际写入的帧数比原视频总帧数少的情况,导致时长变短。 - 增加帧数校验环节
读取原视频总帧数cap.get(cv2.CAP_PROP_FRAME_COUNT),处理完成后对比实际写入的帧数,确认两者完全一致即可排除帧丢失问题。
修正后可直接运行的代码
import cv2 import numpy as np from PIL import Image, ImageOps, ImageEnhance, ImageChops cap = cv2.VideoCapture('fish.mp4') # 读取原视频的参数,全部沿用原参数避免不匹配 frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fps = cap.get(cv2.CAP_PROP_FPS) total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) size = (frame_width, frame_height) # 输出帧率用原视频的fps,不要硬写30 result = cv2.VideoWriter('end.avi', cv2.VideoWriter_fourcc(*'MJPG'), fps, size) # 统计实际写入的帧数,可选用于校验 write_count = 0 while cap.isOpened(): ret, frame = cap.read() # 读到视频末尾直接跳出 if not ret: break # 帧编辑部分写在这里 # 示例:把帧转成灰度 # frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR) # 单通道转三通道才能正常写入 # 写入处理后的帧,不能漏 result.write(frame) write_count += 1 # 如果不需要实时预览可以删掉下面这行,避免误触q提前中断 # if cv2.waitKey(1) & 0xFF == ord('q'): # break # 校验帧数 print(f"原视频总帧数:{total_frames},实际写入帧数:{write_count}") if total_frames == write_count: print("帧数一致,时长不会出现偏差") else: print("存在丢帧,请检查处理逻辑") cap.release() result.release() # 不要漏释放VideoWriter cv2.destroyAllWindows()
额外注意事项
- 如果输出需要保留原视频音频,OpenCV本身不处理音频轨道,你可以用ffmpeg工具把原视频的音频合并到输出视频中,该操作不影响视频轨道的时长。
- 如果需要输出MP4格式,把fourcc改成
cv2.VideoWriter_fourcc(*'mp4v'),文件后缀改成.mp4即可,只要帧率和帧数匹配就不会影响时长。
内容的提问来源于stack exchange,提问作者gasper101
相关产品推荐
相关产品推荐

