This commit is contained in:
闫旭隆
2026-01-09 11:22:42 +08:00
parent f4314c3ede
commit 202d1cb5ba
1066 changed files with 179639 additions and 7618 deletions

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""
视频按大小分割脚本
将视频分割为指定大小默认180MB的片段
先压缩画面质量,再将视频分割为指定时长的片段
"""
import os
import subprocess
@ -12,8 +12,10 @@ import imageio_ffmpeg
# 配置
INPUT_DIR = Path(__file__).parent / "原视频"
OUTPUT_DIR = Path(__file__).parent / "分割后"
TARGET_DURATION_MIN = 30 # 目标片段时长(分钟)
TEMP_DIR = Path(__file__).parent / "压缩临时"
TARGET_DURATION_MIN = 50 # 目标片段时长(分钟)
MERGE_THRESHOLD_MIN = 10 # 最后一段小于此时长则合并到前一段
COMPRESS_CRF = 51 # 画面压缩质量 (0-51, 越大压缩越狠)
FFMPEG_PATH = imageio_ffmpeg.get_ffmpeg_exe()
def get_video_info(video_path):
@ -37,10 +39,62 @@ def get_video_info(video_path):
file_size = os.path.getsize(video_path)
return duration, file_size
def split_video(video_path):
def compress_video(video_path, output_path):
"""压缩视频画面质量,音频保持原样"""
# 先获取视频时长用于进度计算
duration, _ = get_video_info(video_path)
cmd = [
FFMPEG_PATH,
'-y',
'-i', str(video_path),
'-c:v', 'libx264', # CPU编码
'-crf', str(COMPRESS_CRF), # 质量控制 (0-51)
'-preset', 'ultrafast', # 最快编码速度
'-c:a', 'copy', # 音频直接复制,不重新编码
str(output_path)
]
import time as time_module
import threading
print(f" 压缩中...", end='', flush=True)
# 用线程执行 ffmpeg
result = {'returncode': None, 'stderr': ''}
def run_ffmpeg():
proc = subprocess.run(cmd, capture_output=True)
result['returncode'] = proc.returncode
result['stderr'] = proc.stderr.decode('utf-8', errors='replace')
thread = threading.Thread(target=run_ffmpeg)
thread.start()
start_time = time_module.time()
while thread.is_alive():
time_module.sleep(1)
elapsed = int(time_module.time() - start_time)
if output_path.exists():
current_size = os.path.getsize(output_path) / (1024 * 1024)
print(f"\r 压缩中... 已用{elapsed}秒, 输出{current_size:.1f}MB", end='', flush=True)
thread.join()
elapsed = int(time_module.time() - start_time)
# 检查是否成功
if result['returncode'] != 0:
print(f"\r 压缩失败! 错误码: {result['returncode']}", flush=True)
print(f" 错误信息: {result['stderr'][-500:]}", flush=True)
raise RuntimeError("压缩失败")
print(f"\r 压缩完成! 耗时{elapsed}", flush=True)
return output_path
def split_video(video_path, original_name=None):
"""将视频按时长分割"""
video_path = Path(video_path)
video_name = video_path.stem
video_name = original_name if original_name else video_path.stem
video_ext = video_path.suffix
# 获取视频信息
@ -57,7 +111,7 @@ def split_video(video_path):
# 如果视频短于目标时长,直接复制
if duration <= target_duration:
print(f" 视频短于{TARGET_DURATION_MIN}分钟,无需分割")
output_path = OUTPUT_DIR / f"{video_name}-1{video_ext}"
output_path = OUTPUT_DIR / f"1-{video_name}{video_ext}"
import shutil
shutil.copy2(video_path, output_path)
print(f" 已复制到: {output_path.name}")
@ -80,7 +134,7 @@ def split_video(video_path):
output_files = []
for segment_index, (start_time, actual_duration) in enumerate(segments, 1):
output_path = OUTPUT_DIR / f"{video_name}-{segment_index}{video_ext}"
output_path = OUTPUT_DIR / f"{segment_index}-{video_name}{video_ext}"
cmd = [
FFMPEG_PATH,
@ -107,14 +161,16 @@ def split_video(video_path):
def main():
print("=" * 50)
print("视频分割工具")
print("视频压缩+分割工具")
print(f"输入目录: {INPUT_DIR}")
print(f"输出目录: {OUTPUT_DIR}")
print(f"画面压缩: CRF {COMPRESS_CRF}")
print(f"目标时长: {TARGET_DURATION_MIN}分钟/段")
print("=" * 50)
# 创建输出目录
# 创建目录
OUTPUT_DIR.mkdir(exist_ok=True)
TEMP_DIR.mkdir(exist_ok=True)
# 支持的视频格式
video_extensions = {'.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm'}
@ -132,11 +188,34 @@ def main():
# 处理每个视频
for video_file in video_files:
try:
split_video(video_file)
# 第一步:压缩视频
original_size = os.path.getsize(video_file) / (1024 * 1024)
print(f"压缩: {video_file.name} ({original_size:.1f}MB)", flush=True)
compressed_path = TEMP_DIR / f"{video_file.stem}_compressed.mp4"
compress_video(video_file, compressed_path)
if compressed_path.exists():
compressed_size = os.path.getsize(compressed_path) / (1024 * 1024)
ratio = (1 - compressed_size / original_size) * 100
print(f" -> 压缩后: {compressed_size:.1f}MB (压缩率 {ratio:.1f}%)", flush=True)
# 第二步:分割压缩后的视频
split_video(compressed_path, original_name=video_file.stem)
# 清理临时文件
if compressed_path.exists():
compressed_path.unlink()
print()
except Exception as e:
print(f" 错误: {e}\n")
# 清理临时目录
try:
TEMP_DIR.rmdir()
except:
pass
print("=" * 50)
print("处理完成!")
print("=" * 50)