李子柒130個視頻1萬圖片5萬顏色數據可視化的背後,是古柳三年的念念不忘

溫馨提醒:本文有點長,5000+字數,可耐心閱讀或收藏有空再看。寫作花了很多時間,歡迎轉發、點贊、留言,多多捧場,古柳也有動力持續創作。對文章任何內容有疑問歡迎可視化羣裏交流。PS:堀未央奈,畢業快樂!文章剩最後一節沒寫時,突然看到誰都沒料到的乃木坂46成員宣佈畢業,被擊沉懵了,再也寫不下去,很久緩過來後才寫完,有了這麼個插曲,記錄一筆。

書接上文

上篇文章說到古柳不知何故陷入“個人可視化的至暗時刻”,挺長一段時間,沒啥幹勁,但期間依然發生了許多事,因而簡單回顧了下:盤點這個月可視化的那些事

文章最後放上了幾張最近關於李子柒b站視頻畫面顏色的可視化圖,其實也是在這次實現中一點點找回了之前的狀態,果然自己還是喜歡研究、復現作品,或許唯有如此古柳才能從糟糕的狀態中“拯救自己”,人啊“都得一步一步救自己”

什麼叫做救自己呢?就是忠於自己的感覺,認真做每一件事,不要煩,不要放棄,不要敷衍。哪怕寫文章時標點符號弄清楚,不要有錯別字——這就是我所謂的自己救自己。我們都得一步一步救自己。
——陳丹青



契機

使古柳這次下定決心開始動手實踐顏色可視化的契機,說起來或許過於簡單。

某天刷推特時,看到這幾張色彩鮮豔的照片,彷彿啪得一下很快,無干勁的古柳被明媚的顏色衝擊到,腦海中遂又一次響起“要不搞搞顏色可視化”的聲音,動心起念後開始研究與實踐,並還算順利地做出了幾張效果圖。
https://twitter.com/mitsuyuka_lp/status/1327915297257390080

埋下想復現種子的一席演講

這裏說是“又一次”,是因爲這樣的念頭在過去曾有過很多次,但大概都因時機不成熟,便沒了後文,畢竟真的好好學了 D3.js 和前端基礎知識還是近半年的事。若要問爲何有此念頭,那還要從很久以前看向帆老師的一席演講說起。
鏈接:【一席】向帆:如果把每年的春晚都像蚊香一樣捲起來的話,它就是這樣的 - bilibili
鏈接:向帆:祕密的設計 - 一席
https://v.qq.com/x/cover/7qm4vff0bszr5m0/m0500kj8cmu.html

如果此前你沒看過這個視頻,或許此刻可以好好看看,其中尤爲相關的是後半段春晚和全國美展獲獎作品的內容,這裏專門剪輯出來方便觀看。

視頻裏向帆老師用大家不曾有過的方式、以更宏觀角度各種花式排列數據、進行可視化,令人歎爲觀止。驚豔之餘,那時啥也不會的古柳也彷彿癡人說夢般在心中埋下了想實現類似效果的種子。畢竟魯迅曾說過“聽君一席終覺淺,絕知此事要躬行”


如果你曾看過古柳以前的這兩篇文章「圖像檢索(一):因緣際會與前瞻 - 20180506」「伴隨 P5.js 入坑創意編程 - 20190628」,便會發現其中都出現了向帆老師那次演講。再看發佈日期,此間歲月的念念不忘便不言自明

一晃三年

其實這次終於初步打通全部流程、作出幾張顏色可視化效果圖後,古柳纔開始想自己到底最早是什麼時候看到那個視頻的,一開始沒翻歷史文章,想着可能是2018年末吧,然後試着搜了下日記(正經人誰寫日記),沒想到竟然是2017年11月的事,至今正好滿三年,令人唏噓

念念不忘,必有迴響,而古柳這次的迴響竟然是在三年後。大家又是否有什麼念念不忘的事,結果又如何了呢?

動手實踐

說完那些因緣際會的事,將時間拉回到這次開始着手顏色可視化的時刻。

