python压缩图片和视频

article/2025/9/1 14:53:23

引言

在真实项目中,往往要进行图片的传输和视频的传输,但因为用户上传的图片和视频所占用的大小问题而导致占用服务器的空间多,并且用户访问这些图片的时候因为图片或视频太大而长时间加载,所以要对用户上传的视频和图片进行压缩,减少服务器的占用空间和加载时间。

1.新建一个类

我们先新建一个保存图片或视频的一个类

import platformclass Compress_Pic_or_Video(object):def __init__(self,filePath,inputName,outName=""):self.filePath = filePath  #文件地址self.inputName = inputName  #输入的文件名字self.outName = outName  #输出的文件名字self.system_ = platform.platform().split("-",1)[0]	#判断是那个操作系统,因为我的服务器是Linux的但我电脑是windows的,所以只设置了这两个系统的判断if  self.system_ ==  "Windows":	#对windows的文件格式进行设置self.filePath = (self.filePath + "\\") if self.filePath.rsplit("\\",1)[-1] else self.filePathelif self.system_ == "Linux":	#对Linux的文件格式进行设置self.filePath = (self.filePath + "/") if self.filePath.rsplit("/",1)[-1] else self.filePathself.fileInputPath = self.filePath + inputName	#拼接输入的路径self.fileOutPath = self.filePath + outName	#拼接输出的路径

2.设置判断文件是否是图片或视频

	@propertydef is_picture(self):picSuffixSet = {"BMP","GIF","JPEG","TIFF","PNG","SVG","PCX","WMF","EMF","LIC","EPS","TGA","JPG"}	#常用后缀,集合的搜索速度快,所以用集合而不用列表,还能做到去重,避免输入了重复的后缀名suffix = self.fileInputPath.rsplit(".",1)[-1].upper()if suffix in picSuffixSet:return Trueelse:return False@propertydef is_video(self):videoSuffixSet = {"WMV","ASF","ASX","RM","RMVB","MP4","3GP","MOV","M4V","AVI","DAT","MKV","FIV","VOB"}suffix = self.fileInputPath.rsplit(".",1)[-1].upper()if suffix in videoSuffixSet:return Trueelse:return False

3.对上传的图片进行压缩

import zlib	#压缩的库
import threading	#多线程
from PIL import Imagedef SavePic(self):fpsize = os.path.getsize(self.fileInputPath) / 1024  # 获得图片多少K   os.path.getsize(self.picPath)返回的是字节if fpsize >= 50.0:  # 是否大于50Kim = Image.open(self.fileInputPath)  # 打开图片imBytes = im.tobytes()  # 把图片转换成bytes流imBytes = zlib.compress(imBytes, 5)  # 对图像字节串进行压缩,第二个参数是压缩率有-1,0-9,按个人情况进行设置,我都试过了感觉没多大变化,所以随便设置了5im2 = Image.frombytes('RGB', im.size, zlib.decompress(imBytes))  # 压缩成新的图片if self.outName:im2.save(self.fileOutPath)  #不覆盖原图return (self.fileOutPath,os.path.getsize(self.fileOutPath))else:im2.save(self.fileInputPath)    #覆盖原图return (self.fileInputPath,os.path.getsize(self.fileInputPath))else:return Truedef Compress_Picture(self):#异步保存打开下面的代码,注释同步保存的代码,我选用的是异步保存,因为如果图片太大用同步的话会阻塞程序的运行,按自己的情况去选择,也可以设置一个变量,然后用判断来看是否启动多线程保存thr = threading.Thread(target=self.SavePic)thr.start()#下面为同步保存# fpsize = os.path.getsize(self.fileInputPath) / 1024  # 获得图片多少K   os.path.getsize(self.picPath)返回的是字节# if fpsize >= 50.0:  # 是否大于50K#     im = Image.open(self.fileInputPath)  # 打开图片#     imBytes = im.tobytes()  # 把图片转换成bytes流#     imBytes = zlib.compress(imBytes, 5)  # 对图像字节串进行压缩#     im2 = Image.frombytes('RGB', im.size, zlib.decompress(imBytes))  # 压缩成新的图片#     if self.outName:#         im2.save(self.fileOutPath)  # 不覆盖原图#         return (self.fileOutPath, os.path.getsize(self.fileOutPath) / 1024)#     else:#         im2.save(self.fileInputPath)  # 覆盖原图#         return (self.fileInputPath, os.path.getsize(self.fileInputPath) / 1024)# else:#     return True

