python中使用ffmpeg进行视频指定时长截断(解决剪切后音视频不同步的问题)

1. 获取视频时长

有两种方式获取视频总时长:

  1. python-ffmpeg( 获取的是视频总秒数 )
    video_time = float(ffmpeg.probe(video)['format']['duration'])
  2. opencv( 帧速率 / 视频总帧数 = 时间 )
    cap = cv2.VideoCapture(video)
    video_time = float(cap.get(7) / cap.get(5))

2. 根据传入的截取时间进行截断

例如:起始部分5s内容舍去,结尾部分10s内容舍去

  1. ffmpeg中截取视频可以根据指定开始时间,结束时间精确截取视频片段
    ffmpeg -i video.mp4 -vcodec copy -acodec copy -ss start_time -to end_time out.mp4
  2. 使用上一条指令可以指定起始结束时间进行截断视频,但是在截断后会出现音视频不同步的问题。
    因此采用重新编码的方式进行截断视频,但是损失的是时间,重新编码耗时明显过多
    ffmpeg -ss start_time -t duration_time -i video.mp4 -c:v libx264 -c:a aac -strict experimental -b:a 98k out.mp4 -y
  • start_time指开始时间, duration_time指持续时间(不是结束时间)
  • 将-ss -t 参数放在 -i 参数之前,会对输入文件执行seek操作,会seek到-ss设置的时间点前面的关键帧(时间不精确)
  • -vcodec copy指直接按视频原编码格式进行复制,-c:v libx264指按h264格式编码视频
  • -acodec copy指直接按音频原编码格式进行复制,-c:a aac指按aac格式进行音频编码
  • 还可以添加-accurate_seek使时间更精准,-avoid_negative_ts 1 寻找结尾时关键帧进行补全
// 通过传入秒数返回标准时间格式
def get_time(self, second):
     m, s = divmod(int(second), 60)
     h, m = divmod(m, 60)
     return datetime.datetime.strptime(str("%d:%02d:%02d" % (h, m, s)), '%H:%M:%S')
     
// 开始处理视频
def deal_video(self, video_path, start_time, end_time)
	// 获取视频总时长
	video_time = float(ffmpeg.probe(video_path)['format']['duration'])
	video_detail_time = self.get_time(video_time)
	// 判断传入的时间是否有问题(开始结束时长不能大于总时长)
	if int(start_time) + int(end_time) > int(video_time):
	    # 循环处理每个视频
	    self.fail_list.append(video)
	    continue
    else:
    	// 获取截断起始时间(只保留时分秒)
        cut_start_time = str(self.get_time(start_time)).split(" ")[1]
        cut_end_time = str(video_detail_time - datetime.timedelta(seconds=int(end_time))).split(" ")[1]
        // 获取视频名称
        videos = video.split("\\")
        video_out_path = save_video_path + "\\" + videos[len(videos) - 1]
        self.cut_video(video, video_out_path, cut_start_time, cut_end_time)

// 开始使用ffmpeg进行视频截断操作
def cut_video(self, video_path, out_video_path, start_time, end_time):
	try:
	    text = 'ffmpeg -ss \"%s\" -t \"%s\" -i \"%s\"  -c:v libx264 -c:a aac -strict experimental -b:a 98k \"%s\" -y' % (
                start_time, end_time, video_path, out_video_path)
	    res = os.system(text)
	    if res != 0:
	        self.fail_list.append(video_path)
	        logger.error('ffmpeg截断单个视频失败! 视频路径:' + str(video_path))
	        return False
	    logger.info('ffmpeg截断单个视频成功! 视频路径:' + str(video_path))
	    return True
	except Exception as e:
	    logger.error('ffmpeg截断单个视频出现异常! 视频路径:' + str(video_path) + ";异常原因:" + str(e))
	    self.fail_list.append(video_path)
	    return False
原创文章 4 获赞 6 访问量 1550

猜你喜欢

转载自blog.csdn.net/weixin_45475063/article/details/101440793