VideoHeightHandler.py
· 2.5 KiB · Python
Sin formato
import os
import shutil
import subprocess
import concurrent.futures
from pathlib import Path
from datetime import datetime
# 指定ffmpeg的二进制文件夹位置,如果ffmpeg不在系统PATH中
FFMPEG_BIN = "C:\\ffmpeg-7.0.2-full_build\\bin\\" # 请根据实际情况修改路径
def log_error(message):
"""将错误消息写入到日志文件中"""
error_log_file = f"errorlog-{datetime.now().strftime('%Y%m%d')}.txt"
with open(error_log_file, 'a') as f:
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
f.write(f"[{timestamp}] {message}\n")
def get_video_resolution_ffprobe(video_path):
"""使用ffprobe获取视频文件的分辨率"""
ffprobe_cmd = os.path.join(FFMPEG_BIN, 'ffprobe') if FFMPEG_BIN else 'ffprobe'
cmd = [
ffprobe_cmd, '-v', 'error', '-select_streams', 'v:0',
'-show_entries', 'stream=width,height', '-of', 'csv=p=0', video_path
]
try:
output = subprocess.check_output(cmd).decode().strip()
width, height = map(int, output.split(','))
return width, height
except subprocess.CalledProcessError as e:
error_message = f"ffprobe error for file {video_path}: {e.output.decode()}"
log_error(error_message)
return None, None
def move_video(video_path, base_dir):
"""移动单个视频文件"""
try:
# 获取视频分辨率
_, height = get_video_resolution_ffprobe(video_path)
if height:
# 创建目标目录
target_dir = Path(base_dir).parent / str(height)
target_dir.mkdir(exist_ok=True)
# 移动文件
target_path = target_dir / Path(video_path).name
shutil.move(video_path, target_path)
print(f"Moved '{video_path}' to '{target_path}'")
except Exception as e:
error_message = f"Error moving file {Path(video_path).name}: {e}"
log_error(error_message)
def move_videos_by_height(base_dir):
"""根据视频高度并行移动文件"""
video_files = []
for root, _, files in os.walk(base_dir):
for file in files:
if file.lower().endswith(('.mp4', '.mkv', '.avi', '.mov', '.wmv', '.rmvb', '.flv', '.m4v', '.mpg')):
video_files.append(os.path.join(root, file))
with concurrent.futures.ThreadPoolExecutor() as executor:
# 使用多线程处理文件
executor.map(move_video, video_files, [base_dir] * len(video_files))
# 用法示例
base_directory = "foo:\\bar"
move_videos_by_height(base_directory)
| 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) |