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"]