2021年7月3日 星期六

[開箱] 電子書閱讀器 Kobo Elipsa 10.3 吋

Kobo 10.2吋 電子書閱讀器

在 Kobo 也花了五千買電子書了 XD 一開始還滿喜歡用 PC app 觀看,想說還是買一台電子書閱讀器來用用吧!之前買過 Kindle 6吋的經驗,加上沒外出看書的需求,還是想大尺寸一點,剛好跟朋友哈拉 Kobo 沒出過大尺寸的,沒想到哈拉後沒幾週就看到推出 10.3吋的閱讀器,當時很快就下單,沒有想太多。

Kobo 10.2吋 電子書閱讀器

把玩的心得:
  • 裸機不含保護殼還滿輕的: 384g
  • 加上保護殼跟筆: 744g
Kobo 10.2吋 電子書閱讀器

大概 2010年 前研究電子書領域時,就曾跟某書店高層開會過,分享過心得,認為一瓶水 600g 是可以接受的範圍(替換掉女生包包內的東西),因此很期待 iPad 問世,我覺得加保護殼真的會覺得小重 QQ 但一台破萬也讓人不得不保護啊 XD 或許這就是 amazon kindle 6吋主流的原因吧?最終還是方便為主。

Kobo 10.2吋 電子書閱讀器

回過頭來,我自己使用 Kobo Elipsa 10.3 吋的心得,小缺點:
  • 首次登入 kobo 時,會輸入帳密,輸入後發現螢幕上會有鍵盤的殘影(但不影響使用)
  • 把 Kindle Paperwhite 6 翻頁速度快些,但跟 iPad 體驗上還是有一段落差
  • 觸控筆採用 AAAA 6號電池,稍微不好買,網路訂最方便(2個50元)
  • 據說 Kobo 一直以來都有各個裝置同步不即時的問題,甚至已經接近無法同步的體驗
優點:
  • 比 iPad 輕,只有讀書跟寫筆記功能,專心讀書
  • 不加保護殼時,質感不錯(可惜實務上應當還是會裝著保護殼)
  • 搭配 Kobo 觸控筆,比我想像中驚艷不少,像是梳理閱讀時可以隨便畫,很讚(看起來 iPad app 看不到?)
Kobo 10.2吋 電子書閱讀器

其他意外...則是把電子書擺在桌上,小孩拿起 kobo 筆畫一畫,就發生慘案了 <囧> 只能說這就是意外吧...目前看起來還不影響閱讀,讓他去吧...還是把電子書當作耗材,書中的資訊才是核心啊。

Kobo 電子書 刮傷

2021年6月27日 星期日

Node.js 筆記 - 以 HTTP API 提供 ffmpeg 轉檔,以 jpg 轉成 png 為例 @ node.js v10.24.1, macOS 11.4

最近接獲一個任務研究了一下 Javascript 與 H264 的解決方案,首先會立馬想到 ffmpeg 方案,就研究了以下 JS 專案:
其中 ffmpeg.wasm 無法在 node.js v10 運行。在不考慮 node.js 升級的前提上,就來把玩其他三者,而 tinyh264 的源頭是 h264bsd 專案,在 h264bsd 專案中有 js solution 可以挖出來跑,包括裡頭有 github.com/oneam/h264bsd/blob/master/js/test_node.js 這隻程式很小巧美麗,可以欣賞一下。而裡頭把玩最多的是 ffmpeg.js 這專案,有興趣可以看看他的 Makefile ,很簡單清楚,比較特別是他分別產出 ffmpeg-webm.js 和 ffmpeg-mp4.js ,兩者不同的地方是 ffmpeg 支援的 encoder/muxer 不同,可能是為了精簡 js code size 因此就拆成 webm 跟 mp4 的用法。這邊把玩的是善用 ffmpeg.js Makefile 去重編 ffmpeg-*.js 增加 demuxer/decoder 和 encoder/muxer。

這邊滿適合看一下 ffmpeg 框架:


