android技术专栏CodeEaseTools

Convert Gif To Video?

2017-10-11  本文已影响124人  TryEnough

GIF替代方案

维基百科的解释
Video alternative to GIF
已经提出来的替代gif的方案中,通常是用 HTML5 Video,其优点是:
- 可以使文件更小
- 支持超过8-bit 颜色限制
- 通过编解码器实现更好的帧处理和压缩
- HTML5规范中的视频元素的引入,以及H.264和WebM视频文件格式,允许更广泛、更容易的支持和实现视频。

上面提到的webm是一种对gif的替代方案,除了这个还有例如gfycat方案。下面解释一下这两种替代方案的详情:
对比Gfycat和gif效果

Gfycat是GIF主机有三个独特的优势:

其他优点:

Gfycat SDK for Android

Gfycat SDK

api


GIF替代案例

源码查看

发现一个以 .mp4结尾的链接

真实的文件是mp4格式

2、gfycat

gfycat例子

...
网上都在疯转,这是为什么呢?

问题:

有人说是体积和播放控制,真是这样么?

接下来我们自己实际操作看一下

使用工具:


实践出真知:同样的gif用ffmpeg转换比网页转换工具后体积更小。

//命令
ffmpeg -f gif -i animation.gif animation.mp4
//可以选择输出格式:
ffmpeg -f gif -i animation.gif animation.mpeg
ffmpeg -f gif -i animation.gif animation.webm

GIF


gif 的版本号和署名在前6个字节



我们可以在三方库的源码中得到验证(GifHeaderParser.java):

/**
   * Reads GIF file header information.
   */
  private void readHeader() {
    String id = "";
    for (int i = 0; i < 6; i++) {
      id += (char) read();
    }
    if (!id.startsWith("GIF")) {
      header.status = STATUS_FORMAT_ERROR;
      return;
    }
    readLSD();
    if (header.gctFlag && !err()) {
      header.gct = readColorTable(header.gctSize);
      header.bgColor = header.gct[header.bgIndex];
    }
  }
逻辑屏幕标识符

Packet里是调色盘信息,分别来看:

这四个字段一起定义了调色盘的信息。

Background color Index 定义了图像透明区域的背景色在调色盘里的索引。
Pixel Aspect Ratio 定义了像素宽高比,一般为0。

从gif的二进制格式中验证上面说的两点:

gif二进制例子

我们尝试改变自己的gif调色盘的大小,进行重压缩,看看会发生什么:

gifsicle --colors=32 zijizuode.gif > zijizuode-32.gif
gifsicle --colors=16 zijizuode.gif > zijizuode-16.gif
gifsicle --colors=2 zijizuode.gif > zijizuode-2.gif
...

结论是:如果可以接受牺牲图像的部分视觉效果,就可以通过减色来对图像做进一步压缩

参考:
庖丁解牛:GIF
https://www.qcloud.com/community/article/946621001490345387
http://www.jianshu.com/p/38743ef278ac
https://github.com/bumptech/glide
gifsicle

每一色光以8位元表示,每个通道各有256(28)种阶调,三色光交互增减,RGB三色光能在一个像素上最高显示1677万种色(256256256=16,777,216),这个数值就是电脑所能表示的最高色彩。普遍认为人眼对色彩的分辨能力大致是一千万色,因此由RGB形成的图像均称做真彩色



目前较为理想的视频格式是什么?


服务端GIF转换视频技术实现方式:

>>> import ffmpy
>>> ff = ffmpy.FFmpeg(
...     inputs={'input.gif': None},
...     outputs={'output.mp4': None}
... )
>>> ff.run()
import moviepy.editor as mp
clip = mp.VideoFileClip("mygif.gif")
clip.write_videofile("myvideo.mp4")

H.264

h.264是一种视频的编码方式,它的出现提高了视频的压缩比和网络亲和力。先简单了解一下它是如何进行视频压缩的。视频压缩目的是减少和去除冗余视频数据

h.264分层结构

H.264 的功能分为两层

一个视频其实是像gif一样,由很多张的图片组成,但是H.264的原始码流(又称为裸流),却是由一个接一个NALU组成的,如下图:



那么视频中的图片是如何跟NALU关联的呢?

一帧图片跟 NALU 的关联 :

一帧图片经过 H.264 编码器之后,就被编码为一个或多个片(slice),而装载着这些片(slice)的载体,就是 NALU

片(slice),是 H.264 中提出的新概念,是通过编码图片后切分通过高效的方式整合出来的概念,一张图片至少有一个或多个片(slice),片的结构:

视频包涵图片,图片包涵片,片包涵宏块,宏块就是存储像素数据的地方。

宏块的解释:
  • 宏块是视频信息的主要承载者,因为它包含着每一个像素的亮度和色度信息。视频解码最主要的工作则是提供高效的方式从码流中获得宏块中的像素阵列。
  • 组成部分:一个宏块由一个16×16亮度像素和附加的一个8×8 Cb和一个 8×8 Cr 彩色像素块组成。每个图象中,若干宏块被排列成片的形式。
切片和宏块的关系:

整体结构


综上所述,数据可以抽象成这样:



或者这样:


问题:

知道了h264以这样的方式组织数据,那么怎么就能压缩呢?或者说为什么这样做呢?

看完上面的一大堆应该还是一头雾水,先让我们看看它减少数据量的基本方法,此处可以回忆一下gif的压缩实现。。。

减少数据量的基本方法

在一系列的帧内,可以通过差分编码这样的方法来减少视频数据量,包括H.264在内的大多数视频压缩标准都采用这种方法。在差分编码中,会将一个帧与参考帧(即前面的I帧或P帧)进行对比,然后只对那些相对于参考帧来说发生了变化的像素进行编码。通过这种方法,可以降低需要进行编码和发送的像素值。

三个图像分别作为独立的图像(I帧)进行编码和发送

结论:经过对比gif和h264的压缩,gif中会将重复出现的序列用相同的符号表示,但是在h264中相同的序列直接不发送,而是通过帧间预测,所以h264的压缩效率更高。

参考:
新一代视频压缩编码标准
H.264视频压缩标准
深入浅出理解视频编码H264结构
H.264码流以及H.264编解码的基本概念
深度解析H.264编码原理
雷霄骅(leixiaohua1020)的专栏

作者才疏学浅,欢迎大牛吐槽。

上一篇 下一篇

猜你喜欢

热点阅读