其實這次用到的數據:也就是李子柒的所有B站視頻及每個視頻隔幾秒鐘抽幀出一幅畫面,古柳在8月份時就完成了。上百個視頻加上萬張照片,大小超過40GB,所以整個流程已經打通一半。

這回只需要搞清楚如何從一張照片裏抽取主要顏色,然後批量化處理,再選擇合適的方式進行可視化即可。

古柳這次可能就不開源代碼了,但作爲守武德的年輕人,還是將每個步驟我是如何實現的簡單講下,點到爲止,有能力的小夥伴其實足夠復現,當然有任何疑問可羣裏交流。不過又想了想基於已抽取的顏色數據用 D3.js 進行可視化這一步後續倒是開源

五步通關

本次項目分爲以下幾步,用到了各種工具,搭配到一起纔打通整個流程,大家也不一定完全按照古柳的方式實現,可相應選擇自己順手的技術進行替換,僅供參考:

  1. 選擇感興趣的、想要進行顏色可視化的對象,比如李子柒的所有視頻;
  2. 爬取李子柒所有b站視頻數據,並下載全部視頻;
  3. 從每一個視頻裏隔幾秒抽一幀畫面,並存儲在相應b站視頻ID命名的文件夾下;
  4. 從每一幀畫面裏提取幾種主要顏色,如 TOP5 顏色;
  5. D3.js 進行顏色可視化。

1. 選對象

這一步沒啥好說的,任何能抽取出顏色的內容大概都可以,可以挑自己感興趣的UP主/電影/動畫/紀錄片等視頻;也可以用自己以往拍攝的照片,這樣就不用抽幀了。

這次選擇李子柒的視頻,一來是覺得她的視頻雖然挺有爭議,但畢竟在海外也有很多人喜歡,算是挺成功的文化輸出;二來印象裏她的視頻畫面都挺好看、意境唯美、有自己的風格,拿來可視化下或許是不錯的選擇。

2. 爬取b站數據,搭配 you-get 下載視頻

李子柒在YouTube/微博/b站等很多平臺都有更新視頻,選擇容易爬取的平臺即可,比如b站。進到個人主頁-投稿欄目下,抓下包,就會發現是數據通過 API 返回,無需自己解析頁面、抽取數據,用最簡單的爬蟲,翻幾頁就能拿到所有視頻數據。
李子柒 - b站個人主頁

數據格式,以「芋頭的一生,辣椒…是送的」這個視頻爲例,重要的屬性大概有這些,其中每個視頻有 aid 和 bvid 兩個 id,bvid: BV1f54y1r7HV 是視頻URL會帶上的,如 https://www.bilibili.com/video/BV1f54y1r7HV

[{
  aid: 842739336,
  author: "李子柒",
  bvid: "BV1f54y1r7HV",
  comment: 5742,
  created: 1604843617,
  description: "小時候我爺爺教過一句讓我很疑惑的順口溜:“紅薯芋頭本姓張,煮的沒有燒的香”…雖然到現在也想不明白爲啥一定要姓“張”但一點也不妨礙我愛喫它!年初在前院大門口種了幾排毛芋兒後門那多種了香芋,剛好也到了能下嘴的季節。芋兒雞、烤芋兒、紅糖芋圓蛋…你們呢?最喜歡怎麼喫芋頭啊?",
  length: "19:59",
  mid: 19577966,
  pic: "//i1.hdslb.com/bfs/archive/4f65418c058899f40638a55e0cd13bef4bf93be1.jpg",
  play: 2479512,
  review: 0,
  subtitle: "",
  title: "芋頭的一生,辣椒…是送的",
  typeid: 214,
  video_review: 37999,
},]

aid: 842739336 可用來下載視頻,這裏古柳搭配使用 you-get 命令行工具,其支持下載很多平臺的視頻/圖像/音頻。

和安裝其他 Python 庫一樣簡單:pip install you-get,然後用下面的命令即可下載單個視頻。更多用法見:you-get 中文說明

# 下載b站視頻
you-get http://www.bilibili.com/video/av842739336

# --output-dir/-o 設置存儲路徑, --output-filename/-O 設置文件名: av842739336 => av842739336.mp4
you-get -o ./liziqi -O av842739336 http://www.bilibili.com/video/av842739336

