做剪辑时我们需要的素材通常是一段一段的画面,但是从网上找到的素材往往包含许多段画面,想要剪出每段画面,一般的解决方案就是使用剪辑软件,手动找到画面切换的地方,剪开然后保存,这里我尝试一种新的方案:使用Python中ImageHash和moviepy实现自动化剪辑,可以适用于批量生产素材。
首先需要安装Python库
pip install ImageHash pip install moviepy pip install opencv-python视频中画面切换时,前后两帧的图像变化一般会很大,因此我们需要一个函数来判断视频中相邻的前后帧相似度:
def isSimilar(img1, img2): # OpenCV图片转换为PIL image img1 = Image.fromarray(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)) img2 = Image.fromarray(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)) # 通过imagehash获取两个图片的平均hash值 n0 = imagehash.average_hash(img1) n1 = imagehash.average_hash(img2) # hash值最小相差多少则判断为不相似,可以根据需要自定义 cutoff = 7 print(f'目标帧hash平均值:{n0}') print(f'后帧hash平均值: {n1}') print(f'hash差值: {n0-n1}') flag = True if n0 - n1 < cutoff: print('相似') else: flag = False print('不相似') return flag判断帧相似度的函数有了,我们还需要一个函数遍历视频中的所有帧,并使用上面的函数判断前后帧是否相似:
def sliceVideo(clip, fps): im0 = "" # 目标帧 start_time = 0 # 片段开始时间 end_time = 0 # 片段结束时间 success_durations = [] # 成功片段时间列表 skip_durations = [] # 排除片段时间列表 for i,img in enumerate(clip.iter_frames(fps)): if i == 0: im0 = img time = (i) / fps print(f'\n第{time}秒') result = isSimilar(im0, img) if not result: # 结果为不相似 end_time = (i-1) / fps print(start_time, end_time) if start_time == end_time: # 排除情况,开始时间和结束时间相同的话moviepy会报错;也可以根据需要筛选时长大于多少的片段 skip_durations.append([start_time, end_time]) else: clip.subclip(start_time, end_time).write_videofile(f"SUBCLIP-{i}.mp4") success_durations.append([start_time, end_time]) start_time = time im0 = img # 前面的循环并没有包括视频中最后一段画面,因此需要在最后加上 end_time = clip.duration if start_time == end_time: skip_durations.append([start_time, end_time]) else: clip.subclip(start_time, end_time).write_videofile(f"SUBCLIP-{i}.mp4") success_durations.append([start_time, end_time]) return [success_durations, skip_durations]参考文章: https://blog.csdn.net/enter89/article/details/90293971 https://zhuanlan.zhihu.com/p/161530919