0
点赞
收藏
分享

微信扫一扫

用tim从左到右移动帧(感兴趣区域)的Moviepy裁剪视频


我正在使用MoviePy从服务器上的视频剪辑自动创建GIF。图书馆帮助进行各种各样的视频转换和剪辑,以创建gif。在

在我当前的项目中,我有一个视频剪辑,里面有很多移动的物体,很难对感兴趣的区域进行自动跟踪。 (下面一个快速的gif显示了场景,虽然那里的背景可以很容易地消除和做目标的跟踪。但假设跟踪对象超出了项目的范围)。

如下面的gif所示,红色矩形是随时间从左向右移动的感兴趣区域。 我想裁剪这个区域并创建一个GIF。在

​​[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gRPHLtCX-1640780015513)(https://i.stack.imgur.com/rGfeK.gif)]​​

我用的是MoviePy,我从一个视频剪辑了一个矩形来创建一个gif。但矩形被固定在其原始坐标位置。我正在寻找一种方法,移动矩形随着时间和裁剪它创建一个GIF。在

clip = (VideoFileClip("my_video.mp4")
.subclip((1,10.1),(1,14.9))
.resize(0.5)
.crop(x1=145,y1=110,x2=400,y2=810))

clip.write_gif("my_gif.gif")

如何添加时间因子,使坐标随时间变化。在

欢迎提出任何建议。在

您正在moviepy中查找​​scroll​​​函数。它缺少文档,但是它们是​​here​​,以及源代码{a2}。在

moviepy.video.fx.all.scroll(clip, h=None, w=None, x_speed=0, y_speed=0, x_start=0, y_start=0, apply_to='mask')

参数:

  • ​clip​​;要作用的剪辑
  • ​h​​和{},它们决定最终剪辑的高度和宽度
  • ​x_speed​​和{},它们决定滚动的速度。不确定这些是用什么度量的,所以您可能需要调查源代码,或者只是尝试并出错。
  • ​x_start​​和{}这是它开始滚动的距离(0,0)。
  • ​apply_to​​;如果要使用掩码,则不需要它!

最终代码:

clip = (VideoFileClip("my_video.mp4")
.subclip((1,10.1),(1,14.9))
.resize(0.5)
.crop(x1=145,y1=110,x2=400,y2=810))

# You won't need to set `w` and `h` if you are separately cropping it
new_clip = vfx.scroll(clip, w=clip.w, h=var, x_speed=speed, y_start=height_to_top_of_wanted_bit)
new_clip.set_duration(1.0 / speed)

clip.write_gif("my_gif.gif")

注意,此代码未经测试。在

# -*- coding: utf-8 -*-

import cv2
import numpy as np
import time
import os
import math
from common.libs.utils.file_utils import *
from common.libs.utils.image_utils import *
from PIL import Image
from moviepy.editor import *
import moviepy.video.fx.all as vfx

# 最后影片的分辨率片,根据视频来设置,默认是1920*1080
img_size = (int(1920), int(1080))

def cut_film(soure_filename, output_filename, start_time, peroid):
"""
裁剪视频
:param start_time: 开始时间【s】
:param peroid: 持续时间【s】
:param soure_filename 源视频
:param output_filename 输出视频
:return:
"""
global img_size

# 数据源
videoCapture = cv2.VideoCapture(soure_filename)

if videoCapture.isOpened():
print('open success')
else:
print('open fail')

fps = videoCapture.get(cv2.CAP_PROP_FPS)

# 获取大小(1920*1080)
img_size = (int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),
int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))

video_writer = cv2.VideoWriter(output_filename, cv2.VideoWriter_fourcc('X', 'V', 'I', 'D'), fps, img_size)

i = 0

# 开始帧和结束帧
start_frame = fps * start_time
end_frame = start_frame + peroid * fps

print(type(start_frame))
print('即将裁剪的开始帧为:%f,结束帧为:%f' % (start_frame, end_frame))

while True:
success, frame = videoCapture.read() # 循环读取下一帧

if success:
i += 1
if start_frame <= i <= end_frame:
# 将截取到的画面写入“新视频”
video_writer.write(frame)
else:
print('end')
break

