基于帧数分割多段视频为短视频的技术方案咨询
基于帧号切割视频的实现方案
需求背景
原本通过秒数切割视频(如0-10秒、10-20秒),但因秒数计数存在误差,需改为按帧号切割(如0-250帧、250-500帧)。原基于秒数切割的代码如下:
required_video_file = "H8.avi" with open("Z:/temp/Letícia/Videos/teste/times.txt") as f: times = f.readlines() times = [x.strip() for x in times] for time in times: starttime = int(time.split('-')[0]) endtime = int(time.split("-")[1]) ffmpeg_extract_subclip(required_video_file, starttime, endtime, targetname=str(times.index(time)+1)+".avi")
实现思路
核心是利用FFmpeg的帧级控制能力,以下两种方案均可行:
方案1:帧号转精确时间(适配原有代码逻辑)
ffmpeg_extract_subclip基于时间参数切割,我们可以先获取视频帧率(FPS),将帧号转换为精确的时间值(时间 = 帧号 / FPS),再传入原函数完成切割,无需大幅改动原有代码结构。
修改后的代码示例:
from moviepy.editor import VideoFileClip, ffmpeg_extract_subclip required_video_file = "H8.avi" # 获取视频帧率 with VideoFileClip(required_video_file) as clip: fps = clip.fps # 读取帧号区间文件(需将原times.txt改为帧号格式,如每行"0-250") with open("Z:/temp/Letícia/Videos/teste/frames.txt") as f: frame_ranges = f.readlines() frame_ranges = [x.strip() for x in frame_ranges if x.strip()] for idx, frame_range in enumerate(frame_ranges): start_frame, end_frame = map(int, frame_range.split('-')) # 帧号转精确时间 start_time = start_frame / fps end_time = end_frame / fps # 执行切割 target_name = f"{idx+1}.avi" ffmpeg_extract_subclip(required_video_file, start_time, end_time, targetname=target_name)
方案2:直接调用FFmpeg命令按帧切割(更精准)
跳过时间转换环节,直接使用FFmpeg原生的-start_frame(起始帧)和-vframes(截取帧数)参数实现帧级切割,彻底避免时间转换带来的潜在误差。
修改后的代码示例:
import subprocess required_video_file = "H8.avi" # 读取帧号区间文件 with open("Z:/temp/Letícia/Videos/teste/frames.txt") as f: frame_ranges = f.readlines() frame_ranges = [x.strip() for x in frame_ranges if x.strip()] for idx, frame_range in enumerate(frame_ranges): start_frame, end_frame = map(int, frame_range.split('-')) # 计算需要截取的帧数:结束帧 - 起始帧 frame_count = end_frame - start_frame target_name = f"{idx+1}.avi" # 构造FFmpeg命令 cmd = [ "ffmpeg", "-i", required_video_file, "-start_frame", str(start_frame), "-vframes", str(frame_count), "-c:v", "copy", # 直接复制视频流,无重新编码,速度极快 "-c:a", "copy", # 直接复制音频流(无需音频可删除此行) target_name ] # 执行命令 subprocess.run(cmd, check=True)
注意事项
- 确保
frames.txt每行格式为起始帧-结束帧(如0-250),帧号为非负整数; - 方案2中
-c:v copy和-c:a copy参数仅适用于支持帧级截断的编码格式,若切割后视频无法播放,可删除这两个参数让FFmpeg重新编码; - 多数视频帧号从0开始计数,需确认原视频的帧计数规则,避免切割偏差。
内容的提问来源于stack exchange,提问作者LEstvs
相关产品推荐
相关产品推荐

