首页 > 其他分享 >改造版:moviepy使用ffmpeg按照长度分割mp4,根据源文件命名,及时关闭文件避免异常

改造版:moviepy使用ffmpeg按照长度分割mp4,根据源文件命名,及时关闭文件避免异常

时间:2023-08-26 13:00:25浏览次数:41  
标签:moviepy ffmpeg output 源文件 start part time path input

import os  # 导入 os 模块,用于处理文件和目录操作
import subprocess # 导入 subprocess 模块,用于在新的进程中执行子程序
import time # 导入 time 模块,用于处理时间相关操作
import random
from moviepy.editor import VideoFileClip # 从 moviepy.editor 模块导入 VideoFileClip 类,用于处理视频文件



def is_float(string): # 定义一个函数,判断给定字符串是否可以转换为浮点数
try:
float(string) # 尝试将字符串转换为浮点数
return True # 如果成功,返回 True
except ValueError: # 如果抛出 ValueError 异常
return False # 返回 False

def get_keyframe_timestamps(input_path): # 定义一个函数,获取输入视频文件的关键帧时间戳列表
command = [ # 定义 ffprobe 命令,用于提取关键帧时间戳
"ffprobe",
"-v", "quiet",
"-select_streams", "v",
"-skip_frame", "nokey",
"-show_entries", "frame=pkt_pts_time",
"-of", "csv=print_section=0",
input_path
]
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 运行 ffprobe 命令,并捕获标准输出和标准错误
keyframe_timestamps = [float(ts) for ts in result.stdout.decode().splitlines() if is_float(ts)] # 将输出结果转换为关键帧时间戳列表
return keyframe_timestamps # 返回关键帧时间戳列表

def split_video_ffmpeg(input_path, output_path, num_parts): # 定义一个函数,使用 FFmpeg 将输入视频分割成指定数量的部分
if not os.path.exists(output_path): # 如果输出目录不存在
os.makedirs(output_path) # 创建输出目录

video = VideoFileClip(input_path) # 读取输入视频文件
duration = video.duration # 获取视频时长

print(duration)
audio = video.audio
target_part_duration = duration / num_parts
# 计算每部分的目标时长

keyframe_timestamps = get_keyframe_timestamps(input_path) # 获取关键帧时间戳列表

part_start_times = [keyframe_timestamps[0]] # 初始化每部分的起始时间列表
for _ in range(1, num_parts): # 对于剩余部分
target_start_time = part_start_times[-1] + target_part_duration # 计算目标起始时间
closest_keyframe_time = min(keyframe_timestamps, key=lambda ts: abs(ts - target_start_time)) # 寻找最接近的关键帧时间
part_start_times.append(closest_keyframe_time) # 将找到的关键帧时间添加到起始时间列表中

start_time = time.time() # 记录开始时间
out_filename=input_path.split('\\')[-1].split('.')[0]


for i in range(num_parts): # 遍历每个部分
current_time = time.time() # 获取当前时间
elapsed_time = current_time - start_time # 计算已经过去的时间
part_start = part_start_times[i] # 获取当前部分的起始时间
part_end = part_start_times[i + 1] if i + 1 < num_parts else duration # 获取当前部分的结束时间,如果是最后一个部分,则使用视频总时长
output_file_path = os.path.join(output_path, out_filename+f"_{i + 1}.mp4") # 生成当前部分的输出文件路径

progress = (i + 1) / num_parts # 计算当前的进度百分比
time_per_part = elapsed_time / (i + 1) # 计算每个部分的平均处理时间
remaining_time = time_per_part * (num_parts - i - 1) # 估计剩余时间

command = [ # 定义 ffmpeg 命令,用于分割视频
"ffmpeg",
"-ss", str(part_start),
"-i", input_path,
"-t", str(part_end - part_start + random.randint(-10, 5)),
"-c", "copy",
output_file_path
]
subprocess.run(command) # 运行 ffmpeg 命令,分割视频

print(f"\rProcessing part {i + 1}/{num_parts}: {output_file_path}", end="") # 打印当前部分的进度信息
print(f"\rProgress: {progress:.1%}, remaining time: {remaining_time:.0f} seconds", end="") # 打印进度百分比和剩余时间估计

print("\nVideo splitting completed.") # 当所有部分处理完毕后,打印完成信息
video.close()

