python图片和视频的压缩

windows环境

安装ffmpeg

1.下载ffmpeg,并且解压文件

https://github.com/BtbN/FFmpeg-Builds/releases

2.环境变量的配置

在这里插入图片描述
变量目录:../ffmpwg/bin;

3.cmd

cmd

安装Image包

pip install image

python代码(第一种sys.argv传参)


# 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  软件编码器,通用稳定
# -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

from PIL import Image
import os
import zlib
import threading
import platform


class ZipPictureOrVideo(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.filePath
        elif self.system_ == "Linux":
            self.filePath = (self.filePath + "/") if self.filePath.rsplit("/", 1)[-1] else self.filePath
        self.fileInputPath = self.filePath + inputName
        self.fileOutPath = self.filePath + outName

    @property
    def is_picture(self):
        """
        判断文件是否为图片
        :return:
        """
        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 True
        else:
            return False

    @property
    def is_video(self):
        """
        判断文件是否为视频
        :return:
        """
        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 True
        else:
            return False

    def compress_picture(self):
        """
        压缩图片
        :return:
        """
        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))
            else:
                im2.save(self.fileInputPath)  # 覆盖原图
                return (self.fileInputPath, os.path.getsize(self.fileInputPath))
        else:
            return True

    def compress_video(self):
        """
        压缩视频

        :return:
        """
        fpsize = os.path.getsize(self.fileInputPath) / 1024
        if 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,在Linux使用【apt install ffmpeg】安装,windows去【ffmpeg】官网下载")
            return True
        else:
            return True

    def start_compress_pic(self, is_async=True):
        """
        开始压缩图片
        :param is_async: 是否为异步压缩,默认为TRue
        :return:
        """
        if is_async:
            # 异步保存打开下面的代码,注释同步保存的代码
            thr = threading.Thread(target=self.compress_picture)
            thr.start()
        else:
            # 下面为同步保存
            self.compress_picture()

    def start_compress_video(self, is_async=True):
        """
        开始压缩视频
        :param is_async: 是否为异步压缩,默认为TRue
        :return:
        """
        if is_async:
            # 异步保存打开下面的代码,注释同步保存的代码
            thr = threading.Thread(target=self.compress_video)
            thr.start()
        else:
            # 下面为同步代码
            self.compress_video()


if __name__ == "__main__":
    # 输入文件路径
    args = sys.argv[1:]
    file = ZipPictureOrVideo(args[0], args[1], args[2])
    if file.is_picture:
        print(file.start_compress_pic())
    elif file.is_video:
        print(file.start_compress_video())
    else:
        print('该文件不是图片或者视频')
#传参方法
py x.py 文件地址 输入的文件名字(带后缀) 输出的文件名字(带后缀)

Python中 sys.argv[]的用法简明解释

是看书自学的python,开始后不久就遇到了这个引入的模块函数,且一直在IDLE上编辑了后运行,试图从结果发现它的用途,然而结果一直都是没结果,也在网上查了许多,但发现这个问题的比较详细的解释只有一个版本,大部分都是转载和复制的。给的都是简明python教程上那个一长串代码的例子,说看了就明白了,可我看得晕头转向的还是没真正明白,只知道“sys.argv[0]表示代码本身文件路径”这点,其实还是不明其意。后来经过大量努力,多方求教才真正明悟了,谨以记录和分享,希望能从另一个角度给同在求索过程中的同学一点启发。

sys.argv[]说白了就是一个从程序外部获取参数的桥梁,这个“外部”很关键,所以那些试图从代码来说明它作用的解释一直没看明白。因为我们从外部取得的参数可以是多个,所以获得的是一个列表(list),也就是说sys.argv其实可以看作是一个列表,所以才能用[]提取其中的元素。其第一个元素是程序本身,随后才依次是外部给予的参数。

下面我们通过一个极简单的test.py程序的运行结果来说明它的用法。


 1. #test.py  
 2. import sys  
 3. a=sys.argv[0] 
 4. print(a)

将test.py保存在c盘的根目录下。

在程序中找到 ‘运行’->点击->输入"cmd"->回车键 进入控制台命令窗口(如下图),先输入cd c:\ (作用是将命令路径改到c盘根目录),然后输入test.py运行我们刚刚写的程序:
在这里插入图片描述

得到的结果是C:\test.py,这就是0指代码(即此.py程序)本身的意思。

然后我们将代码中0改为1 :

a=sys.argv[1]

保存后,再从控制台窗口运行,这次我们加上一个参数,输入:test.py what
在这里插入图片描述

得到的结果就是我们输入的参数what,看到这里你是不是开始明白了呢。

那我们再把代码修改一下:

