递归扫描 D:\test\视频 ,将不足10秒的视频复制拼接到超过10秒
生成后直接覆盖原视频,文件名不变(原文件自动备份为 .bak)

import os
import sys
import math
import shutil
import subprocess

# ===== 自动安装依赖 =====
required_packages = ["moviepy", "tqdm"]
for pkg in required_packages:
    try:
        __import__(pkg.split('-')[0])
    except ImportError:
        print(f"📦 未找到 {pkg},正在自动安装...")
        subprocess.check_call([
            sys.executable, "-m", "pip", "install", pkg, "-i", "https://pypi.tuna.tsinghua.edu.cn/simple"
        ])

# ===== 正式逻辑 =====
from moviepy.editor import VideoFileClip, concatenate_videoclips
from tqdm import tqdm

# 固定扫描目录
ROOT_DIR = r"D:\test"
MIN_DURATION = 10  # 秒
EXTS = (".mp4", ".mov", ".mkv", ".avi", ".flv", ".webm")


def extend_and_replace(video_path, min_duration=10):
    """
    如果视频时长小于 min_duration,则拼接多次并替换原文件(备份原始)
    """
    try:
        clip = VideoFileClip(video_path)
        duration = clip.duration
        if duration >= min_duration:
            clip.close()
            return False  # 不处理

        # 计算倍数
        times = math.ceil(min_duration / duration)
        new_clip = concatenate_videoclips([clip] * times)

        # 备份原文件
        bak_path = video_path + ".bak"
        if not os.path.exists(bak_path):
            shutil.copy2(video_path, bak_path)

        temp_out = video_path + ".temp.mp4"
        print(f"🎬 {os.path.basename(video_path)} 仅 {duration:.2f}s → 复制 {times} 次 → 替换原文件")

        new_clip.write_videofile(temp_out, codec="libx264", audio_codec="aac", verbose=False, logger=None)
        clip.close()
        new_clip.close()

        # 替换原视频
        os.remove(video_path)
        os.rename(temp_out, video_path)
        return True

    except Exception as e:
        print(f"⚠ 无法处理 {video_path}: {e}")
        return False


def process_folder(root_dir, min_duration=10, exts=EXTS):
    """
    遍历文件夹,处理所有视频
    """
    video_list = []
    for root, _, files in os.walk(root_dir):
        for f in files:
            if f.lower().endswith(exts):
                video_list.append(os.path.join(root, f))

    print(f"🎞 共检测到 {len(video_list)} 个视频文件\n")
    processed = 0

    for path in tqdm(video_list, desc="处理中"):
        if extend_and_replace(path, min_duration=min_duration):
            processed += 1

    print(f"\n✅ 已处理 {processed} 个短视频(自动覆盖原文件,原始文件已备份为 .bak)")


def main():
    if not os.path.isdir(ROOT_DIR):
        print(f"❌ 目录不存在: {ROOT_DIR}")
        return

    process_folder(ROOT_DIR, min_duration=MIN_DURATION)
    print("\n📁 处理完成。短视频已延长,原文件名保持不变。")


if __name__ == "__main__":
    main()
❤️ 转载文章请注明出处,谢谢!❤️