if __name__ == "__main__":
input_video_path = "E:\cutmp4\planet.mp4" # 输入视频文件的路径
output_videos_path = "E:\cutmp4\output" # 输出分割后的视频文件的目录
videoLength = VideoFileClip(input_video_path)
number_of_parts = int(videoLength.duration/30)-1 # 要将视频分割成的部分数量
videoLength.close()
split_video_ffmpeg(input_video_path, output_videos_path, number_of_parts) # 调用函数,将视频分割成指定数量的部分

标签:moviepy,ffmpeg,output,源文件,start,part,time,path,input
From: https://www.cnblogs.com/augustone/p/17658673.html

相关文章

  • ffmpeg 切分音频视频,统计音频时长
    #audiodurationdefmake_duration(file_path):result=sp.run(["ffprobe","-v","error","-show_entries","format=duration","-of",......
  • springboot整合资源文件
    1:什么是SpringBoot?SpringBoot基于Spring4.0设计,不仅继承了Spring框架原有的优秀特性,而且还通过==简化配置==来进一步简化Spring应用的整个搭建和开发过程。另外SpringBoot还通过继承大量框架使依赖包的版本冲突,以及引用不稳定性等问题的到了很好的解决。2:SpringBoot的优点(1)可以......
  • FFmpeg 常用命令汇总
    来源:影音视频技术文章作者:YUV420.COM文章链接: https://www.yuv420.com/2019/12/23/ffmpeg-chang-yong-ming-ling-hui-zong/引言开源音视频处理工具FFMPEG以其强大的功能而在音视频领域著称,从音视频格式转换、裁剪、拼接、提取字幕到提取视频流,编解码等无所不能,本页汇集整......
  • QT将资源打包为外部资源文件进行引用
    QT将资源打包为外部资源文件进行引用将资源打包为外部资源文件进行引用,这样能减少可执行程序exe的大小,在调试运行时需要将相应的rcc复制到对应的Debug或release目录下,否则会加载不了资源对应的qrc应该类似于myres.qrc<RCC><qresourceprefix="/"><file>res/img_bg_level_1.jpg</......
  • SpringBoot整合FFmpeg进行视频分片上传------>Windows
    SpringBoot整合FFmpeg进行视频分片上传------>Windows分片上传的核心思路:将文件按一定的分割规则(静态或动态设定,如手动设置20M为一个分片),用slice分割成多个数据块。为每个文件生成一个唯一标识Key,用于多数据块上传时区分所属文件。所有分片上传完成,服务端校验合并标识为Key的......
  • 麒麟银河系统v10编译ffmpeg并配置QT
    1.前往网站下载安装包https://www.ffmpeg.org/releases/ffmpeg-5.1.2.tar.gz2.解压tar-zxvfffmpeg-5.1.2.tar.gz3.进入文件夹并编译cd/ffmpeg-5.1.2./configure--prefix=/usr/local/ffmpeg--enable-sharedmake-j8makeinstall注意:--prefix:指定安装路径,如果不指定,头文......
  • OpenCV|FFmpeg – OpenCV cv::Mat与FFmpeg AVFrame的相互转换
    1 OpenCV cv::Mat与FFmpeg AVFrame相互转换最近在处理OpenCV采集摄像头图片然后使用ffmpeg编码为h264裸流,之后再将h264裸流转换为OpenCVcv::Mat进行显示的问题,在这个过程中,如何将OpenCV的cv::Mat转化为FFmpegAVFrame在进行h264编码,以及如何将h264解码后的AVFrame转换为cv::......
  • FFmpeg将视频转换成一帧一帧的jpeg图片(代码实现)
      #include<iostream> usingnamespacestd; extern"C" { #include"libavcodec/avcodec.h" #include"libavformat/avformat.h" #include"libswscale/swscale.h" #include......
  • ffmpeg把读取的视频流保存为jpeg文件
    intimg_savejpeg(AVFrame*pFrame,char*out_filename){//视频流保存为jpegintwidth=pFrame->width;intheight=pFrame->height;AVCodecContext*pCodeCtx=NULL;AVFormatContext*pFormatCtx=avformat_alloc_context();//设置输出文件格式pFormatCtx->oformat=av......
  • 使用ffmpeg将MP4文件的每一帧保存为jpg图片
    #include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<fcntl.h>#include<sys/ioctl.h>#include<string.h>#include<sys/mman.h>#include<assert.h>#include<liba......