videoCapture.release()

return fps


def compound_film(film_names, video_output_path):
"""
合并视频
:param film_names:
:return:
"""
print('一共要合成%d段视频' % len(film_names))
print(film_names)

# 通过第一个视频,获取帧率、宽、高
videoCaptureNorm = cv2.VideoCapture(film_names[0])

# 帧率、宽、高
fps = videoCaptureNorm.get(cv2.CAP_PROP_FPS)
width = (int(videoCaptureNorm.get(cv2.CAP_PROP_FRAME_WIDTH)))
height = (int(videoCaptureNorm.get(cv2.CAP_PROP_FRAME_HEIGHT)))

# =====================================================================
# 待写入对象,写入到result.mp4文件中
videoWriter = cv2.VideoWriter(video_output_path, cv2.VideoWriter_fourcc('m', 'p', '4', 'v'), fps, (width, height))

for index, film_name in enumerate(film_names):
print('视频名称:%s' % film_name)
videoCapture = cv2.VideoCapture(film_name)

# 循环写入数据
while True:
success, frame = videoCapture.read()

# 视频必须保证分辨率一致,才能合并
# frame_suitable = cv2.resizeWindow(frame, (width, height), interpolation=cv2.INTER_CUBIC)
videoWriter.write(frame)
if success:
continue
else:
break

videoCapture.release()
print('第%d个视频合成完成~' % (index + 1))

videoWriter.release()
videoCaptureNorm.release()

def compound_pic_special(images_path, output_video_path, fps, total_second):
"""
图片合成视频【卡点视频】
:param path: 图片文件路径
:param output_video_path:合成视频的路径
:param size:
:return:
"""

# 获取该目录下的所有文件名
file_list = os.listdir(images_path)
file_list = sort_strings_with_emb_numbers(file_list)

print('一共有%d张图片' % len(file_list))

fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')

video = cv2.VideoWriter(output_video_path, fourcc, fps, img_size)

percentSecond = total_second/(len(file_list))
total_count = math.ceil(fps*percentSecond)
print('每张图片都需要重复写入%d帧' % total_count)

for i,item in enumerate(file_list):
if item.endswith('.jpg'): # 判断图片后缀是否是.jpg
image_path = images_path + item

# 缩放图片到合适的分辨率,并覆盖源文件
resize_image(image_path, img_size, image_path)



count = 0
while count < total_count:
temp_tuple_size = (int(1920 + 0.1 * count), int(1080 + 0.1 * count))
frame = cv2.imread(image_path)
# 直接缩放到指定大小
frame_suitable = cv2.resize(frame, (temp_tuple_size[0], temp_tuple_size[1]), interpolation=cv2.INTER_CUBIC)
video.write(frame_suitable)
count += 1
else:
print('名称为:%s,文件格式不对,过滤掉~' % item)
# 释放资源
video.release()

def compound_bgm(video_path, bgm_path, video_output_path):
"""
通过视频、BGM 合成一段视频
:param video_path: 视频路径
:param bgm_path: BGM路径
:return:
"""
# $ ffmpeg -i 2_003_014.mp4 -vn -y -acodec copy 3.aac
# 1.提前temp.mp4这个视频的BGM,文件结果为:temp.aac
# os.system('ffmpeg -i temp.mp4 -vn -y -acodec copy temp.aac')

# 2.获取视频的长度
cap = cv2.VideoCapture(video_path)
# 帧率
fps = cap.get(cv2.CAP_PROP_FPS)
# 总帧数
frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
# 总时长-秒,这里做取整操作 【浮点类型】
time_count = math.floor(frame_count / fps)

print('帧率:%f,总帧数:%d' % (fps, frame_count))
print(time_count)

# 3.截取音频
# 为了简单,这里一般不会超过一分钟
#bgm_temp_path = get_temp_path(bgm_path, 'temp_new')
#os.system('ffmpeg -i %s -ss 00:00:00 -t 00:00:%d -acodec copy %s' % (bgm_path, time_count, bgm_temp_path))

