需求
老板要求我上传数百张高清图片和视频。然而,直接上传这些大文件会显著拖慢网页的加载时间,因此需要先对它们进行压缩处理后再上传。
我的具体需求包括:
批量压缩图片与视频。
文件大小至少减少50%以上。
在不影响视觉效果的前提下进行压缩,确保用户几乎察觉不到画质差异。
调研
在寻找合适的压缩工具时,我发现市面上大多数软件要么需要付费订阅,要么仅支持单一类型的媒体文件(如只支持图片或视频),又或者只能逐个文件手动操作。这不仅增加了成本,还大大降低了工作效率。
经过一番努力后,我发现Python中的Pillow库非常适合用来批量处理图像,而MoviePy库则可以很好地应对视频文件。结合这两个强大的库,我可以编写一个简单的脚本来自动执行压缩任务。
此外,利用Python的跨平台GUI框架Kivy,我可以为这个脚本添加一个图形界面,使得整个过程变得更加直观易用。最终,只需通过一个简洁的Python脚本文件即可完成从文件选择到批量压缩的所有步骤,极大地简化了工作流程。
开发
安装环境
首先安装python3.x和pip工具
然后安装setuptools和virtualenv
python -m pip install --upgrade pip setuptools virtualenv
创建虚拟环境
在当前目录创建名字为kivy_venv的虚拟环境
python -m venv kivy_venv
激活虚拟环境,每一次打开命令行工具都需要激活
Windows自带的Cmd输入
kivy_venv\Scripts\activate
Windows下的bash终端输入
source kivy_venv/Scripts/activate
Linux或者macOS终端输入
source kivy_venv/bin/activate
环境激活之后会在路径前面显示虚拟环境的名字(kivy_venv)
pip安装相关python库
pip install moviepy pillow piexif imghdr
代码编写
用kivy创建界面
<StatefulLabel>:
rgba: (1,1,1,1)
canvas.before:
Color:
rgba: self.rgba
Rectangle:
pos: self.pos
size: self.size
Label:
id: file_name
text: root.text
padding: 10,10,10,10
color: 0,0,0,1
size_hint_x: 0.6
text_size: self.size
halign: 'left'
font_name: 'simsun'
Label:
id: file_size
size_hint_x: 0.2
color: 0,0,0,1
padding: 10,10,10,10
text_size: self.size
halign: 'center'
text: root.size_text
Label:
id: file_saving
size_hint_x: 0.2
color: 0,0,0,1
padding: 10,10,10,10
text_size: self.size
halign: 'center'
text: root.saving_text
<RV>:
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
viewclass: 'StatefulLabel'
RecycleBoxLayout:
spacing: 0
default_size: None, dp(36)
size_hint_y: None
default_size_hint: 1, None
height: self.minimum_height
orientation: 'vertical'
BoxLayout:
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
orientation: 'vertical'
BoxLayout:
size_hint_y: 0.05
orientation: 'horizontal'
Label:
text: 'File'
size_hint_x: 0.6
color: 0,0,0,1
padding: 10,10,10,10
text_size: self.size
canvas:
Color:
rgba: 0.8,0.8,0.8,1
Line:
rectangle: (self.pos[0], root.height - self.height, self.width, self.height)
width: 2
Label:
text: 'Size'
size_hint_x: 0.2
color: 0,0,0,1
padding: 10,10,10,10
halign: 'center'
text_size: self.size
canvas:
Color:
rgba: 0.8,0.8,0.8,1
Line:
rectangle: (self.pos[0], root.height - self.height, self.width, self.height)
width: 2
Label:
text: 'Savings'
color: 0,0,0,1
size_hint_x: 0.2
padding: 10,10,10,10
text_size: self.size
halign: 'center'
canvas:
Color:
rgba: 0.8,0.8,0.8,1
Line:
rectangle: (self.pos[0], root.height - self.height, self.width, self.height)
width: 2
RV:
id: rv
处理拖放文件
绑定on_drop_file事件
def build(self):
Window.bind(on_drop_file=self.handledrops)
self.title = "MediaSimple"
return Builder.load_string(kvStr)
写回调函数进行处理
def handledrops(self, window, filename, x, y):
path = bytes.decode(filename)
print(path)
imghdr库判断文件类型
def whatImage(self, path):
return imghdr.what(path)
PIL压缩图片
def reducePng(self,path, destFilename):
with Image.open(path) as img:
img = Image.open(path)
img_8bit = img.convert("P", palette=Image.ADAPTIVE, colors=256)
img_8bit.save(destFilename)
moviepy处理视频
def reduceMp4(self,path, destFilename):
with VideoFileClip(path) as video_clip:
video_clip.write_videofile(destFilename, bitrate='2500K')