4.对上传的视频进行压缩

import osdef SaveVideo(self):fpsize = os.path.getsize(self.fileInputPath) / 1024if fpsize >= 150.0: #大于150KB的视频需要压缩if self.outName:compress = "ffmpeg -i {} -r 10 -pix_fmt yuv420p -vcodec libx264 -preset veryslow -profile:v baseline  -crf 23 -acodec aac -b:a 32k -strict -5 {}".format(self.fileInputPath,self.fileOutPath)isRun = os.system(compress)else:compress = "ffmpeg -i {} -r 10 -pix_fmt yuv420p -vcodec libx264 -preset veryslow -profile:v baseline  -crf 23 -acodec aac -b:a 32k -strict -5 {}".format(self.fileInputPath, self.fileInputPath)isRun = os.system(compress)if isRun != 0:return (isRun,"没有安装ffmpeg")return Trueelse:return Truedef Compress_Video(self):# 异步保存打开下面的代码,注释同步保存的代码thr = threading.Thread(target=self.SaveVideo)thr.start()#下面为同步代码# fpsize = os.path.getsize(self.fileInputPath) / 1024# if fpsize >= 150.0:  # 大于150KB的视频需要压缩#     compress = "ffmpeg -i {} -r 10 -pix_fmt yuv420p -vcodec libx264 -preset veryslow -profile:v baseline  -crf 23 -acodec aac -b:a 32k -strict -5 {}".format(#         self.fileInputPath, self.fileOutPath)#     isRun = os.system(compress)#     if isRun != 0:#         return (isRun, "没有安装ffmpeg")#     return True# else:#     return True

我这里使用了是ffmpeg对视频进行压缩,这个是一个非常好用的工具,Linux和windows都有,在Linux中可以使用apt install ffmpeg进行安装(我用的是Ubuntu的系统,所以使用apt进行安装,如果用的是Centos的用对应的yum进行安装就行了)

ffmpeg命令解释

ffmpeg -i 1.mp4 -r 10 -pix_fmt yuv420p -vcodec libx264 -preset veryslow -profile:v baseline  -crf 23 -acodec aac -b:a 32k -strict -5 147fss.mp4
  • -i 输入的视频文件
  • -r 每一秒的帧数,一秒10帧大概就是人眼的速度
  • -pix_fmt 设置视频颜色空间 yuv420p网络传输用的颜色空间 ffmpeg -pix_fmts可以查看有哪些颜色空间选择
  • -vcodec 软件编码器,libx264通用稳定
  • -preset 编码机预设 编码机预设越高占用CPU越大 有十个参数可选 ultrafast superfast veryfast(录制视频选用) faster fast medium(默认) slow slower veryslow(压制视频时一般选用) pacebo
  • -profile:v 压缩比的配置 越往左边压缩的越厉害,体积越小 baseline(实时通信领域一般选用,画面损失越大) Extended Main(流媒体选用) High(超清视频) High 10 High 4:2:2 High 4:4:4(Predictive)
  • -level:v 对编码机的规范和限制针对不通的使用场景来操作,也就是不同分辨率设置不同的值(这个我没有设置,因为这个要根据不同的分辨率进行设置的,具体要去官方文档查看)
  • -crf 码率控制模式 用于对画面有要求,对文件大小无关紧要的场景 0-51都可以选择 0为无损 一般设置18 - 28之间 大于28画面损失严重
  • -acodec 设置音频编码器

完整代码

