因为很多软件比如朋友圈,淘宝什么的都限制了上传文件大小或者视频时长,所以经常需要将视频无损切割且不会增大切割后的视频大小,所以我自己写了个python脚本,配合ffmpeg来切割视频文件。


本文关键字:python分割视频/ffmpeg分割视频/
注意:在使用本python脚本之前一定要安装好ffmpeg,并能在命令行终端中调用ffmpeg。ffmpeg的安装教程需自行搜索

使用方法

  1. 模式1,每n秒就切割一份视频,比如将视频文件abc.mp4每32秒就切割出一份新的文件出来:python ffmpeg_split_video.py 1 abc.mp4 32
  2. 模式2:将视频分割成n份,比如将abc.mp4分割成5份:python ffmpeg_split_video.py 2 abc.mp4 5
  3. 模式3:指定分割的起始时间,起始时间使用#拼接,分割成的多个时间区间之间使用英文的逗号,连接。比如将abc.mp4分割成:00:00到01:02、00:10到00:30两个视频文件(可以有小时也可以没有):python ffmpeg_split_video.py 3 abc.mp4 00:00#01:02,00:00:10#00:30

代码

ffmpeg_split_video.py

# -*- coding:utf-8 -*-
"""
使用ffmpeg切割视频文件

模式1:指定分割的视频每份时长多久(单位是秒),按时间分割,使用demo对xxx.mp4每60秒切割一份视频出来:python ffmpeg_split_video.py 1 SVID_20220225_103620_1.mp4 60
模式2:指定总共要分割成多少份:总时长÷份数=每份时长,使用demo,将xxx.mp4分割成5份:python ffmpeg_split_video.py 3 xxx.mp4 60
模式3:指定分割list,按照时间段分割。:给定时间序列,每份之间使用","分割,时间开始和结束使用#分隔。比如python ffmpeg_split_video.py 3 xxx.mp4 00:02#02:04,01:02#02:04,00:02#02:04,00:02#02:04,00:02#02:04
"""
import os, sys

def call_command(cmd_content, call_path=None):
    """
    调用命令行
    call_path: 执行命令的目录
    """
    print(f"执行:{cmd_content}")
    import subprocess
    if call_path==None:
        this_file_dir_path = os.getcwd()
    # result = subprocess.run(f'ffmpeg -i video.m4s -i audio.m4s -codec copy {file_path}', shell=True, stdout=subprocess.PIPE, cwd=this_file_dir_path)
    return subprocess.run(cmd_content, shell=True, stdout=subprocess.PIPE, cwd=this_file_dir_path)


def get_input_params(params_index=1):
    """
    获取输入的命令行参数
    """
    return sys.argv[params_index]

def get_input_params_list():
    """
    获取输入的命令行参数
    """
    return sys.argv

def get_video_seconds(filename):
    """
    pip install moviepy
    获取视频时长,返回的单位是秒(s:秒),如果需要换算成时分秒,则调用time_convert()即可
    """
    from moviepy.editor import VideoFileClip
    video_clip = VideoFileClip(filename)
    durantion = video_clip.duration
    video_clip.reader.close()
    video_clip.audio.reader.close_proc()
    print(f"{durantion}-{type(durantion)}")
    return durantion

def convert_second_2_hms_str(total_seconds):
    """
    将秒数转换为"时:分:秒"的形式的字符串,fcj自己写的
    """
    h_int = int(total_seconds/(60*60))
    m_int = int(total_seconds%(60*60)/60)
    s_int = int(total_seconds%60)
    h = '00' if h_int==0 else (str(h_int) if h_int>=10 else '0'+str(h_int))
    m = '00' if m_int==0 else (str(m_int) if m_int>=10 else '0'+str(m_int))
    s = '00' if s_int==0 else (str(s_int) if s_int>=10 else '0'+str(s_int))
    return f"{h}:{m}:{s}"

