xym revisó este gist . Ir a la revisión
1 file changed, 0 insertions, 0 deletions
VideoHeightHandler renombrado a VideoHeightHandler.py
Archivo renombrado sin cambios
xym revisó este gist . Ir a la revisión
1 file changed, 66 insertions
VideoHeightHandler(archivo creado)
| @@ -0,0 +1,66 @@ | |||
| 1 | + | import os | |
| 2 | + | import shutil | |
| 3 | + | import subprocess | |
| 4 | + | import concurrent.futures | |
| 5 | + | from pathlib import Path | |
| 6 | + | from datetime import datetime | |
| 7 | + | ||
| 8 | + | # 指定ffmpeg的二进制文件夹位置,如果ffmpeg不在系统PATH中 | |
| 9 | + | FFMPEG_BIN = "C:\\ffmpeg-7.0.2-full_build\\bin\\" # 请根据实际情况修改路径 | |
| 10 | + | ||
| 11 | + | def log_error(message): | |
| 12 | + | """将错误消息写入到日志文件中""" | |
| 13 | + | error_log_file = f"errorlog-{datetime.now().strftime('%Y%m%d')}.txt" | |
| 14 | + | with open(error_log_file, 'a') as f: | |
| 15 | + | timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') | |
| 16 | + | f.write(f"[{timestamp}] {message}\n") | |
| 17 | + | ||
| 18 | + | def get_video_resolution_ffprobe(video_path): | |
| 19 | + | """使用ffprobe获取视频文件的分辨率""" | |
| 20 | + | ffprobe_cmd = os.path.join(FFMPEG_BIN, 'ffprobe') if FFMPEG_BIN else 'ffprobe' | |
| 21 | + | cmd = [ | |
| 22 | + | ffprobe_cmd, '-v', 'error', '-select_streams', 'v:0', | |
| 23 | + | '-show_entries', 'stream=width,height', '-of', 'csv=p=0', video_path | |
| 24 | + | ] | |
| 25 | + | try: | |
| 26 | + | output = subprocess.check_output(cmd).decode().strip() | |
| 27 | + | width, height = map(int, output.split(',')) | |
| 28 | + | return width, height | |
| 29 | + | except subprocess.CalledProcessError as e: | |
| 30 | + | error_message = f"ffprobe error for file {video_path}: {e.output.decode()}" | |
| 31 | + | log_error(error_message) | |
| 32 | + | return None, None | |
| 33 | + | ||
| 34 | + | def move_video(video_path, base_dir): | |
| 35 | + | """移动单个视频文件""" | |
| 36 | + | try: | |
| 37 | + | # 获取视频分辨率 | |
| 38 | + | _, height = get_video_resolution_ffprobe(video_path) | |
| 39 | + | if height: | |
| 40 | + | # 创建目标目录 | |
| 41 | + | target_dir = Path(base_dir).parent / str(height) | |
| 42 | + | target_dir.mkdir(exist_ok=True) | |
| 43 | + | ||
| 44 | + | # 移动文件 | |
| 45 | + | target_path = target_dir / Path(video_path).name | |
| 46 | + | shutil.move(video_path, target_path) | |
| 47 | + | print(f"Moved '{video_path}' to '{target_path}'") | |
| 48 | + | except Exception as e: | |
| 49 | + | error_message = f"Error moving file {Path(video_path).name}: {e}" | |
| 50 | + | log_error(error_message) | |
| 51 | + | ||
| 52 | + | def move_videos_by_height(base_dir): | |
| 53 | + | """根据视频高度并行移动文件""" | |
| 54 | + | video_files = [] | |
| 55 | + | for root, _, files in os.walk(base_dir): | |
| 56 | + | for file in files: | |
| 57 | + | if file.lower().endswith(('.mp4', '.mkv', '.avi', '.mov', '.wmv', '.rmvb', '.flv', '.m4v', '.mpg')): | |
| 58 | + | video_files.append(os.path.join(root, file)) | |
| 59 | + | ||
| 60 | + | with concurrent.futures.ThreadPoolExecutor() as executor: | |
| 61 | + | # 使用多线程处理文件 | |
| 62 | + | executor.map(move_video, video_files, [base_dir] * len(video_files)) | |
| 63 | + | ||
| 64 | + | # 用法示例 | |
| 65 | + | base_directory = "foo:\\bar" | |
| 66 | + | move_videos_by_height(base_directory) | |