import sys
import os
import zlib
import threading
import platform
from PIL import Imageclass Compress_Pic_or_Video(object):def __init__(self,filePath,inputName,outName=""):self.filePath = filePath  #文件地址self.inputName = inputName  #输入的文件名字self.outName = outName  #输出的文件名字self.system_ = platform.platform().split("-",1)[0]if  self.system_ ==  "Windows":self.filePath = (self.filePath + "\\") if self.filePath.rsplit("\\",1)[-1] else self.filePathelif self.system_ == "Linux":self.filePath = (self.filePath + "/") if self.filePath.rsplit("/",1)[-1] else self.filePathself.fileInputPath = self.filePath + inputNameself.fileOutPath = self.filePath + outName@propertydef is_picture(self):picSuffixSet = {"BMP","GIF","JPEG","TIFF","PNG","SVG","PCX","WMF","EMF","LIC","EPS","TGA","JPG"}suffix = self.fileInputPath.rsplit(".",1)[-1].upper()if suffix in picSuffixSet:return Trueelse:return False@propertydef is_video(self):videoSuffixSet = {"WMV","ASF","ASX","RM","RMVB","MP4","3GP","MOV","M4V","AVI","DAT","MKV","FIV","VOB"}suffix = self.fileInputPath.rsplit(".",1)[-1].upper()if suffix in videoSuffixSet:return Trueelse:return Falsedef SavePic(self):fpsize = os.path.getsize(self.fileInputPath) / 1024  # 获得图片多少K   os.path.getsize(self.picPath)返回的是字节if fpsize >= 50.0:  # 是否大于50Kim = Image.open(self.fileInputPath)  # 打开图片imBytes = im.tobytes()  # 把图片转换成bytes流imBytes = zlib.compress(imBytes, 5)  # 对图像字节串进行压缩im2 = Image.frombytes('RGB', im.size, zlib.decompress(imBytes))  # 压缩成新的图片if self.outName:im2.save(self.fileOutPath)  #不覆盖原图return (self.fileOutPath,os.path.getsize(self.fileOutPath))else:im2.save(self.fileInputPath)    #覆盖原图return (self.fileInputPath,os.path.getsize(self.fileInputPath))else:return Truedef SaveVideo(self):fpsize = os.path.getsize(self.fileInputPath) / 1024if fpsize >= 150.0: #大于150KB的视频需要压缩if self.outName:compress = "ffmpeg -i {} -r 10 -pix_fmt yuv420p -vcodec libx264 -preset veryslow -profile:v baseline  -crf 23 -acodec aac -b:a 32k -strict -5 {}".format(self.fileInputPath,self.fileOutPath)isRun = os.system(compress)else:compress = "ffmpeg -i {} -r 10 -pix_fmt yuv420p -vcodec libx264 -preset veryslow -profile:v baseline  -crf 23 -acodec aac -b:a 32k -strict -5 {}".format(self.fileInputPath, self.fileInputPath)isRun = os.system(compress)if isRun != 0:return (isRun,"没有安装ffmpeg")return Trueelse:return Truedef Compress_Picture(self):#异步保存打开下面的代码,注释同步保存的代码thr = threading.Thread(target=self.SavePic)thr.start()#下面为同步保存# fpsize = os.path.getsize(self.fileInputPath) / 1024  # 获得图片多少K   os.path.getsize(self.picPath)返回的是字节# if fpsize >= 50.0:  # 是否大于50K#     im = Image.open(self.fileInputPath)  # 打开图片#     imBytes = im.tobytes()  # 把图片转换成bytes流#     imBytes = zlib.compress(imBytes, 5)  # 对图像字节串进行压缩#     im2 = Image.frombytes('RGB', im.size, zlib.decompress(imBytes))  # 压缩成新的图片#     if self.outName:#         im2.save(self.fileOutPath)  # 不覆盖原图#         return (self.fileOutPath, os.path.getsize(self.fileOutPath) / 1024)#     else:#         im2.save(self.fileInputPath)  # 覆盖原图#         return (self.fileInputPath, os.path.getsize(self.fileInputPath) / 1024)# else:#     return Truedef Compress_Video(self):# 异步保存打开下面的代码,注释同步保存的代码thr = threading.Thread(target=self.SaveVideo)thr.start()#下面为同步代码# fpsize = os.path.getsize(self.fileInputPath) / 1024# if fpsize >= 150.0:  # 大于150KB的视频需要压缩#     compress = "ffmpeg -i {} -r 10 -pix_fmt yuv420p -vcodec libx264 -preset veryslow -profile:v baseline  -crf 23 -acodec aac -b:a 32k -strict -5 {}".format(#         self.fileInputPath, self.fileOutPath)#     isRun = os.system(compress)#     if isRun != 0:#         return (isRun, "没有安装ffmpeg")#     return True# else:#     return Trueif __name__ == "__main__":b = sys.argv[1:]	#测试压缩savepic = Compress_Pic_or_Video(b[0],b[1],b[2])print(savepic.Compress_Picture())

