2021-09-04 视频封面挑优及图片压缩格式优化 gocv -dlian

项目场景:

app里帖子展示时会首先加载一个图片/视频的缩略图,在高清图片/视频加载完毕,再去替换。目前线上视频缩率图模糊。所以本次项目希望提升视频缩略图清晰度,同时借此机会对图片大小进行压缩,降低带宽成本,减少用户流量损耗。
1、图片jpg转webp格式(结论:平均图片大小压缩率能达到50%)
2、使用ffmpeg选取前2秒60帧挑优作为封面(如果希望减少缩略图和视频起始的差距,可以选取0.5秒内的帧)

环境准备:

1、opencv 4.5.4 用于计算图片的相关指标(查看版本pkg-config --modversion opencv
2、ffmpeg
3、imagemagick 7.0.10-23 用户图片格式转换,需要支持webp、png、jpg以及xml(支持http图片url)。
Delegates (built-in): bzlib fontconfig freetype jng jpeg lzma png webp x xml zlib
5、go 1.16.6
4、gocv 0.28.0

名词:

1、Laplacian 拉普拉斯矩阵,图论。

图片压缩格式优化

  • webp:webp为网络图片提供了无损和有损压缩能力,同时在有损条件下支持透明通道。据官方实验显示:无损WebP相比PNG减少26%大小;有损WebP在相同的SSIM(Structural Similarity Index,结构相似性)下相比JPEG减少25%~34%的大小;有损WebP也支持透明通道,大小通常约为对应PNG的1/3。
  • heif:HVEC或H.265视频格式的静态图像版本。HEIF图像比JPEG格式的相同图片小50%。
  • avif:下一代技术。一种来源于AV1的图像格式,其中AV1是一种视频压缩技术。具有较高的压缩能力,相比于JPEG格式有着10倍以上的进步。

通过视频抽帧获取无损图片(png格式)。转码有损格式:jpeg、webp、heif、avif。在尽量少损害图片质量的前提下,尽量减低图片大小。通过比对DSSIM,获取最佳质量数值。DSSIM值越小,越趋近原图。
实验一:相同quality,对比图片大小

格式 工具 quality 大小占比 DSSIM
jpeg imagemagick 70 19.18% 0.0055
webp imagemagick 70 10.24% 0.0072
heif imagemagick 70 15.17% 0.0031
avif imagemagick 70 6.20% 0.0075

结论:quality相同,不同格式的图片质量不同。
实验二:获取合适quality

格式 工具 quality 大小占比 DSSIM
ffmepg_jpeg ffmpeg 2 [2-31] 25.92% 0.0055
jpeg imagemagick 70 [0-100] 19.18% 0.0072
webp imagemagick 70 [0-100] 10.24% 0.0078
heif imagemagick 40 [0-100] 684.% 0.0071
avif imagemagick 60 [0-100] 5.59% 0.0080
magick a.png -quality 70 a.jpg
magick url图片 -quality 70 a.webp

视频缩略图优化

印尼用户上传视频质量不佳,原始抽取视频首帧作为视频缩略图方案存在瓶颈,存在首帧模糊、黑屏等问题,导致缩略图质量差,不能正向引导用户查看视频。
方案:
使用无参考图像清晰度评估方案,对视频2s内图像序列(取前50帧图像)基于Laplacian梯度函数做图像清晰度预估。

Golang实现

package main

import (
	"errors"
	"fmt"
	"gocv.io/x/gocv"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

var TmpFileDir = "test"

func main() {
   
	fmt.Println("shotframev2")
	ShotFrameV2("https://tenfei01.cfp.cn/creative/vcg/800/version21/VCG21gic20080842.jpg")
}

func ShotFrameV2(desFile string) (frameFilepath string, err error) {
   
	tmpFile := TmpFileDir
	fpre := fmt.Sprintf("%d-framev2", 1)
	outFilepath := filepath.Join(tmpFile, fmt.Sprintf("%s-%s.png", fpre, "%d"))
	frameFilepaths := filepath.Join(tmpFile, fmt.Sprintf("%s-%s.png", fpre, "*"))

	frames := 60
	// 前2s取60帧
	args := []string{
   
		"-i", desFile,
		"-threads", "1",
		"-ss", "00:00:00.000", // 开始位置
		"-t", "2", // 截取视频长
		"-vframes", strconv.FormatInt(int64(frames), 10), // 取60帧
		"-f", "image2",
		outFilepath,
	}
	cmd := exec.Command("ffmpeg", args...)
	err = cmd.Run()
	if err != nil {
   
		fmt.Printf("failed to ShotFrameV2, cmd: %s, err: %s\n", strings.Join(args, " "), err.Error())
		return
	}

	preFrame := ""
	indexLapMap := make(map[int]float64) // 每个下表的lap值
	diffIndexs := make([]int, 0)         //每个不同的第一个diff下标
	for i := 1; i <= frames; i++ {
   
		frame := filepath.Join(tmpFile, fmt.Sprintf("%s-%d.png", fpre, i))
		if has, _ := PathExists(frame); !has {
   
			break
		}
		if i == 1 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dlian丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值