# 3.1 删除源音频并重命令当前文件
#os.remove(bgm_path)
#os.rename(bgm_temp_path, bgm_path)

# 4.视频、音频合二为一
#video_output_path = get_temp_path(video_path, 'output')
if os.path.exists(video_output_path):
os.remove(video_output_path)
os.system('ffmpeg -i %s -i %s -vcodec copy -acodec copy %s' % (video_path, bgm_path, video_output_path))


print('音视频合成完成~')

def make_sticke_point_video(source_film_path, source_image_path, source_bgm_path,oupputMp4Path, video_output_path):
"""
制作卡点视频
:return:
"""

# 1.从一段视频中剪辑前2s的视频
# 也可以指定开始帧和持续时间
# 生成的第一段视频2s
template_video_time = 2
video_part1 = oupputMp4Path + 'part1.mp4'
fps = cut_film(source_film_path, video_part1, 0, template_video_time)
print('第一段视频剪辑完成~')
print('第一段视频的帧率是:%f' % fps)



# 2.把所有图片合成一个视频
# #获取语音时长
audioclip = AudioFileClip(source_bgm_path)
audio_time = audioclip.duration
video_part2 = oupputMp4Path + 'part2.mp4'
compound_pic_special(source_image_path, video_part2, fps, audio_time)
print('第二段视频合成完成~')

# 3.加入背景音乐
compound_bgm(video_part2, source_bgm_path, video_output_path)


#transitions_animation('C:\\tmp\\NbaNew\\20211229\\result\\2626507b8820ddea8b308ba091335e51\\outputMp4\\part1.mp4','C:\\tmp\\NbaNew\\20211229\\result\\2626507b8820ddea8b308ba091335e51\\outputMp4\\part2.mp4','C:\\tmp\\NbaNew\\20211229\\result\\2626507b8820ddea8b308ba091335e51\\outputMp4\\part3.mp4')
def transitions_animation(path_video1, path_video2, output_path):
"""
两段视频中转场动画(以淡入淡出为例)
注意:保证视频拍摄帧率一致
:param video1:
:param video2:
:return:
"""
# 获取视频时长
clip_video1 = VideoFileClip(path_video1)
duration_video1 = clip_video1.duration

clip_video2 = VideoFileClip(path_video2)
duration_video2 = clip_video2.duration

print(f'两段视频的时长分别为:{duration_video1},{duration_video2}')

# 统一视频分辨率
w, h, fps = clip_video1.w, clip_video1.h, clip_video1.fps
clip_video2_new = clip_video2.resize((w, h))

# 转场时长,默认2s
transitions_time = 2

# 第一段视频执行淡出效果
subVideo1_part1 = clip_video1.subclip(0, duration_video1 - 1)
subVideo1_part2 = clip_video1.subclip(duration_video1 - 1).fadeout(1, (1, 1, 1))

# 第二段视频执行淡入效果
subVideo2_part1 = clip_video2_new.subclip(0, 1).fadein(1, (1, 1, 1))
subVideo2_part2 = clip_video2_new.subclip(1)

# 合并4段视频
result_video = concatenate_videoclips([subVideo1_part1, subVideo1_part2, subVideo2_part1, subVideo2_part2])

# pass 写入视频文件
result_video.write_videofile(output_path)

def resize_animation(path_video1, output_path):
"""
两段视频中转场动画(以淡入淡出为例)
注意:保证视频拍摄帧率一致
:param video1:
:param video2:
:return:
"""
# 获取视频时长
clip1 = VideoFileClip(path_video1).crop(0, 0, 540, 660)
duration_video1 = clip1.duration


# 第一段视频执行淡出效果
#subVideo1_part1 = clip_video1.subclip(0, duration_video1).resize(lambda t : 1+0.0001*t)

# 合并4段视频
#result_video = concatenate_videoclips([subVideo1_part1, subVideo1_part2, subVideo2_part1, subVideo2_part2])


#newclip = clip1.fx(vfx.mask_and, clip1)
# preview(newclip)
clip1.write_videofile(output_path)


举报

相关推荐

0 条评论