测试情况

对图片进行压缩

在这里插入图片描述

在这里插入图片描述

左边为没压缩过的原图,右边是压缩过后的原图,两张图片像素都是一样的,两张图片用肉眼几乎分辨不出差别

对视频进行压缩

在这里插入图片描述

在这里插入图片描述

左边为未压缩过的原视频文件,右边为压缩过的视频文件,可见帧宽度与帧高度都没发生过改变,只是修改了数据速率,总比特率等的这些信息,源文件帧速率为每秒12帧,现在压缩成了每秒10帧,人眼是没办法分别出12帧与10帧的区别的,我测试过原视频和压缩后的视频观看上是没有却别的,声轨也听不出。

参考的文章

https://blog.csdn.net/oh5W6HinUg43JvRhhB/article/details/80850839

http://ffmpeg.org/documentation.html


http://chatgpt.dhexx.cn/article/4uD1niTZ.shtml

相关文章

7款最好用的图片无损,视频无损压缩软件

第一:QVE视频压缩软件 下载地址:http://www.qvevideo.com/compress 非常实用的视频,图片两用压缩软件,能够将各种视频压缩成mp4,flv等格式, 缩减视频体积,释放磁盘空间,节省网络带宽,压缩后能够保持视频高清晰度,压缩率高达90%以上。 1,首先打开软件,切换到【图片压缩】…

苹果手机解压缩软件_照片压缩软件哪款好用?推荐5款好用的图片压缩软件

在我们办公的时候,总会遇到各种各样的问题,就比如PDF与文档之间的转换,图片的压缩,文档加密的方法等等,这些都是上班族经常需要处理的问题,特别是图片压缩,很多人都想知道照片压缩软件哪款好&am…

分享一个好用的图片压缩软件

为了性能优化需要,一般需要优化网站上的图片,减少大小。但问题来了,很多压缩软件是有损压缩,压缩后图片质量惨不忍睹。 下面我分享一下刚刚了解到的图片压缩软件,名字叫智图。 官网地址是: http://zhitu.is…

无损对图片进行压缩软件Caesium使用方法及下载

无损对图片进行压缩,除了用PS外,还有一款小白也可以用的软件Caesium。 使用方法如下: 1、打开文件夹,双击Caesium.exe 2、弹出的界面如下 3、点击左上角红色方框打开文件5837014_0_0.jpg,压缩选项的品质任意修改&…

开源免费的图片压缩软件,从50M到50K,极力安利

我相信大家在生活中肯定每日都离不开图片的处理了,比如:考试报名、图片传送、网页图片上传的过程中,都或多或少遇到过“您上传的图片太大”的问题 每次遇到这种情况是真的有点心塞,所以今天特别给大家带来一款人人必备的实用、超好…

如何压缩图片200k以下?

“图片过大无法上传”,“因您上传的图片大小超过限制”这样的提示大家都有遇到过吧?这就是告诉我们现在的图片需要压缩一下才能继续使用了,否则我们就无法使用当前照片了。 那有很多平台,特别是上传一些证件照的时候,要…

怎么压缩图片200k以下?

怎么压缩图片200k以下?有很多小伙伴好奇,为什么别人能将图片压缩到200k以下,而自己却做不到呢!原因很简单,那是因为他们都用好用的压缩软件来压缩。今天小编也为大家分享一个轻松将图片压缩到200k以下的方法给你。 我们…

「精品」无损批量压缩图片工具 - Caesium Image Compressor

每天分享一点小知识,积少成多。今天分享的是一款图片无损压缩工具!最近在做网站的备案,上次的图片要求不能大于9M,无奈只能压缩图片了,今天对比了几款图片压缩工具,最终得出Caesium Image Compressor款工具…