a=sys.argv[2:]

保存后,再从控制台窗台运行程序,这次多加几个参数,以空格隔开:

test.py a b c d e f
在这里插入图片描述

得到的结果为[‘b’, ’c’, ’d’, ’e’, ’f’]

应该大彻大悟了吧。Sys.argv[ ]其实就是一个列表,里边的项为用户输入的参数,关键就是要明白这参数是从程序外部输入的,而非代码本身的什么地方,要想看到它的效果就应该将程序保存了,从外部来运行程序并给出参数。

python代码(第二种input传参)

# 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  软件编码器,通用稳定
# -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

from PIL import Image
import os
import zlib
import threading
import platform


class ZipPictureOrVideo(object):
    """
    压缩图片、视频
    """
    def __init__(self):
    #def __init__(self, filePath, inputName, outName=""):
        #self.filePath = filePath  # 文件地址
        self.filePath=input("请入文件地址")
        #self.inputName = inputName  # 输入的文件名字
        self.inputName=input("请入文件名字")
        #self.outName = outName  # 输出的文件名字
        self.outName=input("请入输出的文件名字")
        self.system_ = platform.platform().split("-", 1)[0]
        if self.system_ == "Windows":
            self.filePath = (self.filePath + "\\") if self.filePath.rsplit("\\", 1)[-1] else self.filePath
        elif self.system_ == "Linux":
            self.filePath = (self.filePath + "/") if self.filePath.rsplit("/", 1)[-1] else self.filePath
        self.fileInputPath = self.filePath + self.inputName
        self.fileOutPath = self.filePath + self.outName
        #self.fileInputPath = self.filePath + inputName
        #self.fileOutPath = self.filePath + outName

    @property
    def is_picture(self):
        """
        判断文件是否为图片
        :return:
        """
        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 True
        else:
            return False

    @property
    def is_video(self):
        """
        判断文件是否为视频
        :return:
        """
        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 True
        else:
            return False

    def compress_picture(self):
        """
        压缩图片
        :return:
        """
        print("压缩图片开始")
        fpsize = os.path.getsize(self.fileInputPath) / 1024  # 获得图片多少K   os.path.getsize(self.picPath)返回的是字节
        
        if fpsize >=40.0:  # 是否大于40K
            im = Image.open(self.fileInputPath)  # 打开图片
            width,height=im.size
            size = os.path.getsize(self.fileInputPath)
            #图像的等比压缩,可以注释不用
            while True:
                if size >=10.0: #控制压缩后的大小(KB)
                    print('等比压缩')
                    width,height=round(width*0.9),round(height*0.9)#去掉浮点,防报错
                    image=im.resize((width,height),Image.ANTIALIAS)
                    image.save(self.outName)
                    size=os.path.getsize(self.outName)/1024
                    print(size)
                else:
                    break
            im = Image.open(self.outName)
            self.inputName=self.outName
            #图像的等比压缩,可以注释不用
            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))
                print("输出图片")
            else:
                im2.save(self.fileInputPath)  # 覆盖原图
                return (self.fileInputPath, os.path.getsize(self.fileInputPath))
                print("输出图片")
        else:
            return True

    def compress_video(self):
        """
        压缩视频

        :return:
        """
        fpsize = os.path.getsize(self.fileInputPath) / 1024
        if 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,在Linux使用【apt install ffmpeg】安装,windows去【ffmpeg】官网下载")
            return True
        else:
            return True

    def start_compress_pic(self, is_async=True):
        """
        开始压缩图片
        :param is_async: 是否为异步压缩,默认为TRue
        :return:
        """
        if is_async:
            # 异步保存打开下面的代码,注释同步保存的代码
            thr = threading.Thread(target=self.compress_picture)
            thr.start()
        else:
            # 下面为同步保存
            self.compress_picture()

    def start_compress_video(self, is_async=True):
        """
        开始压缩视频
        :param is_async: 是否为异步压缩,默认为TRue
        :return:
        """
        if is_async:
            # 异步保存打开下面的代码,注释同步保存的代码
            thr = threading.Thread(target=self.compress_video)
            thr.start()
        else:
            # 下面为同步代码
            self.compress_video()


if __name__ == "__main__":
    # 输入文件路径
    #args = sys.argv[1:]
    #file = ZipPictureOrVideo(args[0], args[1], args[2])
    file = ZipPictureOrVideo()
    if file.is_picture:
        print(file.start_compress_pic())
    elif file.is_video:
        print(file.start_compress_video())
    else:
        print('该文件不是图片或者视频')

ffmpeg 基本用法

https://www.jianshu.com/p/3c8c4a892f3c

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值