import os
import subprocess
import random
import json
# 配置参数
TARGET_WIDTH = 500
TARGET_HEIGHT = 600
TARGET_DURATION = 180 # 目标时长(秒)
OUTPUT_DIR = "processed_videos"
MIRROR_MODES = ["none", "horizontal", "vertical", "diagonal"]
CROP_POSITIONS = ["center", "top", "bottom", "left", "right", "top-left", "top-right", "bottom-left", "bottom-right"]
def get_video_info(file_path):
"""获取视频的宽度、高度和时长"""
cmd = [
'ffprobe', '-v', 'error',
'-select_streams', 'v:0',
'-show_entries', 'stream=width,height',
'-show_entries', 'format=duration',
'-of', 'json',
file_path
]
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
info = json.loads(result.stdout)
width = int(info['streams'][0]['width'])
height = int(info['streams'][0]['height'])
duration = float(info['format']['duration'])
return width, height, duration
def process_video(input_path, output_path):
"""处理单个视频文件"""
# 获取视频信息
width, height, duration = get_video_info(input_path)
print(f"处理: {os.path.basename(input_path)}")
print(f" 原始尺寸: {width}x{height}, 时长: {duration:.2f}秒")
# 计算需要循环的次数
loops = int(TARGET_DURATION / duration) + 1
# 随机选择镜像模式和裁剪位置
mirror_mode = random.choice(MIRROR_MODES)
crop_position = random.choice(CROP_POSITIONS)
print(f" 使用镜像模式: {mirror_mode}, 裁剪位置: {crop_position}")
# 构建FFmpeg滤镜链
filters = []
# 1. 缩放:确保视频至少达到目标尺寸
filters.append(f"scale=w='if(lt(iw,{TARGET_WIDTH}),{TARGET_WIDTH},iw':h='if(lt(ih,{TARGET_HEIGHT}),{TARGET_HEIGHT},ih':force_original_aspect_ratio=increase")
# 2. 智能裁剪
if crop_position == "center":
filters.append(f"crop={TARGET_WIDTH}:{TARGET_HEIGHT}:(iw-{TARGET_WIDTH})/2:(ih-{TARGET_HEIGHT})/2")
elif crop_position == "top":
filters.append(f"crop={TARGET_WIDTH}:{TARGET_HEIGHT}:0:0")
elif crop_position == "bottom":
filters.append(f"crop={TARGET_WIDTH}:{TARGET_HEIGHT}:0:ih-{TARGET_HEIGHT}")
elif crop_position == "left":
filters.append(f"crop={TARGET_WIDTH}:{TARGET_HEIGHT}:0:(ih-{TARGET_HEIGHT})/2")
elif crop_position == "right":
filters.append(f"crop={TARGET_WIDTH}:{TARGET_HEIGHT}:iw-{TARGET_WIDTH}:(ih-{TARGET_HEIGHT})/2")
elif crop_position == "top-left":
filters.append(f"crop={TARGET_WIDTH}:{TARGET_HEIGHT}:0:0")
elif crop_position == "top-right":
filters.append(f"crop={TARGET_WIDTH}:{TARGET_HEIGHT}:iw-{TARGET_WIDTH}:0")
elif crop_position == "bottom-left":
filters.append(f"crop={TARGET_WIDTH}:{TARGET_HEIGHT}:0:ih-{TARGET_HEIGHT}")
elif crop_position == "bottom-right":
filters.append(f"crop={TARGET_WIDTH}:{TARGET_HEIGHT}:iw-{TARGET_WIDTH}:ih-{TARGET_HEIGHT}")
# 3. 镜像效果
mirror_filters = []
if mirror_mode == "horizontal":
mirror_filters.append("hflip")
elif mirror_mode == "vertical":
mirror_filters.append("vflip")
elif mirror_mode == "diagonal":
mirror_filters.append("hflip,vflip")
# 4. 构建完整滤镜链
filter_chain = ",".join(filters)
if mirror_filters:
filter_chain += "," + ",".join(mirror_filters)
# 5. 构建FFmpeg命令
cmd = [
'ffmpeg', '-y', '-i', input_path,
'-vf', filter_chain,
'-filter_complex', f'loop={loops}:32767:0,trim=duration={TARGET_DURATION}',
'-c:v', 'libx264', '-preset', 'fast', '-crf', '23',
'-an', # 移除音频
output_path
]
# 6. 执行命令
subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
print(f" 处理完成: {os.path.basename(output_path)}")
def batch_process_videos(input_dir):
"""批量处理目录中的所有MP4视频文件"""
# 创建输出目录
os.makedirs(OUTPUT_DIR, exist_ok=True)
# 遍历目录中的所有MP4文件
processed_count = 0
for filename in os.listdir(input_dir):
if filename.lower().endswith('.mp4'):
input_path = os.path.join(input_dir, filename)
output_path = os.path.join(OUTPUT_DIR, f"processed_{filename}")
try:
process_video(input_path, output_path)
processed_count += 1
except Exception as e:
print(f"处理 {filename} 时出错: {str(e)}")
print(f"\n处理完成! 共处理 {processed_count} 个视频文件")
print(f"输出目录: {os.path.abspath(OUTPUT_DIR)}")
if __name__ == "__main__":
# 设置当前目录为输入目录
input_directory = os.getcwd()
print("开始批量处理视频...")
print(f"目标尺寸: {TARGET_WIDTH}x{TARGET_HEIGHT}")
print(f"目标时长: {TARGET_DURATION}秒")
print(f"输出目录: {OUTPUT_DIR}\n")
batch_process_videos(input_directory)
----------------自定义选项------------
# 目标尺寸
TARGET_WIDTH = 500
TARGET_HEIGHT = 600
# 目标时长(秒)
TARGET_DURATION = 180
# 输出目录
OUTPUT_DIR = "processed_videos"
# 镜像模式选项
MIRROR_MODES = ["none", "horizontal", "vertical", "diagonal"]
# 裁剪位置选项
CROP_POSITIONS = ["center", "top", "bottom", "left", "right",
"top-left", "top-right", "bottom-left", "bottom-right"]