Mac好用的图片压缩软件——JPG Compress 2 for Mac

不仅是低头码字的作者,摄影师、设计师、画家,以及其他想分享图片内容的人,遇到图片过大无法上传、 加载太慢的情况,该怎么办呢?很简单,给你的图片减减肥这个问题就迎刃而解了。 那么mac图片压缩软件有哪些呢?今天就给大家带来了一些MAC图片压缩神器,来帮您的图片瘦身减…

图片压缩软件有哪些?分享三个好用的图片压缩软件

图片压缩软件有哪些是比较好用的呢?现如今图片拍出来越来越清晰,它的内容自然也就更大,遇到上传图片时,往往都会因为图片内存过大而上传不了,因此我们想要了解一些好用的图片压缩软件,今天给大家分享三种压…

8个免费图片/照片压缩工具帮您降低存储空间

继续查看一些最好的图像压缩工具,以提升用户体验和存储空间以及网站使用支持。 无数图像压缩工具的存在指向一个单一的结论——图像优化至关重要,不应被忽视。 简而言之,图像优化可以对页面加载速度产生奇迹,改善各方面优化。 …

什么软件可以压缩图片大小?这几个软件值得收藏

不知道小伙伴们平时有没有遇到这种情况,在发布图片动态的时候,平台会提示说该图片体积过大,无法上传的情况。通常遇到这种情况,我们如果还想继续发布这张图片,就要对图片进行压缩了。那免费压缩图片的软件哪个好呢&…

LKM:Linux Kernel Map(图解Linux内核)

https://makelinux.github.io/kernel/map/ 《Anatomy of the Linux kernel- linux内核剖析》 《Linux Kernel Map之协议栈概述(1)》

Linux:从min宏开始入手LKM

目录 引言第一版的“疯狂”之处__LINE__的弊端最新版本\_\_PASTE和\_\_\_PASTE 自定义LKM问题锦集/usr/src/下为空无法进入到对应目录,原因比较简单:/bin/sh: 1: flex: not foundConfiguration file ".config" not found!The present kernel c…

MKLink 命令的使用

之前提到帮助一位网友清理C盘的时候,发现他的 iTunes 备份文件夹非常大,于是用 mklink 命令把 iTunes 备份文件夹转移到了 D 盘。 于是我觉得 mklink 这个命令值得好好研究一下,所以我把我研究验证的在 Windows 10 下的 mklink 命令的使用教…

Linux Rootkit 系列一:LKM的基础编写及隐藏

对于这个系列文章,我的规划如下:这一系列文章的重点集中在介绍linux rootkit中最讨论最多也是最受欢迎的一种:loadable kernel module rootkit(LKM rootkit)。 首先介绍最基础的lkm模块的编写与加载以及如何让lsmod命令无法发现我们的模块&a…

linux lkm rootkit reptile项目介绍

目录 简介 Reptile的使用 Reptile原理分析 kmatryoshka 代码分析 驻留 简介 Reptile是github上一个很火的linux lkm rootkit,最近学习了一些linux rootkit的内容,在这里记录一下。 主要是分析reptile的实现 Reptile的使用 安装命令&#xff1a…

LKM入门实例

1.LKM概述: LKM:可加载内核模块,是一段运行在内核空间的代码,可以动态加载,无须重新实现整个 内核。 2.相关操作: ①加载内核模块:insmod ②卸载内核模块:rmmod ③查看内核模块:lsm…

ENVI: 如何进行图像的自动配准?

目录 0 1 理论 0 2 实操 2.1 加载图像 2.2 两幅图像的重影效果展示 2.3 搜寻并点击 图像几何校正工作流程 工具 2.4 选择基准图像和待配准图像 2.5 自动生成Tie点(连接点)的参数设置 2.6 检查连接点和校正参数 2.6.1 对误差较大的Tie点进行删除…

ENVI实现归一化建筑物指数(NDBI)实验操作

这是提出NDBI的那个人的文章,有兴趣的可以下载下来看 这是他的技术路线图,他有做了验证,我们这里只是实现,不做验证。 这是NDBI方法的公式:我们这里用L8 OLI数据做实验,也就是对应的MIR是第6波段&#xf…