批量下載可以通過將所有視頻的 aid 都生成一句命令然後寫到 shell 腳本里,然後 bash you-get-cmd.sh 運行腳本即可。

3. 用 ffmpeg 進行視頻抽幀

視頻抽幀或許大家之前沒接觸過,但其實也並不難,用 ffmpeg 同樣一行命令搞定。Mac 下可直接通過 brew install ffmpeg 安裝就行。
官網:https://ffmpeg.org/

原本古柳擔心安裝這類工具會不會有坑,專門提前搜了些文章,以防萬一,沒想到一帆風順,沒出問題。但保不齊大家自己安裝時可能依舊有坑,所以最好有個心理準備......

在正式開始抽幀前,古柳提前計算了下李子柒所有視頻的累計總時長,以便評估不同間隔秒數分別會抽出多少圖片。

其實計算方式在8月28日這篇文章裏有寫到:收益3583萬?我是如何快速統計「李子柒」YouTube頻道視頻累計播放量並計算收益的,只不過當時沒透露是想做這個項目,也並不知道何時會打通後半流程,所以就先寫了這篇有點標題黨的文章,但其實背後是有原因的,草蛇灰線,伏脈千里

當時李子柒油管有116個視頻,共50637秒,約14小時時長,如果每秒抽1幀,就會有5萬張圖片。
鏈接:李子柒Liziqi - YouTube

# 116 個視頻
$$('span.ytd-thumbnail-overlay-time-status-renderer').forEach(el=>console.log(el.innerHTML.trim()))

# 計算全部下一共多少秒
$$('span.ytd-thumbnail-overlay-time-status-renderer').reduce((sum, el)=>{
    let item = el.innerHTML.trim()
    let min = +item.split(':')[0]
    let sec = +item.split(':')[1]
    return sum + min * 60 + sec
}, 0)
# 50637s = 843.95 min = 14h

但抽太多內存會爆炸,且李子柒的視頻畫面不會快速變換,所以選擇間隔大些,隔5秒抽1幀,就會有1萬多張圖片。直接用這裏的命令即可對一個視頻進行抽幀。
鏈接:使用ffmpeg從視頻中截取圖像幀(最簡單實用的視頻抽幀,一句命令)

# 抽幀,每5秒抽1幀
ffmpeg -i av842739336.mp4 -f image2 -vf fps=fps=1/5 image-%05d.png

同樣通過 shell 腳本來批量抽幀,然後......就可以在電腦上煎雞蛋了。

4. 圖片顏色抽取

終於到後半流程了。

能抽取圖片顏色的第三方庫想來很多編程語言都有,但抽取後對顏色進行可視化的項目古柳卻也想不起來太多(歡迎安利),可能唯一記得的就是 Shirely Wu 有做過,於是找了下 data sketches 上「九月旅行」主題的項目就是。後續可能會翻譯這篇文章,所以這裏挑要緊的、相關的說下。

首先介紹下,該項目是 Shirely Wu 對自己2012年5月至2016年8月,4年間13場旅行、4千張照片2萬個顏色(每張抽取5種主要顏色)進行的可視化,同一年的排列成一行,行內每場旅行用一個圓圈表示(徑向圖),圓圈內會展示本次旅行所拍攝照片的日期與顏色以及相關信息。
鏈接:http://sxywu.com/travel

文章中 Shirely Wu 寫到顏色抽取用的 node.js 的第三方模塊包 get-image-colors,並且爲了加快抽取速度,會先用 gm 把照片縮小到8*8大小。不過古柳這次偷個懶就沒縮小,批量抽取上萬張圖片顏色,耗時大概在20min內,也還行。

這裏是抽取一張照片顏色的代碼,getColors() 默認會抽取5種主要顏色,colorschroma.js 顏色對象組成的數組,需要轉換成16進制顏色表示的數組。

const getColors = require("get-image-colors");

async function extractImageColor(imgPath){
  let colors = await getColors(imgPath);
  colors = colors.map((color) => color.hex());
  return colors;
}

