python 合并加速mp4文件(含对文件、目录的处理)

最近家里买了一些花,正好到了开花的季节,突然想到,我们自己能不能把开花过程留下来?并以快进的模式展现出来?

说干就干,设备很简单,就是用了几年前从小米买的小白摄像头(记得好像是不到300),当然电脑还是少不了。
小白录像的内容留在TF卡中,读出来后发现里面有两个目录:msc 和 XiaoBaiCam,msc中是空目录,XiaoBaiCam中则按每小时一个文件夹,每个文件夹中每10秒一个mp4文件,有360个MP4文件,如下所示。

python 合并加速mp4文件(含对文件、目录的处理)_第1张图片
影像处理软件自然是可以来做,但文件数量众多,自然需要一些工具,好在python很给力。

思路也很简单,把每个小时的视频文件自动合成一个大的MP4文件,然后进行快进处理即可。
一是使用文件处理功能,写代码处理文件、处理目录是最基本的需求之一,好在python的OS包对此有很简便的办法。
二是需要视频处理功能,python的moviepy这个包可以满足要求,不过这个包需要下载安装(推荐国内镜像)

pip install -i https://mirrors.aliyun.com/pypi/simple moviepy

一、基本的文件处理函数

假设 当前目录是 “D:\python\xiaobaicam” 存在文件 20221103.MP4 , 另外虚拟一个不存在的文件 xxx.MP4

函数 说明 示例
os.path.abspath(r“.”) 返回绝对路径 “d:\python\xiaobaicam”
os.path.basename(r“D:\python\xiaobaicam\20221103.mp4”) 返回文件名 “20221103.mp4”
os.path.dirname(r“D:\python\xiaobaicam\20221103.mp4”) 返回文件路径 “D:\python\xiaobaicam”
os.path.exists(r“D:\python\xiaobaicam\20221103.mp4”) 如果路径 path 存在,返回 True;如果路径 path 不存在,返回 False。 返回False
os.path.lexists(r"d:\python\xxx.MP4") 路径存在则返回True,路径损坏也返回True False
os.path.getsize(r“D:\python\xiaobaicam\20221103.mp4”) 返回文件大小,如果文件不存在就返回错误;使用前先用exists函数判断是否存在 返回文件大小901306
os.path.isabs(r“D:\python\xiaobaicam\20221103.mp4”) 判断是否为绝对路径 返回True
os.path.isfile(r“D:\python\xiaobaicam\20221103.mp4”) 判断路径是否为文件 返回True
os.path.isdir(r“D:\python\xiaobaicam”) 判断路径是否为目录 返回True
os.path.join(r“D:\python\xiaobaicam”, r“20221103.mp4”) 把目录和文件名合成一个路径 返回“D:\python\xiaobaicam\20221103.mp4”
os.path.realpath(r“D:\python\xiaobaicam\20221103.mp4”) 返回path的真实路径 这里文件不一定需要真实存在,会把相对路径变为绝对路径
os.path.split(r“D:\python\xiaobaicam\20221103.mp4”) 把路径分割成 dirname 和 basename,返回一个元组 (“D:\python\xiaobaicam“,“20221103.mp4”)一般用于取文件名
os.path.splitext(r“D:\python\xiaobaicam\20221103.mp4”) 分割路径,返回路径名和文件扩展名的元组 (“D:\python\xiaobaicam\20221103“,”.mp4”)一般用于取文件后缀
os.path.splitdrive(r“D:\python\xiaobaicam\20221103.mp4”) 一般用在 windows 下,返回驱动器名和路径组成的元组 (“D:“,”\python\xiaobaicam\20221103.mp4”)
os.path.walk(path, visit, arg) 遍历path,进入每个目录都调用visit函数,visit函数必须有3个参数(arg, dirname, names),dirname表示当前目录的目录名,names代表当前目录下的所有文件名,args则为walk的第三个参数 这个函数在遍历是特别有用,可以见示例

二、遍历目录和数据转换

现在就需要把目录下所有的MP4文件取出来,这个就需要用到 os.walk() 函数
这个函数最简单的用法是把返回的目录和文件取出来,循环操作即可。如果需要可以做的比较复杂,这里就不介绍了。

# 获取目录下所有的的文件、目录等数据,如果不怕时间久可以采用递归循环
for root,dirs,files in os.walk(theDir):  
    for file in files:
            if os.path.splitext(file)[1] == '.mp4':
                print(root,dirs,file)

完整代码如下,完成后可以获得快进效果的视频,本人用这个把花开的过程浓缩到短短的几秒钟,虽然效果比不上别人家的大制作,但确实可以看到花从萌芽到盛开的过程(做好的视频附在最后):

from moviepy.editor import *
import os

s = ["2022042709"]

for sDir in s:
    L = []
    theDir = "D:\\小白摄像机\\20220427\\XiaoBaiCam\\"+sDir
    for root,dirs,files in os.walk(theDir):
        x = files.sort()
        print(x)
        for file in files:
            if os.path.splitext(file)[1] == '.mp4':
                print(root,dirs,file)
                filePath = os.path.join(root,file)
                print(filePath)
                video = VideoFileClip(filePath)
                L.append(video)
    #合并为 一个MP4文件
    final_clip = concatenate_videoclips(L)
    # # 正常输出到文件,最后大约是27-32分钟,估计与帧数设置有关
    # final_clip.to_videofile("./mp4/t"+sDir+".mp4", fps=24, remove_temp=False)

    # 下面进行快进压缩方式进行
    play_speed = 15.0 #设置速率 即15倍,上述一个小时内容合并后再压缩大约为2分钟左右

    # 根据快进速率重新生成最后文件,文件质量感觉不如用专业软件压缩的质量;如果追求质量可以把上述合并后的正常文件用专业软件进行转换
    new_au = final_clip.fl_time(lambda t:  play_speed*t, apply_to=['mask', 'audio'])
    new_au = new_au.set_duration(final_clip.duration/play_speed)
    new_au.to_videofile("./mp4/t"+sDir+".mp4", fps=24, remove_temp=False)  

花开-短视频

你可能感兴趣的:(笔记,Python,python,开发语言)