在剪辑视频的时候,如果视频很少的情况可以考虑自己使用软件来拼接一下,但是如果要给几百个视频加片头片尾,那就需要使用软件来加了。
基础代码示例:
from moviepy.editor import VideoFileClip, concatenate_videoclips# 读取三段视频 piantou = VideoFileClip("piantou-10000k-25f.mp4") video = VideoFileClip("video.mp4") pianwei = VideoFileClip("pianwei-10000k-25f.mp4") # 拼接并导出 outvideo = concatenate_videoclips([piantou, video, pianwei]) outvideo.write_videofile("outvideo.mp4")
这种方式可以给一个视频添加片头片尾。
批量给视频视频添加片头片尾:
import os import re import time import subprocess from multiprocessing import Pool from typing import List, Dict# 配置路径 INPUT_VIDEO_DIR = r"E:\python-test\视频处理\原视频" # 原视频文件夹 OUTPUT_VIDEO_DIR = r"E:\python-test\视频处理\带片头片尾视频" # 输出文件夹 OPENING_VIDEO = r"E:\python-test\视频处理\piantou-tongyi.mp4" # 片头视频路径 ENDING_VIDEO = r"E:\python-test\视频处理\pianwei-tongyi.mp4" # 片尾视频路径# 支持的视频格式(可扩展) SUPPORTED_FORMATS = ('.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv')def check_dependencies() -> bool:"""检查ffmpeg是否可用及片头片尾文件是否存在"""# 检查ffmpegtry:subprocess.run(['ffmpeg', '-version'], capture_output=True, check=True)except (subprocess.CalledProcessError, FileNotFoundError):print("错误:未找到ffmpeg!请安装并配置环境变量")return False# 检查片头文件if not os.path.exists(OPENING_VIDEO):print(f"错误:片头文件不存在 - {OPENING_VIDEO}")return False# 检查片尾文件if not os.path.exists(ENDING_VIDEO):print(f"错误:片尾文件不存在 - {ENDING_VIDEO}")return Falsereturn Truedef get_video_duration(file_path: str) -> float:"""获取视频时长(秒)"""try:result = subprocess.run(['ffmpeg', '-i', file_path],stdout=subprocess.PIPE,stderr=subprocess.STDOUT,encoding='utf-8',errors='ignore')# 匹配时长格式(如:Duration: 00:01:23.45)pattern = re.compile(r"Duration:\s*(\d+):(\d+):(\d+\.\d+)")match = pattern.search(result.stdout)if not match:return -1hours = float(match.group(1))minutes = float(match.group(2))seconds = float(match.group(3))return hours * 3600 + minutes * 60 + secondsexcept Exception as e:print(f"获取时长失败:{file_path},错误:{str(e)}")return -1def concat_videos(opening: str, main_video: str, ending: str, output: str) -> bool:"""拼接片头、主视频、片尾"""# 确保输出目录存在os.makedirs(os.path.dirname(output), exist_ok=True)# 创建临时文件列表(ffmpeg拼接需要的文件列表)temp_list = f"{output}.txt"try:with open(temp_list, 'w', encoding='utf-8') as f:f.write(f"file '{opening}'\n")f.write(f"file '{main_video}'\n")f.write(f"file '{ending}'\n")# ffmpeg命令:使用concat协议拼接(快速,无需重新编码)command = ['ffmpeg', '-f', 'concat', '-safe', '0', '-i', temp_list,'-c', 'copy', '-y', # -y:覆盖已有文件 output]result = subprocess.run(command,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,encoding='utf-8',errors='ignore',timeout=600 # 超时时间10分钟 )if result.returncode != 0:print(f"拼接失败:{main_video},错误:{result.stderr[:500]}")return Falseprint(f"拼接成功:{output}")return Trueexcept Exception as e:print(f"拼接异常:{main_video},错误:{str(e)}")return Falsefinally:# 清理临时文件if os.path.exists(temp_list):try:os.remove(temp_list)except:passdef process_single_video(task: Dict[str, str]) -> None:"""处理单个视频的函数(供多进程调用)"""main_video = task['main_video']output_video = task['output_video']# 检查原视频是否有效duration = get_video_duration(main_video)if duration <= 0:print(f"跳过无效视频:{main_video}")return# 执行拼接 concat_videos(opening=OPENING_VIDEO,main_video=main_video,ending=ENDING_VIDEO,output=output_video)def get_all_videos(folder: str) -> List[str]:"""递归获取所有支持的视频文件"""video_files = []for root, _, files in os.walk(folder):for file in files:if file.lower().endswith(SUPPORTED_FORMATS):video_files.append(os.path.join(root, file))return video_filesif __name__ == "__main__":# 检查依赖if not check_dependencies():input("按回车键退出...")exit(1)# 获取所有视频文件video_files = get_all_videos(INPUT_VIDEO_DIR)if not video_files:print(f"未在 {INPUT_VIDEO_DIR} 找到支持的视频文件(格式:{SUPPORTED_FORMATS})")input("按回车键退出...")exit(0)print(f"共找到 {len(video_files)} 个视频文件,准备添加片头片尾...")# 构建任务列表(保持原文件目录结构)tasks = []for video in video_files:# 计算输出路径(保持原目录结构)relative_path = os.path.relpath(video, INPUT_VIDEO_DIR)output_path = os.path.join(OUTPUT_VIDEO_DIR, relative_path)tasks.append({'main_video': video,'output_video': output_path})# 多进程处理start_time = time.time()print("\n开始处理...")# 进程数设为CPU核心数的一半,避免资源占用过高with Pool(processes=os.cpu_count() // 2) as pool:pool.map(process_single_video, tasks)# 统计结果total_time = time.time() - start_timeprint(f"\n处理完成!共处理 {len(video_files)} 个视频,耗时 {total_time:.2f} 秒")print(f"输出目录:{OUTPUT_VIDEO_DIR}")input("按回车键退出...")
简直了YYDS!
打完收工!