## 1. 为什么需要自动化清理低分辨率视频
最近整理电脑里的视频文件时,我发现一个头疼的问题:硬盘里堆积了大量低分辨率的老视频。这些480p甚至360p的视频不仅画质模糊,还占用了宝贵的存储空间。手动一个个检查分辨率再删除实在太费时间,于是我决定用Python写个自动化脚本来解决这个问题。
你可能也遇到过类似场景:下载文件夹里混杂着不同分辨率的视频、手机备份的视频文件大小不一、监控摄像头录制的低质量视频堆积如山。手动筛选不仅效率低下,还容易出错。这时候,一个能自动识别并清理低分辨率视频的Python脚本就能派上大用场。
这个方案特别适合以下几类用户:
- 视频创作者需要清理素材库
- IT运维人员要管理监控录像
- 普通用户想优化电脑存储空间
- 需要批量处理视频文件的研究人员
## 2. 环境准备与基础工具
### 2.1 安装必要的Python库
在开始编写脚本前,我们需要准备两个核心工具:OpenCV和os模块。OpenCV(Open Source Computer Vision Library)是一个强大的计算机视觉库,我们将用它来读取视频的元数据;而Python内置的os模块则用于文件系统操作。
安装OpenCV非常简单,只需在命令行运行:
```bash
pip install opencv-python
```
如果你使用的是Anaconda环境,也可以用:
```bash
conda install -c conda-forge opencv
```
### 2.2 测试OpenCV是否正常工作
安装完成后,建议先做个简单测试确保一切正常。创建一个test.py文件,写入以下代码:
```python
import cv2
print("OpenCV版本:", cv2.__version__)
```
运行后如果能看到版本号输出(比如4.5.5),说明安装成功。如果遇到问题,可能需要检查Python环境路径或者尝试重新安装。
## 3. 核心功能实现详解
### 3.1 获取文件夹中的视频文件列表
首先我们需要编写一个函数来获取指定文件夹中的所有文件。这里有个实用技巧:按修改时间排序文件,这样我们可以优先处理最新的视频文件。
```python
import os
import cv2
def get_file_list(file_path):
dir_list = os.listdir(file_path)
if not dir_list:
return []
else:
# 按修改时间排序
dir_list = sorted(dir_list,
key=lambda x: os.path.getmtime(os.path.join(file_path, x)))
return [f for f in dir_list if f.lower().endswith(('.mp4', '.avi', '.mov'))]
```
这个函数做了几件事:
1. 使用os.listdir获取文件夹所有内容
2. 检查是否为空文件夹
3. 用lambda函数按修改时间排序
4. 过滤出常见视频格式(mp4/avi/mov)
### 3.2 读取视频分辨率信息
接下来是关键部分:读取视频的分辨率。OpenCV的VideoCapture类让这变得很简单:
```python
def get_video_resolution(filename):
cap = cv2.VideoCapture(filename)
if not cap.isOpened():
print(f"无法打开视频文件: {filename}")
return 0, 0
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
cap.release()
return width, height
```
注意几个要点:
- 使用isOpened()检查文件是否能正常打开
- CAP_PROP_FRAME_WIDTH/HEIGHT获取宽高
- 一定要记得release()释放资源
- 将浮点数转为整数更方便比较
### 3.3 实现过滤删除逻辑
现在我们可以组合这些功能,实现完整的过滤流程:
```python
def clean_low_res_videos(folder_path, min_height=720):
video_files = get_file_list(folder_path)
for video in video_files:
full_path = os.path.join(folder_path, video)
width, height = get_video_resolution(full_path)
print(f"处理中: {video} - 分辨率: {width}x{height}")
if height < min_height:
try:
os.remove(full_path)
print(f"已删除低分辨率视频: {video}")
except Exception as e:
print(f"删除失败: {video} - {str(e)}")
```
这个函数允许我们:
- 自定义最低分辨率要求(默认720p)
- 显示处理进度信息
- 捕获删除操作中的异常
- 保留高分辨率视频
## 4. 高级功能与优化建议
### 4.1 支持更多视频格式
基础版本只支持常见格式,我们可以扩展格式支持列表:
```python
VIDEO_EXTENSIONS = ('.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv', '.webm')
def get_file_list(file_path):
# ...其他代码不变...
return [f for f in dir_list if f.lower().endswith(VIDEO_EXTENSIONS)]
```
### 4.2 添加日志记录功能
对于重要操作,建议添加日志记录:
```python
import logging
logging.basicConfig(
filename='video_cleaner.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
def clean_low_res_videos(folder_path, min_height=720):
# ...其他代码不变...
if height < min_height:
try:
os.remove(full_path)
logging.info(f"Deleted {video} ({width}x{height})")
except Exception as e:
logging.error(f"Failed to delete {video}: {str(e)}")
```
### 4.3 性能优化技巧
处理大量视频时,可以考虑以下优化:
1. 多线程处理:使用concurrent.futures加速
2. 进度显示:添加tqdm进度条
3. 内存管理:确保及时释放视频资源
```python
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm
def process_video(video, folder_path, min_height):
full_path = os.path.join(folder_path, video)
width, height = get_video_resolution(full_path)
if height < min_height:
os.remove(full_path)
def batch_clean(folder_path, min_height=720):
videos = get_file_list(folder_path)
with ThreadPoolExecutor(max_workers=4) as executor:
list(tqdm(
executor.map(lambda v: process_video(v, folder_path, min_height), videos),
total=len(videos)
))
```
## 5. 实际应用中的注意事项
### 5.1 安全防护措施
在删除文件前,强烈建议先实现"试运行"模式:
```python
def clean_low_res_videos(folder_path, min_height=720, dry_run=True):
videos = get_file_list(folder_path)
for video in videos:
full_path = os.path.join(folder_path, video)
width, height = get_video_resolution(full_path)
if height < min_height:
if dry_run:
print(f"[试运行] 将删除: {video} ({width}x{height})")
else:
try:
os.remove(full_path)
print(f"已删除: {video}")
except Exception as e:
print(f"删除失败: {video} - {str(e)}")
```
使用dry_run=True参数可以先查看哪些文件会被删除,确认无误后再实际执行。
### 5.2 处理特殊情况的技巧
在实际使用中可能会遇到:
1. 损坏的视频文件:添加异常处理
2. 权限问题:检查文件可写权限
3. 路径问题:处理空格和特殊字符
改进后的版本:
```python
def get_video_resolution(filename):
try:
cap = cv2.VideoCapture(filename)
if not cap.isOpened():
return 0, 0
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
return width, height
except Exception as e:
print(f"读取视频信息出错: {filename} - {str(e)}")
return 0, 0
finally:
if 'cap' in locals():
cap.release()
```
### 5.3 图形界面扩展
对于非技术用户,可以考虑用tkinter添加简单GUI:
```python
import tkinter as tk
from tkinter import filedialog, messagebox
class VideoCleanerApp:
def __init__(self):
self.window = tk.Tk()
self.setup_ui()
def setup_ui(self):
# 创建界面元素
self.window.title("视频清理工具")
tk.Label(self.window, text="文件夹路径:").pack()
self.path_entry = tk.Entry(self.window, width=50)
self.path_entry.pack()
tk.Button(self.window, text="浏览...", command=self.browse_folder).pack()
tk.Label(self.window, text="最低分辨率(高度):").pack()
self.res_entry = tk.Entry(self.window)
self.res_entry.insert(0, "720")
self.res_entry.pack()
tk.Button(self.window, text="开始清理", command=self.start_cleaning).pack()
def browse_folder(self):
folder = filedialog.askdirectory()
if folder:
self.path_entry.delete(0, tk.END)
self.path_entry.insert(0, folder)
def start_cleaning(self):
folder = self.path_entry.get()
min_height = int(self.res_entry.get())
clean_low_res_videos(folder, min_height)
messagebox.showinfo("完成", "视频清理完成!")
if __name__ == "__main__":
app = VideoCleanerApp()
app.window.mainloop()
```
## 6. 完整代码整合与使用示例
将所有功能整合成一个完整的脚本:
```python
import os
import cv2
import logging
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm
# 配置
VIDEO_EXTENSIONS = ('.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv', '.webm')
logging.basicConfig(
filename='video_cleaner.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
def get_file_list(file_path):
"""获取文件夹中的视频文件列表并按修改时间排序"""
dir_list = os.listdir(file_path)
if not dir_list:
return []
return sorted(
[f for f in dir_list if f.lower().endswith(VIDEO_EXTENSIONS)],
key=lambda x: os.path.getmtime(os.path.join(file_path, x))
)
def get_video_resolution(filename):
"""获取视频分辨率"""
try:
cap = cv2.VideoCapture(filename)
if not cap.isOpened():
return 0, 0
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
return width, height
except Exception as e:
logging.error(f"Error reading {filename}: {str(e)}")
return 0, 0
finally:
if 'cap' in locals():
cap.release()
def process_video(video, folder_path, min_height, dry_run):
"""处理单个视频文件"""
full_path = os.path.join(folder_path, video)
width, height = get_video_resolution(full_path)
if height < min_height:
if dry_run:
logging.info(f"[Dry Run] Would delete {video} ({width}x{height})")
print(f"[试运行] 将删除: {video} ({width}x{height})")
else:
try:
os.remove(full_path)
logging.info(f"Deleted {video} ({width}x{height})")
print(f"已删除: {video}")
except Exception as e:
logging.error(f"Failed to delete {video}: {str(e)}")
print(f"删除失败: {video} - {str(e)}")
def clean_low_res_videos(folder_path, min_height=720, dry_run=False, max_workers=4):
"""主清理函数"""
if not os.path.exists(folder_path):
print(f"路径不存在: {folder_path}")
return
videos = get_file_list(folder_path)
if not videos:
print("没有找到视频文件")
return
print(f"找到 {len(videos)} 个视频文件,开始处理...")
with ThreadPoolExecutor(max_workers=max_workers) as executor:
tasks = [
executor.submit(process_video, v, folder_path, min_height, dry_run)
for v in videos
]
for _ in tqdm(tasks, total=len(tasks)):
pass
if __name__ == "__main__":
# 使用示例
folder = input("请输入视频文件夹路径: ")
min_h = int(input("输入最低分辨率(高度): ") or "720")
dry = input("试运行模式?(y/n): ").lower() == 'y'
clean_low_res_videos(folder, min_h, dry)
```
这个完整版本包含了我们讨论的所有功能:
- 多格式支持
- 多线程处理
- 进度显示
- 日志记录
- 试运行模式
- 完善的错误处理
使用时只需将脚本保存为video_cleaner.py,然后运行:
```bash
python video_cleaner.py
```
按照提示输入文件夹路径、最低分辨率要求和是否试运行即可。第一次使用时建议先使用试运行模式确认效果。