OpenCV中如何制作开头慢结尾快的可变FPS视频?
解决OpenCV合成变速视频的问题
因为cv2.VideoWriter实例化后确实无法修改FPS,要实现开头慢、结尾快的变速效果,核心思路是通过控制单帧的写入次数来模拟不同播放速度——视频整体使用一个固定的基础FPS(建议设为你需要的最高FPS),慢放段的帧重复写入多次,快放段的帧正常写入(或减少重复)。
具体实现逻辑
- 设定基础FPS:选你需求中的最高FPS作为视频的固定帧率,确保能覆盖所有变速场景。
- 划分变速区间:明确哪些帧是慢放段、哪些是快放段。
- 计算帧重复次数:重复次数 = 基础FPS / 目标段FPS。比如基础FPS设为50,慢放段目标10FPS,那每帧需要重复写入5次,以此模拟慢放效果。
修改后的完整代码
import numpy as np import cv2, os import matplotlib image_size = 200 def create_image_array(image_size): image_array = np.random.randn(image_size, image_size) row = np.random.randint(0, image_size) image_array[row, :] = 100 return image_array # 生成测试帧 frame_numbers = 200 os.makedirs('./shots', exist_ok=True) # 确保存储文件夹存在 for i in range(frame_numbers): image_array = create_image_array(image_size) matplotlib.image.imsave(f'./shots/frame_{i:03d}.png', image_array) def make_variable_speed_video(shots_folder, video_path): shots_folder = 'shots' base_fps = 50 # 基础FPS,设为需求中的最高帧率 images = [img for img in os.listdir(shots_folder) if img.endswith(".png")] images = sorted(images) # 获取帧尺寸信息 frame = cv2.imread(os.path.join(shots_folder, images[0])) height, width, layers = frame.shape # 初始化VideoWriter,使用固定基础FPS video = cv2.VideoWriter(video_path, cv2.VideoWriter_fourcc(*'mp4v'), base_fps, (width, height)) # 划分变速区间:前100帧慢放,后100帧快放 slow_frames = images[:100] fast_frames = images[100:] # 慢放段处理:每帧重复写入对应次数 slow_target_fps = 10 repeat_times_slow = int(base_fps / slow_target_fps) for img_name in slow_frames: frame = cv2.imread(os.path.join(shots_folder, img_name)) for _ in range(repeat_times_slow): video.write(frame) # 快放段处理:每帧写入1次(与基础FPS一致) for img_name in fast_frames: frame = cv2.imread(os.path.join(shots_folder, img_name)) video.write(frame) video.release() cv2.destroyAllWindows() shots_folder = 'shots' video_path = 'variable_speed_video.mp4' make_variable_speed_video(shots_folder, video_path)
扩展说明
- 如果需要平滑渐变的变速效果(比如从慢到快逐渐过渡),可以让重复次数随帧索引线性变化,比如从5次逐步降到1次。
- 也可以分阶段生成不同FPS的视频片段再拼接,但这种方式需要处理视频拼接的细节,复杂度更高,不如控制帧重复次数直接高效。
内容的提问来源于stack exchange,提问作者Saeed
相关产品推荐
相关产品推荐

