使用ffmpeg进行webp图片压缩,ffmpeg的帮助信息查看方法

使用ffmpeg进行webp图片压缩,ffmpeg的帮助信息查看方法

01.ffmpeg中帮助信息的查看

? ffmpeg继承了很多编解码器,使用ffmpeg很多时候需要了解这些编解码器的参数。

? 最近在看小泉同学的bd,去网络上搜寻op的cd资源的时候,下载下来发现一张扫图有80mb大小。音乐本身是hires压制的flac,大小是qq音乐上无损flac的3倍。一首歌占100mb的空间,这应该是hires的音乐的正常大小了。

? 因为hi-res是96kHz是通常采样的两倍,采样位数也更高,通常的cd音质是 44.1kHz 16bit的音源,而hi-res通常是 96kHz 24bit,如果音源一样的话 应该大约是 (96/44.1) * (24/16)=3.27倍大小。这是算是验证了,一般一首正常长度的歌,一般的flac是30多mb,而hi-res 是100mb左右。

? 但是扫图的大小感觉过大了,图像的分辨率是7623*3763,已经超过屏幕的大小,主要是cd封面大小的一张图占用80mb实在是浪费,于是想用目前流行webp格式进行压缩。

? 执行ffmpeg.exe -i .1.png out.webp

? 给定后缀名,ffmpeg会自动寻找编码器进行处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
ffmpeg.exe -i .1.png  out.webp
ffmpeg version N-93851-gdcc999819d Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8.3.1 (GCC) 20190414
  configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt
  libavutil      56. 27.100 / 56. 27.100
  libavcodec     58. 52.101 / 58. 52.101
  libavformat    58. 27.103 / 58. 27.103
  libavdevice    58.  7.100 / 58.  7.100
  libavfilter     7. 51.100 /  7. 51.100
  libswscale      5.  4.101 /  5.  4.101
  libswresample   3.  4.100 /  3.  4.100
  libpostproc    55.  4.100 / 55.  4.100
[png_pipe @ 000001b495fa8f40] Stream #0: not enough frames to estimate rate; consider increasing probesize
Input #0, png_pipe, from '.1.png':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: png, rgb24(pc), 7623x3763 [SAR 31496:31496 DAR 7623:3763], 25 tbr, 25 tbn, 25 tbc
Stream mapping:
  Stream #0:0 -> #0:0 (png (native) -> webp (libwebp))
Press [q] to stop, [?] for help
Output #0, webp, to 'out.webp':
  Metadata:
    encoder         : Lavf58.27.103
    Stream #0:0: Video: webp (libwebp), bgra, 7623x3763 [SAR 1:1 DAR 7623:3763], q=2-31, 200 kb/s, 25 fps, 1k tbn, 25 tbc
    Metadata:
      encoder         : Lavc58.52.101 libwebp
[libwebp @ 000001b495fbcdc0] Using libwebp for RGB-to-YUV conversion. You may want to consider passing in YUV instead for lossy encoding.
frame=    1 fps=0.1 q=-0.0 Lsize=    9820kB time=00:00:00.00 bitrate=80448240.0kbits/s speed=7.85e-05x
video:9820kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%

看到这一行, Stream #0:0 -> #0:0 (png (native) -> webp (libwebp)),ffmpeg使用了一个libwebp的编码器进行压缩。

所以这里我们就要查一下libwebp这个编码器具体有哪些参数。

?

下面是ffmpeg查看帮助文档的方法

基础的帮助 选中的项目的帮助
ffmpeg -? or ffmpeg -h ffmpeg -h decoder=decoder_name
额外的帮助/扩展的帮助 ffmpeg -h encoder=encoder_name
ffmpeg -h long or ffmpeg -h full ffmpeg -h demuxer=demuxer_name
ffmpeg –? topic or ffmpeg -h topic ffmpeg -h muxer=muxer_name

这里我们执行以下命令即可

ffmpeg -h encoder=libwebp

02.libwebp的使用

查看libwebp的帮助如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
ffmpeg -h encoder=libwebp
ffmpeg version N-93851-gdcc999819d Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8.3.1 (GCC) 20190414
  configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt
  libavutil      56. 27.100 / 56. 27.100
  libavcodec     58. 52.101 / 58. 52.101
  libavformat    58. 27.103 / 58. 27.103
  libavdevice    58.  7.100 / 58.  7.100
  libavfilter     7. 51.100 /  7. 51.100
  libswscale      5.  4.101 /  5.  4.101
  libswresample   3.  4.100 /  3.  4.100
  libpostproc    55.  4.100 / 55.  4.100
