2025年3月29日 星期六 甲辰(龙)年 月廿八 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Python

制作抖音卡点视频?Python来帮你~

时间:10-11来源:作者:点击数:60
城东书院 www.cdsy.xyz

1、目 标 场 景

玩抖音的朋友都应该知道,最近「卡点视频」简直不要太火。抖音上很多大神也出了剪辑各种卡点视频的教程。

实际上,利用很多手机 APP 或者 PR、FCPX 软件也可以制作卡点视频,但是剪辑效率都太慢。如果想实现一篮子剪辑素材,通过运行一段代码,得到一个卡点视频,这种感觉不要太爽。

本篇文章的目的是利用 Python 从一篮子素材中快速地剪辑卡点小视频这一操作。

2、准 备 工 作

首先,对视频的剪辑需要用到「opencv」库,通过 pip3 安装到虚拟环境中。

  • # opencv 用于剪辑视频
  • pip3 install opencv-python

然而,通过 opencv 剪辑的视频只有画面,没有背景音乐。

我们需要借助「ffmpeg」,将抖音下载好的某个卡点视频利用 ffmpeg 命令分离出音频文件,然后合并到上面剪辑的视频当中。

  • # 分离BGM、合并视频和BGM
  • pip3 install ffmpeg

3、编 写 脚 本

我们以抖音上的某个卡点音乐为例,这段背景音乐的节奏需要一个 2s 的视频,然后其他都是静态图片,每个图片显示 0.5s。

图片

下面通过 5 个步骤完成卡点视频的剪辑,分别是:剪辑开始视频、合并静态图片视频、合并上面两段视频、给视频加入水印、加入背景音乐。

第一步,我们需要从视频素材文件中剪辑一段 2s 的片段。

通过 cv2 库为视频文件构建一个「VideoCapture」对象,然后获取到视频的帧率和视频的分辨率。

  • # 视频源
  • videoCapture = cv2.VideoCapture(soure_filename)
  • # 获取视频的帧率
  • fps = videoCapture.get(cv2.CAP_PROP_FPS)
  • # 获取视频的分辨率
  • img_size = (int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),
  •                 int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))

然后,利用上面的帧率、分辨率构建一个写入对象,即:「VideoWriter」。

  • # 构建一个视频写入对象
  • video_writer = cv2.VideoWriter(output_filename, cv2.VideoWriter_fourcc('X''V''I''D'), fps, img_size)

最后,通过传入要开始剪辑的起始点和要剪的长度,然后循环读取视频帧,如果满足条件,就写入到目标视频文件中。

写入视频帧完成之后,需要手动释放对象资源。

  • # 开始帧和结束帧
  • start_frame = fps * start_time
  • end_frame = start_frame + peroid * fps
  • # 循环读取视频帧,只写入开始帧和结束帧之间的帧数据
  • while True:
  •       success, frame = videoCapture.read()  
  •       if success:
  •             i += 1
  •             if start_frame <= i <= end_frame:
  •                 # 将截取到的画面写入“新视频”
  •                 video_writer.write(frame)
  •       else:
  •             break
  • # 释放资源
  • videoCapture.release()

第二步,需要把所有的静态文件都合成一段视频。

ps:为了保证每一张静态图片都显示 0.5s,并且静态图片生成的视频与第一段视频使用同一帧率,因此我们应该针对每一张图片写入多次,即多帧数据。每张图片写入的总次数为上段视频的帧率的 1/2。

和剪辑视频类似,静态图片合成视频也需要先构建一个写入对象VideoWriter,然后通过向上取整获取要写入的总帧数。

  • # 视频格式:MP4
  • fourcc = cv2.VideoWriter_fourcc('m''p''4''v')
  • # 构建写入对象
  • video = cv2.VideoWriter(output_video_path, fourcc, fps, img_size)
  • # 每一张图片要写入的帧数目
  • total_count = math.ceil(fps / 2)