def split_video_each_time(video_file_name, second_of_video_file, input_second):
    """
    给出切割完成后的每份视频时长,自动切割
    """
    if second_of_video_file>input_second:
        index = 0
        last_second = 0
        file_name, suffix = os.path.splitext(video_file_name)
        while True:
            end_second = (index+1)*input_second
            if last_second>=second_of_video_file:
                break
            start_time = convert_second_2_hms_str(last_second)
            end_time = convert_second_2_hms_str(end_second)
            call_command(f'ffmpeg -i {video_file_name} -vcodec copy -acodec copy -ss {start_time} -to {end_time} {file_name}_{index}_({start_time.replace(":","")}-{end_time.replace(":","")}){suffix} -y')
            last_second = end_second
            index+=1
    else:
        print(f"源文件比指定的大小还小,无需分割")


def main():
    params_list = get_input_params_list()
    print(f"{params_list}")
    if len(params_list)>2:
        mode = int(get_input_params(1))
        video_file_name = get_input_params(2)
        if mode==1: # 模式1:指定分割的视频每份时长多久(单位是秒),按时间分割,使用demo对xxx.mp4每60秒切割一份视频出来:python ffmpeg_split_video.py 1 SVID_20220225_103620_1.mp4 60
            second_of_video_file = get_video_seconds(video_file_name)
            input_second = int(get_input_params(3))
            split_video_each_time(video_file_name, second_of_video_file, input_second)
        elif mode==2: # 模式2:指定总共要分割成多少份:总时长÷份数=每份时长,使用demo,将xxx.mp4分割成5份:python ffmpeg_split_video.py 3 xxx.mp4 60
            second_of_video_file = get_video_seconds(video_file_name)
            input_split_count = int(get_input_params(3))
            input_second = int(second_of_video_file/input_split_count)
            split_video_each_time(video_file_name, second_of_video_file, input_second)
        elif mode==3: # 模式3:指定分割list,按照时间段分割。:给定时间序列,每份之间使用","分割,时间开始和结束使用#分隔。比如:python ffmpeg_split_video.py 3 SVID_20220225_103620_1.mp4 00:00#00:01:02,00:00:10#00:30,00:25#02:04
            second_of_video_file = get_video_seconds(video_file_name)
            input_split_time_list = get_input_params(3).split(",")
            index = 0
            for i in input_split_time_list:
                time_list = i.split("#")
                start_time = time_list[0]
                end_time = time_list[1]
                file_name, suffix = os.path.splitext(video_file_name)
                out_start_time = f"00:{start_time}" if len(start_time)<=5 else start_time
                out_end_time = f"00:{end_time}" if len(end_time)<=5 else end_time
                call_command(f'ffmpeg -i {video_file_name} -vcodec copy -acodec copy -ss {start_time} -to {end_time} {file_name}_{index}_({out_start_time.replace(":","")}-{out_end_time.replace(":","")}){suffix} -y')
                index+=1
        else:
            print("""模式错误,请重新输入:
模式1:指定分割的视频每份时长多久(单位是秒),按时间分割,使用demo对xxx.mp4每60秒切割一份视频出来:python ffmpeg_split_video.py 1 SVID_20220225_103620_1.mp4 60
模式2:指定总共要分割成多少份:总时长÷份数=每份时长,使用demo,将xxx.mp4分割成5份:python ffmpeg_split_video.py 3 xxx.mp4 60
模式3:指定分割list,按照时间段分割。:给定时间序列,每份之间使用","分割,时间开始和结束使用#分隔。比如python ffmpeg_split_video.py 3 SVID_20220225_103620_1.mp4 00:00#00:01:02,00:00:10#00:30,00:25#02:04
    """)
    else:
        print("""参数个数不足。参考:
模式1:指定分割的视频每份时长多久(单位是秒),按时间分割,使用demo对xxx.mp4每60秒切割一份视频出来:python ffmpeg_split_video.py 1 SVID_20220225_103620_1.mp4 60
模式2:指定总共要分割成多少份:总时长÷份数=每份时长,使用demo,将xxx.mp4分割成5份:python ffmpeg_split_video.py 3 xxx.mp4 60
模式3:指定分割list,按照时间段分割。:给定时间序列,每份之间使用","分割,时间开始和结束使用#分隔。比如python ffmpeg_split_video.py 3 SVID_20220225_103620_1.mp4 00:00#00:01:02,00:00:10#00:30,00:25#02:04
""")


if __name__ == '__main__':
    main()

Q.E.D.


做一个热爱生活的人