接著,工作上的任務是讓 input 支援 h264,而 output 支援 jpg/png 等。這邊把範圍限縮到 input 支援 jpg ,輸出支援 png 來筆記。最後包裝個 HTTP API 出來筆記一下,結果花最多時間是在確認如何從檔案系統讀出檔案資料,以及透過 http.request 將圖片資料下載回來 Orz 還派上 md5sum 來檔案內容是否正常。

而 ffmpeg.js 真的設計得不錯,用起來很方便,可以參考 local-file-cmd.js 用法:

const ffmpeg = require('./ffmpeg-20210624_1550/ffmpeg-mp4.js');
//const ffmpeg = require('./ffmpeg-default/ffmpeg-mp4.js');
const fs = require('fs');
const crypto = require('crypto');

let from_local_file = '/tmp/test.jpg';
let raw_data = fs.readFileSync(from_local_file);
let testData = Uint8Array.from(raw_data);
const md5sum = crypto.createHash('md5');
md5sum.update(raw_data);
console.log('[INFO][from_local_file][size:'+raw_data.length+'][md5:'+md5sum.digest('hex')+'][path:'+from_local_file+']');

const result = ffmpeg({
MEMFS: [{name: 'test.jpg', data: testData}],
arguments: ['-i', 'test.jpg', 'test.png']
})
const out = result.MEMFS[0];
const outputContent = Buffer.from(out.data);

console.log('[INFO] Done. Input size: ' + raw_data.length +', testData size: '+testData.length+', output size: '+outputContent.length);

更多資訊:changyy/study-wasm-ffmpeg-jpg-to-png

2021年6月12日 星期六

Node.js 筆記 - 使用 Puppeteer 監控瀏覽網頁的 Requests 跟 HTML Code @ macOS 11.4, node v14.14.0, npm 6.14.5

緣起於在追蹤網站架構時,每次都靠 chrome browser 開發人員工具去追蹤特定的 request 還好,若需要大量瀏覽找尋一些蛛絲馬跡時,就會很煩!以前很閒時,就會跳下去寫 chrome extension 或是熱衷於 C++ 時,就會寫一點點  Chromium Embedded Framework 來寫個小型瀏覽器,最後想起來試試看 Puppeteer 吧!

使用 Puppeteer 很輕鬆,除了是很常見的 Javascript 語言外,Puppeteer 套件提供了網頁端常見的事件偵測、所發的 Request 清單。就這樣拼拼湊湊即可完工:

(async () => {
const browser = await puppeteer.launch({headless: false});
//const page = await browser.newPage();
const context = await browser.createIncognitoBrowserContext();
const page = await context.newPage();
await page.emulate(device);
await page.setRequestInterception(true);

// https://pptr.dev/#?product=Puppeteer&version=v10.0.0&show=api-event-domcontentloaded
// https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event
//
// The DOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.
//
page.on('domcontentloaded', () => {
console.log('on.domcontentloaded');
});

// https://pptr.dev/#?product=Puppeteer&version=v10.0.0&show=api-event-domcontentloaded
// https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
//
// The load event is fired when the whole page has loaded, including all dependent resources such as stylesheets and images. This is in contrast to DOMContentLoaded, which is fired as soon as the page DOM has been loaded, without waiting for resources to finish loading.
//
page.on('load', async () => {
console.log('on.load');
watchTags(page, watch_tags);
});

// https://pptr.dev/#?product=Puppeteer&version=v10.0.0&show=api-event-framenavigated
// https://pptr.dev/#?product=Puppeteer&version=v10.0.0&show=api-class-frame
page.on('framenavigated', frame => {
console.log('on.framenavigated: '+frame.url());
});

// https://pptr.dev/#?product=Puppeteer&version=v10.0.0&show=api-event-request
// https://pptr.dev/#?product=Puppeteer&version=v10.0.0&show=api-class-httprequest
page.on('request', request => {
watchRequest(page.url(), request.url());
if (skip_resource_type[ request.resourceType() ])
request.abort();
else
request.continue();
});

// https://pptr.dev/#?product=Puppeteer&version=v10.0.0&show=api-event-response
// https://pptr.dev/#?product=Puppeteer&version=v10.0.0&show=api-class-httpresponse
page.on('response', response => {
//console.log('on.response: '+response.url());
});

while (true) {
if (url_init.length > 0) {
const target_url = url_init.shift();
await page.goto(target_url, {
waitUntil: 'networkidle0',
});
console.log('networkidle0');
}
if (url_init.length > 0)
await sleep(5000);
else
await sleep(50);
}
await browser.close();
})();