Encoder libwebp [libwebp WebP image]:
    General capabilities: none
    Threading capabilities: none
    Supported pixel formats: bgra yuv420p yuva420p
libwebp AVOptions:
  -lossless          <int>        E..V..... Use lossless mode (from 0 to 1) (default 0)
  -preset            <int>        E..V..... Configuration preset (from -1 to 5) (default none)
     none                         E..V..... do not use a preset
     default                      E..V..... default preset
     picture                      E..V..... digital picture, like portrait, inner shot
     photo                        E..V..... outdoor photograph, with natural lighting
     drawing                      E..V..... hand or line drawing, with high-contrast details
     icon                         E..V..... small-sized colorful images
     text                         E..V..... text-like
  -cr_threshold      <int>        E..V..... Conditional replenishment threshold (from 0 to INT_MAX) (default 0)
  -cr_size           <int>        E..V..... Conditional replenishment block size (from 0 to 256) (default 16)
  -quality           <float>      E..V..... Quality (from 0 to 100) (default 75)

我们发现有以下的选项

-lossless 是设置无损压缩

-preset 是几个预设的参数

-quality 这个就是主要的参数了,控制压缩率

-cr_size 这个参数试了一下 200和16各压了一遍,没看出什么区别,大小也一样

不设置参数默认压制出来 的图片 80mb 变成10mb左右,这已经是接近无损的质量了。

测试了一下 quality 0的时候也有500多kb大小,但是图片就有点糊了。

去网上查了一下libwebp参数的具体设置,有人得出了下面的结论
https://www.cnblogs.com/yanguhung/p/10784598.html

1
2
3
4
5
6
7
8
9
选择无损压缩时,“-lossless -q 100” 是最佳方案,注意:cwebp 仅仅对png格式的图片使用无损压缩时,会有较为高效的压缩率和图片质量

选择有损压缩时,“-q 75”是最佳方案(图片质量与体积大小达到均衡)建议其他格式图片使用有损压缩

无论何种压缩参数,加上“-m 6”都能使得输出的 WebP 图片进一步减少体积,量级是1%~2%,但是会增加耗时

非png格式的图片选择无损压缩时,“-lossless -q 100” 时编码时间长,图片质量反而极高可能变大,编码时间时间很长,cpu使用率飙升跑满,不建议使用

建议选择有损压缩时,“-q 75”是最佳方案(图片质量与体积大小达到均衡)建议使用

还有webp 和jpg的对比

1
即使jpg图片同比例压缩为jpg和webp图片 webp图片也要比jpg图片质量低百分之10~20之间

也就是说,webp的压缩率完全优于jpg,但是webp的编码时间比jpg长8倍。

所以说我们使用的时候按照默认参数来就行了。

调整图片大小用-vf scale=iw/3:ih/3,可以指定和原来的比例,也可以指定明确的像素值比如1280:720.

单纯调整图片大小,无损压缩把图片宽高缩小3倍iw/3:ih/3,大小就只有5mb了。

但是这里不缩小大小,只压缩,所以按照默认参数就行。

1
ffmpeg.exe -i input.png  -vf scale=iw:ih -codec libwebp -lossless 0 -quality 75 out.webp

编写一个压缩指定大小png图片的powershell脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<#
.synopsis
批量转换占用空间过大的图片
.example

使用方法如下
allPngtoWebp.ps1 -limitSize 10mb -paramStr '-codec libwebp -vf scale=iw/4:ih/4 -lossless 1 -quality 100'


#>
param(
# 需要压缩的图片阈值大小,小于这个数值的图片不进行压缩
[int]$limitSize=10mb,
[string]$paramStr='-vf scale=iw:ih -codec libwebp -lossless 0 -quality 75'
)

#只压缩png格式的图片,先检索目录下的png图片
$count=0
Get-ChildItem -Recurse *.png | foreach{
if($_.Length -gt $limitSize){
     Write-Host -ForegroundColor Green "detect large png picture : $($_.FullName) size:$($_.Length/1mb) "
     
     $newfullname=$_.FullName.Substring(0,$_.FullName.Length-4)+'.webp'
     Invoke-Expression "ffmpeg.exe -i '$($_.FullName)'  $paramStr  '$($newfullname)'"
    # ffmpeg.exe -i $_.FullName  $paramStr  ($_.FullName.Substring(0,$_.FullName.Length-4)+'.webp')

    if (Test-Path -Path $newfullname){
        rm $_.FullName
     Write-Host -ForegroundColor yellow "delete $($_.FullName) complete "
     $count++
     }
     else{
        Write-Host -ForegroundColor red "convert failed "
        break
     }
    }
}

Write-Host -ForegroundColor  Green   "compress $count  png files  complete"