Convert Gif To Video?


原文鏈接


GIF替代方案

維基百科的解釋
Video alternative to GIF
已經(jīng)提出來的替代gif的方案中,通常是用 HTML5 Video,其優(yōu)點(diǎn)是:
- 可以使文件更小
- 支持超過8-bit 顏色限制
- 通過編解碼器實(shí)現(xiàn)更好的幀處理和壓縮
- HTML5規(guī)范中的視頻元素的引入,以及H.264和WebM視頻文件格式,允許更廣泛、更容易的支持和實(shí)現(xiàn)視頻。

上面提到的webm是一種對(duì)gif的替代方案,除了這個(gè)還有例如gfycat方案。下面解釋一下這兩種替代方案的詳情:
  • Gfycat(fifty-cat)
    Gfy 代表“gif format yoker”,目的是通過提供 快速傳送控制選項(xiàng) 彌補(bǔ)gif和html5 video之間的差距,
對(duì)比Gfycat和gif效果

Gfycat是GIF主機(jī)有三個(gè)獨(dú)特的優(yōu)勢(shì):

  • 速度 : 傳統(tǒng)GIF平均速度提高10倍
  • 無限大小 : 大型GIF或視頻沒有問題
  • 功能 : 通過暫停,倒轉(zhuǎn),減速或加速分析逐幀分析

其他優(yōu)點(diǎn):

  • 鏈接。 我們生成的每個(gè)鏈接包括一個(gè)GIF文件。 即使通過視頻傳送,GIF始終在那里。 我們選擇瀏覽器可以查看的最佳格式,但作為用戶,您可以選擇僅查看GIF,或直接鏈接到GIF。
  • 全球CDN
  • 可擴(kuò)展的服務(wù)器系統(tǒng), 多層負(fù)載平衡和緩存,無單點(diǎn)故障。
  • RES集成! 如果您使用Reddit增強(qiáng)套件,您可以播放Gfycat,甚至不需要重新編輯。 只需點(diǎn)擊鏈接中的播放按鈕。

Gfycat SDK for Android

Gfycat SDK

api


GIF替代案例

  • Twitter將用戶上傳的GIF動(dòng)圖轉(zhuǎn)換成mp4格式
  • imgur將上傳到自己網(wǎng)站的所有g(shù)if轉(zhuǎn)換成video,并提供以.gifv 為擴(kuò)展名的真實(shí)文件(WebM);
  • Telegram將gif保存成video以后,同樣質(zhì)量的內(nèi)容節(jié)省95%的存儲(chǔ)空間。
  • 9gag
  • 看一看實(shí)情是怎樣的:
    例子:
    1、twitter
    twitter上的一個(gè)gif圖

    顯示gif的圖,我們看看實(shí)際上是什么:
源碼查看

發(fā)現(xiàn)一個(gè)以 .mp4結(jié)尾的鏈接

真實(shí)的文件是mp4格式

2、gfycat

gfycat例子

...
網(wǎng)上都在瘋轉(zhuǎn),這是為什么呢?

問題:

有人說是體積和播放控制,真是這樣么?

接下來我們自己實(shí)際操作看一下

使用工具:


實(shí)踐出真知:同樣的gif用ffmpeg轉(zhuǎn)換比網(wǎng)頁(yè)轉(zhuǎn)換工具后體積更小。

//命令
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存儲(chǔ)
    Gif以塊的形式存儲(chǔ)圖像信息,分別是
    • 控制塊(Control Block)
      • 文件頭信息:(GIF87a\GIF89a)占用6個(gè)字節(jié)
      • 邏輯屏幕描述塊
      • 圖像控制擴(kuò)充塊
      • 文件結(jié)尾塊
    • 圖像描述塊(Graphic Rendering Block)
      • 圖像描述塊
      • 全局調(diào)色板
      • 局部調(diào)色板
      • 圖像壓縮數(shù)據(jù)
      • 圖像說明擴(kuò)充塊
    • 特殊用途塊(Special Purpose Block)
      • 圖像注釋擴(kuò)充塊
      • 應(yīng)用程序擴(kuò)充塊



gif 的版本號(hào)和署名在前6個(gè)字節(jié)



我們可以在三方庫(kù)的源碼中得到驗(yàn)證(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];
    }
  }
邏輯屏幕標(biāo)識(shí)符

Packet里是調(diào)色盤信息,分別來看:

  • Global Color Table Flag為全局顏色表標(biāo)志,即為1時(shí)表明全局顏色表有定義。
  • Color Resolution 代表顏色表中每種基色位長(zhǎng)(需要+1),為111時(shí),每個(gè)顏色用8bit表示,即我們熟悉的RGB表示法,一個(gè)顏色三字節(jié)。
  • Sort Flag 表示是否對(duì)顏色表里的顏色進(jìn)行優(yōu)先度排序,把常用的排在前面,這個(gè)主要是為了適應(yīng)一些顏色解析度低的早期渲染器,現(xiàn)在已經(jīng)很少使用了。
  • Global Color Table 表示顏色表的長(zhǎng)度,計(jì)算規(guī)則是值+1作為2的冪,得到的數(shù)字就是顏色表的項(xiàng)數(shù),取最大值111時(shí),項(xiàng)數(shù)=256,也就是說GIF格式最多支持256色的位圖,再乘以Color Resolution算出的字節(jié)數(shù),就是調(diào)色盤的總長(zhǎng)度。