const imgPath = '⁨cnliziqi⁩/bilibili-videos-20200807⁩/⁨av5491231av5491231-00001.png⁩'
const colors = extractImageColor(imgPath);

接着挑一個視頻看看抽出來的顏色效果如何,其實也看不出有啥規律,所以還是繼續下一步用全量數據、從各種維度看看能否挖掘出什麼好玩的。


注:其他關於如何安裝 node.jsnpm,如何初始化 Node.js 項目、如何安裝 get-image-colors 、如何結合 fs 模塊讀取所有文件夾裏的所有圖片然後批量抽取,就不再展開了,其實也不難(逃),可自行解決或羣裏交流。

5. 顏色可視化

這部分內容可能會另寫文章詳細講,並開源代碼,所以此處擇其要點講下,有不清楚的地方可關注後續文章。

經過上一步的處理,有了一份如下格式的數據,含視頻avid、該視頻裏所有抽幀圖片的路徑及其5種主要顏色,因爲有上萬張圖片,所以相應有5萬多顏色數據點。至於每個視頻的其他信息可結合第2步爬取的數據來查詢。

[
  {
    "avid": "av753928375",
    "imgColor": [
      {
        "img": "../my-media/cnliziqi/bilibili-videos-20200807/av753928375/av753928375-00001.png",
        "colors": [
          "#25312f",
          "#bdcfdf",
          "#708ba6",
          "#ad2629",
          "#826276"
        ]
      },
   },
]

https://github.com/sxywu/travel/blob/master/src/Trip.js

終於到最後一步顏色可視化,臨門一腳古柳卻不知道該怎麼踢,顏色彷彿很熟悉但又很陌生,但從沒想過該如何排列顏色,因而再好好看看 Shirely Wu 是怎麼做的。

在代表每一場旅行的徑向圖裏,按日期劃分不同扇形區域,每一天拍的照片所涉及的顏色按照 Hue/色相 值(0-360)的不同而徑向排列,並加上x/y力佈局以避免重疊。

HSB 又稱 HSV,表示一種顏色模式:在HSB模式中,H(hues) 表示色相,S(saturation) 表示飽和度,B(brightness)表示亮度。色相(H)是色彩的基本屬性,就是平常所說的顏色名稱,如紅色、黃色等,取0-360;飽和度(S)是指色彩的純度,越高色彩越純,低則逐漸變灰,取0-100%;明度/亮度(B or V),取0-100%。


鏈接:https://github.com/sxywu/travel/blob/master/src/App.js

照貓畫虎,先不用徑向圖,而是在x/y軸二維座標系下進行展示。古柳先將上面的顏色數據打平變成一個僅包含5萬多顏色的數組。

x軸用 Hue 值 區分,y軸固定在頁面中間,然後加上x/y力佈局,看看效果:蠻意外綠色佔比那麼少,藍色居然是最多的,本以爲畫面裏綠色自然植物應該會很多,不過本身只看過零星幾個李子柒的視頻,也說不上來準不準。

接着嘗試其他設置,x軸用 Hue 值,y軸用 Saturation 值,不加力佈局

x軸用 Hue 值,y軸用 Saturation 值,加x/y力佈局

x軸用 Hue 值,y軸用 Saturation 值,加x/y力佈局

小結

這些圖都挺有趣的,都是古柳以前不曾有過的嘗試。另外還可以結合視頻發佈日期、季節等不同維度進行佈局,甚至其他能想到的角度都可以試試,看看會有什麼發現。

由於本次並不完全是爲了從李子柒的視頻畫面顏色中挖掘出什麼內容,更多是爲了打通爬取數據、下載視頻、視頻抽幀、顏色抽取、可視化整個流程,所以最後出了幾張圖後,想到三年來唸念不忘的顏色可視化終於有了個初步結果,就想先寫篇文章記錄下,更多可視化探索留到後面有時間再搞,到時候看看有沒有值得分享的新發現。


以上就是本文內容,如果大家還想看到更多幹貨,歡迎【轉發】、【點贊】、【在看】和【留言】,多多捧場,古柳也有持續創作的動力,畢竟這慘淡的閱讀量實在也是有點說服不了自己太頻繁更新,還真不是因爲懶。逃。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章