另外需要注意的是,为了保证图片合成的视频能与第一段视频顺利剪辑在一起,这里需要对图片的分辨率进行缩放,没有像素的位置填充为黑色。

  • def resize_image(target_image_path, target_size):
  •     """
  •     调整图片大小,缺失的部分用黑色填充
  •     :param target_image_path: 图片路径
  •     :param target_size: 分辨率大小
  •     :return:
  •     """
  •     image = Image.open(target_image_path)
  •     iw, ih = image.size  # 原始图像的尺寸
  •     w, h = target_size  # 目标图像的尺寸
  •     scale = min(w / iw, h / ih)  # 转换的最小比例
  •     # 保证长或宽,至少一个符合目标图像的尺寸
  •     nw = int(iw * scale)
  •     nh = int(ih * scale)
  •     image = image.resize((nw, nh), Image.BICUBIC)  # 缩小图像
  •     # image.show()
  •     new_image = Image.new('RGB', target_size, (0000))  # 生成黑色图像
  •     # 将图像填充为中间图像,两侧为灰色的样式    
  •     new_image.paste(image, ((w - nw) // 2, (h - nh) // 2))  
  •     # 覆盖原图片
  •     new_image.save(target_image_path)

图片分辨率处理完成之后,最后就可以读取指定文件夹下的图片,按照上面获取的次数把静态图片写入到视频文件中。

  • # 使用opencv读取图像
  • frame = cv2.imread(image_path)
  • # 直接缩放到指定大小
  • frame_suitable = cv2.resize(frame, (img_size[0], img_size[1]), interpolation=cv2.INTER_CUBIC)
  • # 把图片写进视频
  • # 重复写入多少次
  • count = 0
  • while count < total_count:
  •        video.write(frame_suitable)
  •        count += 1

以上两步已经完成了两段单独视频的剪辑,第三步是「合成」上面的两段视频。

由于两段视频的帧率、分辨率都一致,这里不需要做其他多余的处理,只需要遍历两段视频文件,循环读取每一帧,然后写入到新的视频文件中。

第四步,需要对视频添加「水印」操作。

添加水印也很方便,利用 cv2 中的函数putText,指定水印的起始坐标、字体样式、字体大小和颜色,然后循环每一帧,写入到视频就可以实现。

  • ret, frame = cap.read()
  • while ret:
  •      # 文字在图中的坐标(注意:这里的坐标原点是图片左上角)
  •      x, y = img_size[0] - 200, img_size[1] - 50
  •      # 写入水印文字,文字颜色为白色
  •      cv2.putText(img=frame, text=mask_word,
  •                     org=(x, y), fontFace=cv2.FONT_HERSHEY_COMPLEX_SMALL,
  •                     fontScale=1, color=(255255255))
  •      video_writer.write(frame)
  •      ret, frame = cap.read()
  • # 删除源文件,并重命名临时文件
  • os.remove(video_path)
  • os.rename(video_temp_path, video_path)
  • print('水印添加完成~')
  • video_writer.release()
  • cap.release()

最后一步就是合成视频和背景音乐,重新生成一段视频文件。

利用视频的帧率与总帧数得到视频的总时长,然后利用 ffmpeg 命令对背景音乐做一次裁剪操作,使得视频的长度与背景音乐的时间长度一致。

  • #获取视频的长度
  • 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))

接着使用 ffmpeg 命令,合并视频文件和音频文件,就可以生成一个我们需要的卡点视频。

  • #视频、音频合二为一
  • # 临时文件
  • video_temp_path = get_temp_path(video_path, 'temp')
  • os.system('ffmpeg -i %s  -i %s  -vcodec copy -acodec copy %s' % (video_path, bgm_path, video_temp_path))
  • # 删除源文件,重命令临时文件
  • os.remove(video_path)
  • os.rename(video_temp_path, video_path)

4、结 果 结 论

运行程序后,视频、图片、背景音乐会自动进行剪辑、合成,最后加上水印,在本地生成一个卡点视频。

下面是我利用 Python 在一篮子素材中生成的一个卡点视频。

已经将全部源码上传到github:https://github.com/xingag/tools_python/tree/master/video_auto/%E5%8D%A1%E7%82%B9%E8%A7%86%E9%A2%91。

另外,如果文中的视频、图片素材:链接:https://pan.baidu.com/s/1dXZRYIIsWL1cD8p7N-4cbQ  密码:nzhv。

城东书院 www.cdsy.xyz
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