這四個(gè)字段一起定義了調(diào)色盤的信息。

Background color Index 定義了圖像透明區(qū)域的背景色在調(diào)色盤里的索引。
Pixel Aspect Ratio 定義了像素寬高比,一般為0。

從gif的二進(jìn)制格式中驗(yàn)證上面說的兩點(diǎn):

gif二進(jìn)制例子

我們嘗試改變自己的gif調(diào)色盤的大小,進(jìn)行重壓縮,看看會(huì)發(fā)生什么:

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

結(jié)論是:如果可以接受犧牲圖像的部分視覺效果,就可以通過減色來對(duì)圖像做進(jìn)一步壓縮

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

  • 256色


每一色光以8位元表示,每個(gè)通道各有256(28)種階調(diào),三色光交互增減,RGB三色光能在一個(gè)像素上最高顯示1677萬種色(256256256=16,777,216),這個(gè)數(shù)值就是電腦所能表示的最高色彩。普遍認(rèn)為人眼對(duì)色彩的分辨能力大致是一千萬色,因此由RGB形成的圖像均稱做真彩色


  • LZW 無損數(shù)據(jù)壓縮算法
    特點(diǎn):具有可逆推的邏輯程序
    算法:基本思路是,對(duì)于原始數(shù)據(jù),將每個(gè)第一次出現(xiàn)的串放在一個(gè)串表中,用索引來表示串,后續(xù)遇到同樣的串,簡(jiǎn)化為索引來存儲(chǔ)(串表壓縮法)。
    編碼:
    原始數(shù)據(jù)為aabcaac,其字符串編碼表為:

    解碼:
    解碼依據(jù)是將壓縮數(shù)據(jù)與原先字符串編碼表對(duì)照,并將對(duì)應(yīng)的字符放于一個(gè)暫存隊(duì)列中,依序?qū)嚎s數(shù)據(jù)讀入,若為重復(fù)數(shù)據(jù)保存于隊(duì)列中,若不為重復(fù)數(shù)據(jù),則擴(kuò)充一個(gè)新的碼置于字符串編碼表中。
    缺點(diǎn):
    那就是原始數(shù)據(jù)串最好是有大量的子串多次重復(fù)出現(xiàn),重復(fù)的越多,壓縮效果越好。反之則越差,可能真的不減反增了
    Gif壓縮算法詳解及實(shí)現(xiàn)

目前較為理想的視頻格式是什么?


服務(wù)端GIF轉(zhuǎn)換視頻技術(shù)實(shí)現(xiàn)方式:

  • python 腳本 movie2gif
  • python 中只用ffmpeg
>>> import ffmpy
>>> ff = ffmpy.FFmpeg(
...     inputs={'input.gif': None},
...     outputs={'output.mp4': None}
... )
>>> ff.run()
  • python 中使用MoviePy
import moviepy.editor as mp
clip = mp.VideoFileClip("mygif.gif")
clip.write_videofile("myvideo.mp4")

H.264

h.264是一種視頻的編碼方式,它的出現(xiàn)提高了視頻的壓縮比和網(wǎng)絡(luò)親和力。先簡(jiǎn)單了解一下它是如何進(jìn)行視頻壓縮的。視頻壓縮目的是減少和去除冗余視頻數(shù)據(jù)

h.264分層結(jié)構(gòu)

H.264 的功能分為兩層

  • 視頻編碼層(VCL, Video Coding Layer)
  • 網(wǎng)絡(luò)提取層(NAL, Network Abstraction Layer)。

一個(gè)視頻其實(shí)是像gif一樣,由很多張的圖片組成,但是H.264的原始碼流(又稱為裸流),卻是由一個(gè)接一個(gè)NALU組成的,如下圖:



那么視頻中的圖片是如何跟NALU關(guān)聯(lián)的呢?

一幀圖片跟 NALU 的關(guān)聯(lián) :

一幀圖片經(jīng)過 H.264 編碼器之后,就被編碼為一個(gè)或多個(gè)片(slice),而裝載著這些片(slice)的載體,就是 NALU

片(slice),是 H.264 中提出的新概念,是通過編碼圖片后切分通過高效的方式整合出來的概念,一張圖片至少有一個(gè)或多個(gè)片(slice),片的結(jié)構(gòu):

視頻包涵圖片,圖片包涵片,片包涵宏塊,宏塊就是存儲(chǔ)像素?cái)?shù)據(jù)的地方。