如此,搭配 command line 使用,就可很快的監控想要的 request 規則,或是 HTML DOM Tree 的變化,例如監控 <script> 的讀取位置在哪:

% node index.js -url "https://tw.yahoo.com" -tag "script.src"
...
on.load
[WATCH][TAG] script: src
Web URL: [https://tw.yahoo.com/]
[
  { src: 'https://s.yimg.com/wi/ytc.js' },
  {
    src: 'https://tw.mobi.yahoo.com/polyfill.min.js?features=array.isarray%2Carray.prototype.every%2Carray.prototype.foreach%2Carray.prototype.indexof%2Carray.prototype.map%2Cdate.now%2Cfunction.prototype.bind%2Cobject.keys%2Cstring.prototype.trim%2Cobject.defineproperty%2Cobject.defineproperties%2Cobject.create%2Cobject.freeze%2Carray.prototype.filter%2Carray.prototype.reduce%2Cobject.assign%2Cpromise%2Crequestanimationframe%2Carray.prototype.some%2Cobject.getownpropertynames%2Clocale-data-en-us%2Cintl%2Clocale-data-zh-hant-tw&version=2.1.23'
  },
  { src: 'https://s.yimg.com/aaq/yc/2.9.0/zh.js' },
  {
    src: 'https://s.yimg.com/ud/fp/js/vendor.174522d6d76b51858b93.min.js'
  },
  { src: 'https://s.yimg.com/ud/fp/js/common.js' },
  { src: 'https://s.yimg.com/oa/consent.js' },
  { src: 'https://consent.cmp.oath.com/cmpStub.min.js' },
  { src: 'https://consent.cmp.oath.com/cmp.js' },
  { src: 'https://s.yimg.com/ss/rapid3.js' },
  { src: 'https://s.yimg.com/rq/darla/boot.js' },
  {
    src: 'https://s.yimg.com/ud/fp/js/main.6622c6aeda051386afaa.min.js'
  },
  { src: 'https://mbp.yimg.com/sy/os/yaft/yaft-0.3.22.min.js' },
  {
    src: 'https://mbp.yimg.com/sy/os/yaft/yaft-plugin-aftnoad-0.1.3.min.js'
  },
  { src: 'https://s.yimg.com/aaq/vzm/perf-vitals_1.0.0.js' },
  {
    src: 'https://fc.yahoo.com/sdarla/php/client.php?dm=1&lang=zh-Hant-TW'
  },
  {
    src: 'https://s.yimg.com/aaq/c/e7fecc0.caas-abu_highlander.min.js'
  }
]
...

2021年6月4日 星期五

[Linux] 升級 Red Hat Enterprise Server 的 OpenSSL, OpenSSH 服務 @ Red Hat Enterprise Linux Server release 5.3

這是一台滿舊的機器,大概 10 年前吧。同事想要 git clone 時,出現了失敗問題,追蹤一下是機器的 openssl 過舊,由於機器有他的任務在,不好意思亂更新系統資源,怕爆!所以採用 tarball 的安裝方式。

openssl 太舊時,連用 wget/curl 去下載 https 來源時都會失敗的,只好靠 http 或是 scp 搬東西進去。

$ lsb_release -a
Distributor ID: RedHatEnterpriseServer
Description: Red Hat Enterprise Linux Server release 5.3 (Tikanga)
Release: 5.3
Codename: Tikanga

$ openssl version
OpenSSL 0.9.8e-fips-rhel5 01 Jul 2008

只好挑個 /opt/tarball 安裝啦,沒想到要編譯 openssl 又會碰到 perl 版本不夠新:

$ wget http://www.cpan.org/src/5.0/perl-5.10.0.tar.gz
$ cd ~/perl-5.10.0
$ ./configure.gnu --prefix=/opt/tarball
$ make -j4 install

接著再安裝個 zlib ,採用 static 方式方便後續大家使用:

$ wget http://zlib.net/zlib-1.2.11.tar.gz
$ cd ~/zlib-1.2.11
$ ./configure --prefix=/opt/tarball --static
$ make install

編譯 openssl:

$ wget http://www.openssl.org/source/openssl-1.1.1k.tar.gz 
$ cd ~/openssl-OpenSSL_1_1_1k 
$ PATH=/opt/tarball/bin:$PATH ./config --prefix=/opt/tarball
$ make -j4 install

編譯 openssh 工具包:https://github.com/openssh/openssh-portable/releases

$ cd ~/openssh-portable-V_8_6_P1
$ autoreconf
$ LD_LIBRARY_PATH=/opt/tarball/lib:$LD_LIBRARY_PATH ./configure --prefix=/opt/tarball/ --with-ssl-dir=/opt/tarball
$ LD_LIBRARY_PATH=/opt/tarball/lib:$LD_LIBRARY_PATH make -j4 install
$ file /opt/tarball/bin/ssh
/opt/tarball/bin/ssh: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, stripped

接著偷懶拉 code 方式:

$ GIT_SSH_COMMAND="LD_LIBRARY_PATH=/opt/tarball/lib:$LD_LIBRARY_PATH /opt/tarball/bin/ssh" git clone ...

或是在環境變數添加好:

LD_LIBRARY_PATH=/opt/tarball/lib:$LD_LIBRARY_PATH 
PATH=/opt/tarball/bin:$PATH

搞定!

2021年5月9日 星期日

[韓劇] 認識的妻子

前幾天想說好久沒用愛奇藝,上去逛了一下,想說看一下「消失的情人節」,結果幾分鐘被朋友提醒可以去 NETFLIX 看高畫質 XD 就這樣又遠離了愛奇藝。倒是在 NETFLIX 看完後,又被推薦服務推坑「認識的妻子」,主因是去年底看過韓劇「Start-Up」,內裡的另一位反派恰好也在這齣戲裡演出。

這是一部 2018 年初的韓劇。這故事跟那時很夯的穿越劇有點關係,但真正吸引到我的,卻是第一集描述雙薪家庭養小孩的困境,真的養了小孩更有感的,感受到劇情安排的那種生活壓力。

不知是不是年紀過 35 的關係,對於大叔熟女演的戲都特別有興趣看完 XD 就這樣花個一天追了 12 集,完食!隨後逛了一下男女主角的 IG ,才發現現實的靜態的照片反而吸引不了我,看來還是劇情關係,讓人喜歡笑起來古靈精怪的女主角,且我不太愛學生時代的裝扮,反而是 OL 時期的精明搭配特有的笑容令人印象深刻。

此時會觀看這齣戲也滿有緣分的,像是幾天前聽股癌 Podcast 回憶起在軍中看了 about time ,讓我回想起對時間的印象,像是電影裡提到小孩出生後,就不適合回到過去,避免改變到未來的小孩狀態。接著恰逢表弟的第一個小孩來到世上,為了體貼老婆,包括月子中心住滿30天、放棄親餵等規劃,著實已把生活的目標跟品質都規劃好也定位好,以及另一位年收稅率達 20% 級距的網路名人在哀哀叫初乳擠得多痛苦和 20% 後就沒了眾多社會福利,政府這稅務規劃到底是助生還阻生 XD

總總點滴,都讓人好好回憶著家庭、小孩、婆媳、雙薪、工作的天秤究竟要怎樣平衡著,就這樣一口氣就看完了這戲!