宏塊的解釋:
  • 宏塊是視頻信息的主要承載者,因?yàn)樗恳粋€(gè)像素的亮度和色度信息。視頻解碼最主要的工作則是提供高效的方式從碼流中獲得宏塊中的像素陣列。
  • 組成部分:一個(gè)宏塊由一個(gè)16×16亮度像素和附加的一個(gè)8×8 Cb和一個(gè) 8×8 Cr 彩色像素塊組成。每個(gè)圖象中,若干宏塊被排列成片的形式。
切片和宏塊的關(guān)系:
  • I片:只包 I宏塊,I 宏塊利用從當(dāng)前片中已解碼的像素作為參考進(jìn)行幀內(nèi)預(yù)測(cè)(不能取其它片中的已解碼像素作為參考進(jìn)行幀內(nèi)預(yù)測(cè))。

  • P片:可包 P和I宏塊,P 宏塊利用前面已編碼圖象作為參考圖象進(jìn)行幀內(nèi)預(yù)測(cè),一個(gè)幀內(nèi)編碼的宏塊可進(jìn)一步作宏塊的分割:即 16×16、16×8、8×16 或 8×8 亮度像素塊(以及附帶的彩色像素);如果選了 8×8 的子宏塊,則可再分成各種子宏塊的分割,其尺寸為 8×8、8×4、4×8 或 4×4 亮度像素塊(以及附帶的彩色像素)。

  • B片:可包 B和I宏塊,B 宏塊則利用雙向的參考圖象(當(dāng)前和 來的已編碼圖象幀)進(jìn)行幀內(nèi)預(yù)測(cè)。

  • SP片(切換P):用于不同編碼流之間的切換,包含 P 和/或 I 宏塊

  • SI片:擴(kuò)展檔次中必須具有的切換,它包 了一種特殊類型的編碼宏塊,叫做 SI 宏塊,SI 也是擴(kuò)展檔次中的必備功能。

整體結(jié)構(gòu)


綜上所述,數(shù)據(jù)可以抽象成這樣:



或者這樣:


問題:

知道了h264以這樣的方式組織數(shù)據(jù),那么怎么就能壓縮呢?或者說為什么這樣做呢?

  • I幀(幀內(nèi)編碼幀)是一種自帶全部信息的獨(dú)立幀,無需參考其它圖像便可獨(dú)立進(jìn)行解碼。視頻序列中的第一個(gè)幀始終都是I幀。如果所傳輸?shù)谋忍亓髟獾狡茐模瑒t需要將I幀用作新查看器的起始點(diǎn)或重新同步點(diǎn)。I幀可以用來實(shí)現(xiàn)快進(jìn)、快退以及其它隨機(jī)訪問功能。如果新的客戶端將參與查看視頻流,編碼器將以相同的時(shí)間間隔或者根據(jù)要求自動(dòng)插入I幀。I幀的缺點(diǎn)在于它們會(huì)占用更多的數(shù)據(jù)位,但從另一方面看,I幀不會(huì)產(chǎn)生可覺察的模糊現(xiàn)象。
  • P幀(幀間預(yù)測(cè)編碼幀)需要參考前面的I幀和/或P幀的不同部分才能進(jìn)行編碼。與I幀相比,P幀通常占用更少的數(shù)據(jù)位,但其缺點(diǎn)是,由于P幀對(duì)前面的P和I參考幀有著復(fù)雜的依賴性,因此對(duì)傳輸錯(cuò)誤非常敏感。
  • B幀(雙向預(yù)測(cè)編碼幀)需要同時(shí)以前面的幀和后面的幀作為參考幀。

看完上面的一大堆應(yīng)該還是一頭霧水,先讓我們看看它減少數(shù)據(jù)量的基本方法,此處可以回憶一下gif的壓縮實(shí)現(xiàn)。。。

減少數(shù)據(jù)量的基本方法

在一系列的幀內(nèi),可以通過差分編碼這樣的方法來減少視頻數(shù)據(jù)量,包括H.264在內(nèi)的大多數(shù)視頻壓縮標(biāo)準(zhǔn)都采用這種方法。在差分編碼中,會(huì)將一個(gè)幀與參考幀(即前面的I幀或P幀)進(jìn)行對(duì)比,然后只對(duì)那些相對(duì)于參考幀來說發(fā)生了變化的像素進(jìn)行編碼。通過這種方法,可以降低需要進(jìn)行編碼和發(fā)送的像素值。

三個(gè)圖像分別作為獨(dú)立的圖像(I幀)進(jìn)行編碼和發(fā)送

結(jié)論:經(jīng)過對(duì)比gif和h264的壓縮,gif中會(huì)將重復(fù)出現(xiàn)的序列用相同的符號(hào)表示,但是在h264中相同的序列直接不發(fā)送,而是通過幀間預(yù)測(cè),所以h264的壓縮效率更高。

參考:
新一代視頻壓縮編碼標(biāo)準(zhǔn)
H.264視頻壓縮標(biāo)準(zhǔn)
深入淺出理解視頻編碼H264結(jié)構(gòu)
H.264碼流以及H.264編解碼的基本概念
深度解析H.264編碼原理
雷霄驊(leixiaohua1020)的專欄

作者才疏學(xué)淺,歡迎大牛吐槽。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容