顯示具有 Program 標籤的文章。 顯示所有文章
顯示具有 Program 標籤的文章。 顯示所有文章

2026-05-31

什麼樣的鍵盤最好用?

 去年曾經提到60%鍵盤最好用,不過經過將近十個月之後,那個觀點修正為「附有音量旋鈕的65%鍵盤最好用」,或者說「附有音量旋鈕的68鍵鍵盤」最好用!

 65%的比60%的基本上多了上、下、左、右以及像是Del、PgUp、PgDn等等。

 68鍵鍵盤是怎樣的概念?
就是將104鍵的鍵盤拿掉最上面那排F1……F12,以及拿掉右邊九宮格數字盤,剩下幾個NumLock、ScrollLock、PrintScreen、Pause、Insert、Home、End這些也都不要,所剩下的簡約鍵盤。

 然後要加一個「音量旋鈕」,這可以讓我們有如使用實體音響器材般的感受。那是很直覺的轉動旋鈕來調整大小聲,而不是用老鼠不斷的按「+」或「-」的圖樣,或者不斷按實體鍵盤上的某兩個「音量+」或「音量-」鍵,操作旋鈕來改變音量真的直覺、簡單好用得多。

 加了音量旋鈕的65%鍵盤有哪些好處:
➀調整音量大小時很直覺,只需兩支手指轉動旋鈕
➁經由軔體或軟體定義後,手指移動範圍變很小,眼睛不必看鍵盤
➂鍵盤體積小,只佔用桌子上小小的面積
➃清理鍵盤灰塵、掉降物時,省掉很多麻煩事

 這是我在用了好幾個機械鍵盤之後的最終心得。

 至於用來定義鍵盤的軟體,強力推薦kanata!
 https://github.com/jtroo/kanata

2026-04-30

語音轉文字的小工具

https://github.com/peteonrails/voxtype

自訂一個開關鍵,設成 toggle 的話,按一下開始收音,再按一下停止收音,並輸出文字。先試著在 terminal 下直接執行 voxtype -v 
不借由其他程式來輸出,當停止收音後,就可以看到螢幕上出現你唸的語音內容,把它 copy/paste 到任何你要的地方。

設定檔在
~/.config/voxtype/config.toml

 [hotkey]
#key = "SCROLLLOCK"
# 在 notebook 上沒有 Scrolllock 鍵,所以改成 F24, 然後再借由 window manager
# 來定義 F24 到任何組合,例如 Win + F12 來當控制鍵,按一下開始收音,再按一下停止
key = "F24"
mode = "toggle" 

這個小工具可以聽你說的話轉成文字,以內定的 base.en 語言模式來說只有142MB,隨便唸一段英語給它聽,轉出來的文字效果相當不錯,先簡單介紹至此,有空再來試中文。

2025-12-31

編輯HTML檔案來自製epub檔案

 以下是用來轉換成epub的最簡單HTML檔案,把它存成延伸檔名為html,再用瀏覽器來閱讀會比較容易懂我的意思。

(請用瀏覽器的View Page Source 來看以下內文的HTML格式語法

-------從這一行以下開始

 

編輯HTML檔案來產出epub檔案

使用Calibre把HTML轉成epub電子書格式.

目錄

前言
簡介
第一章 這是什麼?
第二章 什麼時候做?
第三章 怎麼做?

前言

"epub"格式檔案在諸多電子書閱讀器都能看,我們來自製"epub"檔案給閱讀器用。

因為"epub"格式的檔案在你調整字體大小之後,它會重新排列段落,方便閱讀,不像"PDF"檔的段落格式是固定不變,一旦調整字體大小,需要移動整個頁面才能讀到所有文字。


簡介

做法簡介:

編輯你的HTML檔案
你需要懂一些基本的HTML語法,才能有效的編排文字。
你需要"zip"程式工具或相同功用的程式。

你可以用任何文字編輯程式來編寫HTML檔案,這個檔案裡有一些基本需要用到的HTML控制語。

用zip來壓縮html檔案,並把壓縮後檔案的延伸名稱改成htmlz
在Linux作業系統裡,用這個指令"zip myfile.htmlz myfile.html"


第一章
這裡要說明以下事項

下載Calibre,可以選用AppImage格式,它的使用最方便。

到這裡下載Calibre

https://github.com/KushagraKarira/calibre-appimage/releases/
或是這裡
https://github.com/ivan-hc/Calibre-appimage/releases

授權給它,變成可執行檔,"chmod 755 Calibre-xxyyzz-x86_64.AppImage"


第二章
進行檔案轉換

執行Calibre(AppImage)
按一下"Add books"然後選你的htmlz檔案"myfile.htmlz"
按一下來編輯"Author name(作者名字)"

按一下"Convert books(轉換電子書)"然後選擇"epub"格式。

產出的"epub"檔案會自動存到$HOME/Calibre Library/ 下面的作者名之下


第三章
隨便舉例的一些內容

"這是第一行
然後是第二行
打一些斜體字,外加一些字
這是另外一行字"
這個有個註釋說明一些什麼

甲乙丙丁日月星

小蜜蜂轟轟轟


附註: 關於作者

-- 本書結束 --

-------到這一行以上為止

2025-09-23

把Linux桌面投射到其他電腦的螢幕

 最近剛好用到透過AirPlay去連一台三爽螢幕,不過是使用MacOS連上去的,也就是讓MacOS的機器不需實體就能連上外接的三爽螢幕。查了一下有人寫了給Linux用的Java based程式,所以來試試看能不能用。

 從這個github clone程式:
https://github.com/openairplay/open-airplay
以及下載預先compile好的aprplay.jar
https://github.com/openairplay/open-airplay/releases/tag/0.1.1

 安裝相關程式並執行compile:
apt-get install -y default-jdk
apt-get install -y maven
cd open-airplay-master/Java
ant

 產生jmdns.jar

接著執行:
java -cp "build/airplay.jar:lib/jmdns.jar" com.jameslow.AirPlay

它開始搜尋目前LAN裡的AirPlay,找不到的話當然沒有任何可連上的目標,如果有,就會顯示它的名稱、IP,點下去之後,可以選解析度。

然後,就沒有然後了!

 換用MacOS的機器去連的話,找到AirPlay所提供的螢幕之後點下去,會有一組4位數顯示在對方的螢幕(這要看AirPlay怎麼設定條件,一般是這樣),這時就打在你所操作MacOS這台機器,然後就連上了,等同一個外接螢幕。證明給Linux用的這個Java程式無法如預期的工作。

畢竟AirPlay用的是阿婆公司私有的protocol,並沒有open source,所有試圖連接AirPlay的辦法應該都是走reverse engineering得到的,沒有預期的結果也很正常,不必失望。 

 這時發現另一個螢幕投射程式
https://github.com/pavlobu/deskreen
可以下載它compile好的可執行程式,包括Linux, Mac, Windows都有,不過已經三年沒再更新。

 執行 deskreen 之後它會產生一串位置的 link(例如:http://192.168.1.100:3131/123456), 任何在你同一個 LAN 裡的電腦都可以用瀏覽器打開這個連接字串,然後你在本身電腦上面按下允許,你的螢幕就能投射到對方那一台電腦的螢幕上了(它單純就是投影過去,對方不能操作你的電腦),好像很簡單。

 馬上來試,立即成功使用。不過這跟阿婆的AirPlay無關。

也就是只要有瀏覽器的電腦(包括手機、平板、一般電腦)都能被執行deskreen的電腦投影過去,當成另一台外接螢幕。 

2025-06-24

給kanata更多滑鼠的控制項目

增加一個滑鼠layer "mmouse" 啟動按鍵為"e"

按住 "e" 不放,加按以下各鍵,達到跟用滑鼠一樣的作用

  i = 往上移動
  j = 往左移動
  k = 往下移動
  l = 往右移動
  (同時按 i+l = 往右上移動,其餘類推)

  在移動游標的同時,左手加按
  t = 加速
  f = 減速
  s = 最慢速

  w = 壓下滑鼠左鍵不放
  r = 壓下滑鼠右鍵不放

  y = 滾輪向前
  h = 滾輪向後
  u = 滾輪向左
  o = 滾輪向右

(defcfg
;; You can set the value below to no if you only use the keys defined in defsrc.
  process-unmapped-keys yes
;;  danger-enable-cmd yes
)

(defsrc
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft up
  lctl lmet lalt          spc          ralt rmet rctl    left down right
)

(defvar
  streak-count 3
  streak-time 325
  tap-timeout 200
  hold-timeout 500
  hold-time-slow 300
  chord-timeout 50
)

(deftemplate charmod (char mod)
  (switch 
    ((key-timing $streak-count less-than $streak-time)) $char break
    () (tap-hold-release-timeout $tap-timeout $hold-timeout $char $mod $char) break
  )
)

(defchords piano $chord-timeout
  ( 2 ) 2
  ( 3 ) 3
  ( q ) q
  ( w ) (tap-hold 200 200 w (layer-while-held himep))
  ( e ) (tap-hold 200 200 e (layer-while-held mmouse))
  ( r ) r
  ( f ) (t! charmod f lmet)
  ( g ) g
  ( 2 3 ) esc
  ( w e ) A-left
  ( e f ) home
  ( r g ) C-S--
  ( x ) x
  ( c ) c
  ( v ) v
  ( b ) b
  ( 9 ) 9
  ( 0 ) 0
  ( - ) -
  ( u ) u
  ( i ) i
  ( o ) o
  ( p ) p
  ( h ) h
  ( j ) (t! charmod j rmet)
  ( m ) m
  ( , ) ,
  ( . ) .
  ( x c ) A-tab
  ( c v ) mmid
  ( v b ) enter
  ( i o ) A-right
  ( i j ) end
  ( u h ) pgup
  ( h b ) pgdn
  ( 9 0 ) bspc
  ( m , ) C-f12
  ( , . ) C-tab
)

(deflayermap (main)
  #| for some Notebook combine up/down/left/right with pgup/pgdn/home/end |#
  ;; KEY (tap-hold tap-time hold-time ACTION (layer-while-held LAYER))
  ;; KEY (tap-dance timeout ACTIONa ACTIONb ACTIONc)
  up (tap-dance 170 (up pgup))
  down (tap-dance 170 (down pgdn))
  home (tap-dance 200 (home end))
  lsft (tap-hold 200 200 (tap-dance 180 ((macro M-a 60 lctl) (macro M-f 60 lctl))) lsft)
  rsft (tap-hold 200 200 (tap-dance 180 ((macro M-f 60 lctl) (macro M-a 60 lctl))) rsft)
  caps (tap-hold 200 200 C-spc (layer-while-held capc))
  2 (chord piano 2)
  3 (chord piano 3)
  q (chord piano q)
  w (chord piano w)
  e (chord piano e)
  r (chord piano r)
  a (t! charmod a lalt)
  s (t! charmod s lsft)
  d (t! charmod d lctl)
  f (chord piano f)
  g (chord piano g)
  x (chord piano x)
  c (chord piano c)
  v (chord piano v)
  b (chord piano b)
  9 (chord piano 9)
  0 (chord piano 0)
  - (chord piano -)
  u (chord piano u)
  i (chord piano i)
  o (chord piano o)
  p (chord piano p)
  h (chord piano h)
  j (chord piano j)
  k (t! charmod k rctl)
  l (t! charmod l rsft)
  ; (t! charmod ; ralt)
  m (chord piano m)
  , (chord piano ,)
  . (chord piano .)
  rctl (tap-hold 200 200 C-f12 rctl)
  spc  (tap-hold 200 200 spc (layer-while-held nav))
)

(deflayermap (nav)
  i up
  j left
  k down
  l right
  h home
  ; end
  y bspc
  u del
  g `
  f esc
  m mute
  , vold
  . volu
  q 1 ;; kp1
  w 2 ;; kp2
  e 3 ;; kp3
  a 4 ;; kp4
  s 5
  d 6
  z 7
  x 8
  c 9
  v 0
)

(deflayermap (capc)
  g `
  f esc
  i (mwheel-up 50 120)
  j mltp
  k mmtp
  l mrtp
  , (mwheel-down 50 120)
  u (mwheel-left 50 120)
  o (mwheel-right 50 120)
)

(deflayermap (himep)
  o (macro . o spc)
  k (macro . k spc)
  i (macro . i spc)
  y (macro . y spc)
  p (macro . p spc)
  h (macro . h spc)
  j (macro . j spc)
  . (macro . spc)
  f (macro . f spc)
  g (macro . g spc)
)

(deflayermap (mmouse)
  t (movemouse-speed 200)
  f (movemouse-speed 50)
  s (movemouse-speed 25)

  w mlft 
  r mrgt

  y (mwheel-up 50 120)
  h (mwheel-down 50 120)
  u (mwheel-left 50 120)
  o (mwheel-right 50 120)

  i (movemouse-up 4 3)
  j (movemouse-left 4 3)
  k (movemouse-down 4 3)
  l (movemouse-right 4 3)
)

2025-06-18

kanata鍵盤程式可以在三種OS使用

用了一陣子keyd之後,覺得可惜的是它只能在Linux用,沒辦法推薦給更多非Linux使用者。所以換用kanata看看,一開始被它的設定檔搞得一頭霧水,慢慢摸索終於把keyd用的default.conf 轉換過來,在kanata也能使用相同於keyd的操作方式。

https://github.com/jtroo/kanata
這裡有compile好的可執行檔可以下載來用
https://github.com/jtroo/kanata/releases/tag/v1.8.1

kanata 最大優點是能跨三種OS使用,Linux, Windows, MacOS(某些功能受限)。兩者的設定檔不同,不過有了keyd的設定概念,轉來kanata用也不會太難懂。

kanata 有一項keyd沒有的功能,就是tap-dance

可以定義某個鍵按幾下是什麼功能,例如

Home按一下是Home
Home按兩下是End
Left按一下是Left
Left按兩下是Home
當然不止能按兩下,也可以定義Home按三下=up、按四下=down……,不過按那麼多下其實也不是很好用。

(上面說的「按幾下」是說快速連續按)
以下是我的kanata.kdb 裡面的功能跟我在keyd 定義方式一樣。


(defcfg
  process-unmapped-keys yes
)

(defsrc
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt          spc          ralt rmet rctl
)

(defvar
  streak-count 3
  streak-time 325
  tap-timeout 200
  hold-timeout 500
  hold-time-slow 300
  chord-timeout 50
)

(deftemplate charmod (char mod)
  (switch 
    ((key-timing $streak-count less-than $streak-time)) $char break
    () (tap-hold-release-timeout $tap-timeout $hold-timeout $char $mod $char) break
  )
)

(defchords piano $chord-timeout
  ( 2 ) 2
  ( 3 ) 3
  ( q ) q
  ( w ) (tap-hold 200 200 w (layer-while-held himep))
  ( e ) (tap-hold 200 200 e (layer-while-held mmouse))
  ( r ) r
  ( f ) (t! charmod f lmet)
  ( g ) g
  ( 2 3 ) esc
  ( w e ) A-left
  ( e f ) home
  ( r g ) C-S--
  ( x ) x
  ( c ) c
  ( v ) v
  ( b ) b
  ( 9 ) 9
  ( 0 ) 0
  ( - ) -
  ( u ) u
  ( i ) i
  ( o ) o
  ( p ) p
  ( h ) h
  ( j ) (t! charmod j rmet)
  ( m ) m
  ( , ) ,
  ( . ) .
  ( x c ) A-tab
  ( c v ) mmid
  ( v b ) enter
  ( i o ) A-right
  ( i j ) end
  ( u h ) pgup
  ( h b ) pgdn
  ( 9 0 ) bspc
  ( m , ) C-f12
  ( , . ) C-tab
)

(deflayermap (main)
  ;; for some Notebook combine up/down/left/right with pgup/pgdn/home/end
  ;; use tap-dance to set one key with multiple functions by tapping more than once
  ;; KEY (tap-dance timeout ACTIONa ACTIONb ACTIONc)
  up (tap-dance 170 (up pgup))
  down (tap-dance 170 (down pgdn))
  home (tap-dance 200 (home end))
  lsft (tap-hold 200 200 (tap-dance 180 ((macro M-a lctl) (macro M-f lctl))) lsft)
  rsft (tap-hold 200 200 (tap-dance 180 ((macro M-f lctl) (macro M-a lctl))) rsft)
  caps (tap-hold 200 200 C-spc (layer-while-held capc))
  2 (chord piano 2)
  3 (chord piano 3)
  q (chord piano q)
  w (chord piano w)
  e (chord piano e)
  r (chord piano r)
  a (t! charmod a lalt)
  s (t! charmod s lsft)
  d (t! charmod d lctl)
  f (chord piano f)
  g (chord piano g)
  x (chord piano x)
  c (chord piano c)
  v (chord piano v)
  b (chord piano b)
  9 (chord piano 9)
  0 (chord piano 0)
  - (chord piano -)
  u (chord piano u)
  i (chord piano i)
  o (chord piano o)
  p (chord piano p)
  h (chord piano h)
  j (chord piano j)
  k (t! charmod k rctl)
  l (t! charmod l rsft)
  ; (t! charmod ; ralt)
  m (chord piano m)
  , (chord piano ,)
  . (chord piano .)
  rctl (tap-hold 200 200 C-f12 rctl)
  spc  (tap-hold 200 200 spc (layer-while-held nav))
)

(deflayermap (nav)
  i up
  j left
  k down
  l right
  h home
  ; end
  y bspc
  u del
  g `
  f esc
  m mute
  , vold
  . volu
  q 1 ;; kp1
  w 2 ;; kp2
  e 3 ;; kp3
  a 4 ;; kp4
  s 5
  d 6
  z 7
  x 8
  c 9
  v 0
)

(deflayermap (capc)
  g `
  f esc
  i (mwheel-up 50 120)
  j mlft
  k mmid
  l mrtp ;; mrgt
  , (mwheel-down 50 120)
  u (mwheel-left 50 120)
  o (mwheel-right 50 120)
)

(deflayermap (himep)
  o (macro . o spc)
  k (macro . k spc)
  i (macro . i spc)
  y (macro . y spc)
  p (macro . p spc)
  h (macro . h spc)
  j (macro . j spc)
  . (macro . spc)
  f (macro . f spc)
  g (macro . g spc)
)

2024-08-28

CEO會是全公司最害怕、抗拒AI的人

 這兩年AI炒熱起來,有人用ChatGPT來寫程式,於是寫程式的工程式開始害怕。曾經有某個CEO說五年內寫程式的工作就可以用AI取代,於是programmer人人自危。

 其實更該被AI取代的職位應該是CEO!

 CEO的職責不必懂程式,而是跟據各種情報以及資訊來下決定,以推展公司業務、提高公司獲利,讓股東賺大錢,但事實上CEO可能會下了錯誤的判斷,其中原因除了專業是否足夠?還包括自己的利益、自己的情緒、私生活等等干擾,最終下了錯誤或不應該的決策。

 一個CEO決策的錯誤,比數百個programmer的錯誤所導致公司的損失更加巨大,更不用說捲款潛逃的CEO了。

 一個造成公司虧損的CEO,卻領著比幾百、幾千個programmer加總起來還要高幾倍的薪水!

 如果用AI來當CEO,不必支付這一份在公司裡『絕對高的薪水』,更不用分股票,只要對AI CEO提出(輸入)各種條件、資料,透過AI來摸擬推演各種可能狀況,AI CEO能快速、無私、客觀、公正的做出最有利公司的判斷、下決定,相信這是絕大多數投資人所信賴和支持的。

  1. AI的運算比人腦快太多,能推演的狀況比人腦還多
  2. AI的判斷不帶個人私利、情緒、偏見、人情
  3. AI任職CEO不必領全公司最高的薪水
  4. AI CEO可以24小時,週休零日
  5. AI CEO不會有大房、二房、三房、小三
  6. AI CEO不會把公司員工當韭菜割

 這麼好的CEO不請來公司上班對嗎?

 如果說五年內programmer的工作會被AI取代,相同的,五年內CEO的工作也應該被AI取代。

2022-11-30

聽CNN的RTTY新聞

RTTY原本是發射端把文字轉成高低高低的數位聲音,透過無線電發射出去。
RTTY的接收端是把收到的電波轉成高低的數位聲音,但RTTY不是摩爾斯碼,人耳是聽不懂的,需要再轉成文字,就可以閱讀。但是這篇短文是要用電腦語音合成軟體再把文字轉成語音用耳朵聽。

有人把 CNN 的新聞轉成 RTTY 然後在網路上廣播,這就不必依賴無線電,只要有網路就可以通連了。

以下講的都是在終端機軟體裡進行的,例如用terminator或是gnome-terminal之類。

首先我們在電腦裡(這裡是用Linux環境)建立一個pulseaudio的virtual sink, 指令為

pacmd load-module module-null-sink sink_name=Virtual_Sink sink_properties=device.description=Virtual_Sink

CNN的RTTY的URL 如下,我們用mpv來播放,指令就是

mpv http://internet-tty.net:8000/ITTY

但是它的尖銳聲音耳朵聽起來不悅耳,所以來找看看mpv是輸出到pulseaudio的哪一個sink, 然後把它從原本的sink轉到前面建立的virtual sink就不會聽到吵雜的聲音了,指令為

INPUT=$(pacmd list-sink-inputs|grep -B18 "ITTY"|grep "index:"|awk '{print $2}')

再來把得到的這個INPUT塞到Virtual_Sink,指令是

pacmd move-sink-input $INPUT Virtual_Sink

然後就可以用minimodem來收看,它會解碼成文字,指令為

minimodem rtty -rai

參數rtty是說我們要用minimodem來接收RTTY協定
參數-rai
r 是接收
a 是自動對正載波頻率
i 是高低反向

如果你只要用看的,那到這裡就可以,它會一直打出英文文字來,如果要用聽的,就要再把文字丟給語音合成器espeak,指令是

minimodem rtty -rai| espeak -g9 -s120

-rai 後面是一個 pipe "|"

espeak的參數
-g 9 是字與字的間隔時間
-s 120 是句子的播放速度

2022-07-31

SDR與電腦的連接設置

 RTL SDR出現在巿面大概快20年了吧?之後各種不同牌子的SDR紛紛出現,在功能上更加複雜,不過還是以RTL283x 為基礎的RTL-SDR最普遍,雖然它的頻寬只有2MHz,其它SDR甚至有頻寬幾十MHz。

一開始RTL-SDR出現巿面時大都沒有TCXO,後來的產品才有這個功能,當然價格也會有所不同,在開機使用一段時間後SDR溫度會上升,導致頻率偏移,TCXO是做為熱偏移補償,工作頻率才能穩定。

絕大多數SDR都是以USB裝置連接到電腦上,這樣可能接涉到所在位置的訊號強弱。如果SDR放在訊號強的地方,再透過網路讓其他電腦接收,就能得到更良好的結果。rtl-sdr軟體包裡面的rtl_tcp就是這個用途。

直接執行rtl_tcp 按Enter,然後可以在gqrx的Device選項裡找RTL-SDR Spectrum Server,在Device string項目裡使用rtl_tcp=localhost:1234,這是使用RTL SDR。

如果使用RSP公司的SDR例是RSP1A, 可以先安裝RSP公司的 "SDRplay_RSP_API-Linux-3.07.1.run" 再安裝 https://github.com/SDRplay/RSPTCPServer 這樣可以讓gqrx 也能使用 RSP1A (gqrx是不支援RSP1A, 在device設定裡是看不到的).

使用rsp_tcp之前要先執行 systemctl start sdrplay 再執行 rsp_tcp, 在gqrx的Device選項跟使用 rtl_tcp 完全一樣。

既然能透過TCP方式讓SDR跟電腦連接,那就是可以把SDR與電腦分別放在不同地方,只要網路能連上,就能使用,這時 rtl_tcp(或rsp_tcp) 要加上IP參數,例如 "rtl_tcp -a 192.168.3.135",不過有時候gqrx仍無法連線時,可以試試看加上 "-n" 也就是例如 "rtl_tcp -a 192.168.3.135 -n 250", rsp_tcp 的使用也一樣。

2021-12-31

取得網路串流的URL

為什麼要取得網路串流的URL?因為眾多網站的串流都是要操作滑鼠去點按才能聽,
這樣就不能用自動化的程式去選播收聽,所以要想辦法把它的連結找出來。

以下是用firefox來說明,其它的browser應該有類似的用法。

先以祖國古典音樂電台網站為例:
https://www.classic.nl/livestreams

找到它的播放按鈕,就是一個很一般的三角型讓你Play的,按右鍵,選Inspect

找第一橫列的 Network
找第二橫列右邊的 Media
看Indicator裡有沒有 media 按下去
看File這一欄連結的字串,按老鼠右鍵Copy URL(或Copy cURL,或Open in New Tab)
會得到以下這一串資料

https://22543.live.streamtheworld.com/CLASSICFMAAC.aac?tdsdk=js-2.9&pname=TDSdk&pversion=2.9&banners=none&sbmid=c01352ab-737f-4992-9291-8544a0764fa1

而我們要的就是 https://22543.live.streamtheworld.com/CLASSICFMAAC.aac

再以我國的教育廣播電台為例:
https://www.ner.gov.tw/
找「收聽頻道」點下去找到第一個「臺北總臺FM臺」的三角型,一樣用上面列的方法,
在File這一欄看到一個數字"1",Copy URL得到
https://cast.ner.gov.tw/1

這樣就可以用任何自動化程式(bash/python)來把串流的URL交給播放程式收聽了。

2021-11-28

crontab定時播放音樂

最近做了一個Internet Radio, 收集了一百多個有興趣的網路電台,然後想用定時
機制來播放,當然"sleep"是一個立即可用的工具,但是要去算「睡幾分鐘」就不方便
,這時想到Linux環境下的crontab是個好用的工具,可以自由設定月、日、星期、日
、分來做一些原本要手工啟動的工作。

它的基本語法就是「分 時 日 月 星 程式(參數)」

但是遇到的問題是,設定好「程式+參數」之後,時間到了確實有進行動作,但是我要的
是播放音樂叫我起床卻沒有聲音!

為了證實程式有做動作,設了一個參考檔,只有程式有動起來,就會產生參考檔。

然而在時間到的時候,參考檔有產出,喇叭卻沒發出聲音!?
一開始以為是tty的問題,試來試去也是沒聲音,最後終於找到原因,就是環境參數
XDG_RUNTIME_DIR的問題。

這個參數雖然以 X開頭,但實際上跟Xorg無關,在純console mode也需要設定它。

因此把執行程式改成獨立的script,然後在script裡面設定環境參數,如下:

export XDG_RUNTIME_DIR="/run/user/NNNN"
/PATH/music_player URL
這裡的 /run/user/NNNN 要看你電腦裡的實際字串,它可能是1000或999
這樣就能借由crontab來定時播放音樂了。

2021-07-17

Linux環境下的IR receiver

在Linux環要用紅外線遙控器來做一些事,找到最多都文章都是用lirc, 但是我發現
可以完全不用lirc, 只要裝了ir-keytable加上python pexpect就可以做任何事了。

對於有GPIO腳可以裝IR sensor的機器來說,例如各種pi(主要都是ARM電腦), 只要把
IR sensor三支腳的
信號腳接到GPIO
一支腳接供電
一支腳接地
就可以利用IR遙控你的電腦了。

至於沒有GPIO腳的電腦(例如一般X86電腦),最簡單的方法是買一支RTL-SDR(露天或
PCHome大約400元)它上面就有IR sensor, 而且附紅外線發射器。

至於要怎麼把接IR sensor的GPIO腳enable ?

在ARM電腦可能稍微麻煩一點,有的要在/boot/config.txt設定(如Raspberry Pi),
有的要用distribution附的工具設定(例如armbian-config).

而x86電腦只要把RTL-SDR插入就可以了,不用任何設定IR sensor.

再來就是要安裝 ir-keytable, 每個Linux distribution應該都有這個package,
用系統工具(例如apt-get, yum)就能裝好。

必需以root身份執行 ir-keytable,如果不知道發射器的協定,就用
sudo ir-keytable -c -p all -t
如果知道那個搖控器的protocol, 例如 NEC, 那就可以用
sudo ir-keytable -c -p nec -t
(我還在用網樂通的遙控器,它就是NEC protocol, 感謝黎智英先生,很多台灣人都有
黎先生贈送的網樂通,可惜香港蘋果已經在2021/6/24被中國政府強迫關門了)

然後拿著紅外線遙控器對著電腦把每個遙控鍵都按一遍,記錄一下每個鍵的值,
再來就是寫個程式讓你要的動作對應某個按鍵(或按鍵組合),這程式用
python3 + pexpect 就夠用了

import pexpect
ir = pexpect.spawn('sudo ir-keytable -c -p nec -t')

ir.timeout = None

while True:
    ir.expect("EV_SYN")
    T = ir.before.split()
    if not b'repeat' in T:
	K = str(T[-4])
	if '902' in K:	print('Mute') #0x732902
	elif '91e' in K:     print('Home')  #0x73291e
	elif '91d' in K:     print('Power') #0x73291d
        elif '940' in K:     print('Blue')  #0x732940
        elif '909' in K:     print('Up')    #0x732909
把對應按鍵的值找出來,做為你要執行的動作代碼,就能完全不必用鍵盤、螢幕來
操作一台電腦,不管是X86或是ARM。
用一台小小的什麼ARM pi,透過espeak-ng可以做為報時、報氣象、網路收音機,
不過pi本身的音效不太好,最好就是接一台USB DAC來撥放高品質的音樂。

2021-05-30

閱讀youtube字幕

 Youtube的影片非常多,如果每個影片都要從頭到尾看,相當花時間,當然我們可以
跳著看,但這也是花時間的事。有一個能偷時間的方法,就是「只看字幕」!

可以透過 youtube-dl 這個工具,就能下載影片或以及影片裡的字幕
https://github.com/ytdl-org/youtube-dl

基本上,字幕大都是以影片的原始語言存在的,例如日語影片會有日文字幕,然而
大部份影片會有英文字幕,所以我們可以指定要下載的字幕語文
youtube-dl --write-sub --sub-lang en https://www.youtube.com/watch?v=xxyyzz123

如果不想下載完整的影片,可以在下載完字幕(xxxx.vtt)之後按 Ctrl-C 中斷。

下載來的字幕至少會有兩種格式,都需要人工處理一下才適合閱讀

  1. 最簡單處理的是只要濾掉時間那一行,也就是以00開頭(或影片超過一小時就會有01開頭的)
  2. 比較複雜的字幕除了時間之外,內容也會重複兩次,這個要處理
    • 有這個關鍵字 :start position: 的一行不要
    • 有兩個減號 -- 的一行不要
    • 再來用python寫個小工具把重複的行刪除
 fout = open(argv[1]+'.out', 'w')
Line_old = ''
for line in f:
    if line == Line_old:
       pass
    else:
       print(line)
       Line_old = line
       fout.write(line)

f.close()
fout.close() 
當然只看字幕有時也會有些問題,例如字幕是不會分別主持人跟受訪者的對話內容,
所以不知道這段話是受訪者或主時人說的。

但是先看看字幕,覺得值得花時間看影片時,再去看吧! 

2021-04-25

辨識是否在WSL或正常Linux環境

 例用python來播放網路影音的script, 為了在標準Linux或是在WSL環境都能通用,
首先需要辨識環境,再啟用對應的播放軟體。

我們可以用 os.uname() 或 platform.uname() 來判別是在正常Linux環境或是在WSL
下的Linux環境,再呼叫指定的播放器。

在WSL環境的Linux可以直接執行Windows的播放器,例如VLC, 它在WSL裡的路徑是
/mnt/c/Program\ Files/VideoLAN/VLC/vlc.exe

platform.uname()或是os.uname() 如果是在WSL裡的linux執行會列出:
uname_result(system='Linux', node='MY_LAPTOP', release='5.4.72-microsoft-standard-WSL2', version='xxxxxx', machine='x86_64')

import csv, platform, os
from sys import argv, exit

LIST="""\
Classic Portland,http://allclassical-ice.streamguys.com/ac96kmp3
Classic NL,http://playerservices.streamtheworld.com/pls/CLASSICFM.pls
Clarinet obbo,http://213.141.131.10:8002/clarinet
Caprice cello, http://79.111.14.76:8002/cello
Chamber music,http://chambermusic.stream.publicradio.org/chambermusic.mp3
WMNF,http://stream.wmnf.org:8000/wmnf_hd3
Taiwan PBS,http://stream.pbs.gov.tw:1935/live/mp3:PBS/playlist.m3u8
ICRT,http://live.leanstream.co/ICRTFM-MP3"""

MENU = csv.reader(LIST.split('\n'))
n = 1

if len(argv) == 1:
   for x,y in MENU:
       if n%3 == 0:
          END = '\n'
       else:
          END = '\t'
       print('\033[32;1m'+str(n)+'.\033[m' +x,end=END)
       n+=1
   print('\n')
   exit(1)
else:
   for x,y in MENU:
       if argv[1].isdigit():
           if n == int(argv[1]):
               MusicLink = y
               break
           else:
               n+=1

if 'WSL' in platform.uname().release:
      PLAYER = '/mnt/c/Program\ Files/VideoLAN/VLC/vlc.exe'
else:
      PLAYER = 'mpv'

os.system('%s %s '%(PLAYER,MusicLink))

 

2021-04-05

在Linux對Raspberry Pi Pico改裝micropython

 這是在純文字的 Linux shell 裡對 Pico 進行的基礎動作。
(也可以用來對 BBC micro:bit 動作)

使用 lsusb 可以看到這個 Pico 是這樣
Bus 001 Device 017: ID 2e8a:0003 Raspberry Pi RP2 Boot
再用 cat /proc/partitions 可以看到它預設 partition 已經割出一個
   8       32     131072 sdc
   8       33     131071 sdc1
(因為我已經插了一支 USB 佔掉 sdb, 所以這裡顯示 sdc)

如果用 fdisk -l 可以看到
/dev/sdc1 1 262143 262143 128M e W95 FAT16 (LBA)

在這裡可以下載 micropython for Pico
https://micropython.org/download/rp2-pico/

rp2-pico-20210403-unstable-v1.14-132-gd87f42b0e.uf2 (目前最新的)

按住 Pico USB旁邊的 BOOTSEL 然後插上 micro USB 到你的電腦
用手動掛載 Pico:
mount /dev/sdc1 /media/sdc1
再把下載來的 micropython 的 uf2 檔直接 copy 到 Pico 的 partition 1
cp rp2-pico-20210205-unstable-v1.14-8-g1f800cac3.uf2 /media/sdc1

然後 Pico 自己會 reboot 進入 micropython mode

使用 miniterm (只要裝了 python serial 就會有的一個好用 terminal)
miniterm /dev/ttyACM0 115200 --raw  就連進 Pico 的 micropython 提示符號

2020-08-23

espeak講台灣國語

 台灣「國語」跟中國「普通話」之間除了發音不同之外,語調規則也有不同,網路有些
東西因為台灣人不關心,漸漸的被中國侵蝕,像電子產品的語音幾乎都是用中國發音。

在open source裡一個已經很多年的語音合成程式espeak原本只有歐語,後來有人把
它加了漢語,可能是中國人去加的,所以是用中國人的發音方式,台灣人如果仔細聽的話
應該會發覺它跟我們日常發音不一樣。

例如「暴露」:
台灣發音 ㄆㄨˋㄌㄨˋ(PùLù)
中國發音 ㄅㄠˋㄌㄨˋ BàoLù
 

「質量」
台灣發音 ㄓˊㄌㄧㄤˋ (ZhíLiàng) (質:二聲)
中國發音 ㄓˋㄌㄧㄤˋ Zhìliàng (質:四聲)
 

「企業」
台灣發音 ㄑㄧˋㄧㄝˋ (Chí yè) (企:四聲)
中國發音 ㄑㄧˇㄧㄝˋ Qǐ  yè  (企:三聲)
 

「期待」
台灣發音 ㄑㄧˊㄉㄞˋ (Chí dài) (期:二聲)
中國發音 ㄑㄧ ㄉㄞˋ Qi dài  (期:一聲)
 

「說服」
台灣發音 ㄕㄨㄟˋ ㄈㄨˊ (shuì fú) 四聲+母音不同
中國發音 ㄕㄨㄛ  ㄈㄨˊ shuō fú  一聲+母音不同

就像美語與英語一樣,分流之後各有各的特點,文化多樣性是人類文明重要的一環,
就跟生物多樣性一樣重要,把異己通通消滅、歸於一統,將是文明的災難。

把espeak改為台灣發音方式的方法:
1. 到這裡下載 https://drive.google.com/open?id=1ArwjaKM6lYby4lxKuv5F8_S6qexjY0pp
 

2. unzip zh_dictionary-calvin_2018-10-30.zip

  copy
  zh_list, zh_listx, zh_rules,
  到
  /usr/lib/x86_64-linux-gnu/espeak-data

  cd /usr/lib/x86_64-linux-gnu/espeak-data
  espeak --compile=zh

現在就可以用espeak唸出台灣發音
espeak -vzh 今天可以講台灣國語
or
espeak -g11 -s150 -vzh 今天可以講台灣國語

 

2020-07-19

把聲音丟到別台電腦

在同一個LAN內設好某一台已經接上喇叭的電腦做為audio server, 然後在別台電腦
播放的聲音,都可以丟到這台server放出聲音。

固然個別的應用軟體可以把聲音丟到特定的一台電腦,例如:
mpv --pulse-host=192.168.5.10 http://stream.srg-ssr.ch/m/rsc_fr/aacp_96

但是每個產生聲音的應用程式都要加上遠端server的參數就有一點麻煩,如果直接
在電腦總控聲音的設定檔寫好遠端電腦的傳輸協定,就可以一次搞定,不必每一個
應用軟體都設定。

可以利用pulseaudio來達成這個目的。
要做為音效server的電腦:
/etc/pulse/default.pa
load-module module-native-protocol-tcp \
auth-ip-acl=127.0.0.1;192.168.5.0/24 [auth-anonymous=1]
以上是接受整個網段其他電腦都可以把聲音丟過來。
(記得firewall要打開4713)

同一段LAN內其他client電腦:
/etc/pulse/default.pa
load-module module-tunnel-sink \
sink_name=NEO server=tcp:192.168.5.10:4713
(那一台server電腦是NanoPi NEO, 名字可以隨便寫)

設定好之後執行一下 pulseaudio -k; pulseaudio --start

這樣在同一個LAN內的任何電腦(client)都可以把任何程式產生的聲音丟給NEO,
包括在看youtube所產生的聲音也一樣會被丟到server.


2020-06-07

關於MTP傳輸協定與電子閱讀器

MTP是 Media Transfer Protocol 的縮寫。

我們可以透過adb與正常Android手機連通、做各種操作,但是有些不是很正常的
Android系統,例如國內品牌的電子書閱讀器Mooink,它OS是Android,但是被
刪減到沒辦法跟adb溝通。

這時可以利用傳統MTP協定的工具來跟週邊溝通,其中有一個"jmtpfs" 還不錯用,
這是一個文字介面的工具,我們在操作時可以明確知道它在幹什麼。

當讀書器透過USB連到電腦後,可以用指令
jmtpfs -l 來列出這個 device, 它會出現
Device 0 (VID=1f85 and PID=7a12) is UNKNOWN in libmtp v1.1.13.

再用 lsusb 列出來看
Bus 001 Device 006: ID 1f85:7a12

這就是閱讀器,接下來把它掛載到某個目錄之下,例如自行建立一個 /media/moo
使用指令為
jmtpfs /media/moo

再看看它有什麼東西
ls -l /media/moo

出現「/media/moo/內部儲存空間」,再看下一層
ls -l /media/moo/內部儲存空間/  就有很多檔案在那裡,你可以進行一般正常的
檔案操作,cp, rm, vi......

但是mooink只能閱讀 epub 格式檔案,如果你的檔案是 pdf 需要藉由別的工具
進行格式轉換,calibre 有一個叫做 eboot-convert 的工具可以達到轉換目的。
eboot-convert aaaa.pdf aaaa.epub 就可以轉出來了。

calibre請用它的官網提供的版本,因為各Linux repository 裡的calibre可能有點舊。
https://calibre-ebook.com/download_linux

2020-05-17

DM-1801的 open source firmware

之前介紹過這支手機的設定可以在Linux環境用 python 寫入,這篇是要整個換掉它的
firmware, 換用這個open source firmware後,先前用的那個 python 就沒辦法用
來寫入這個新環境的操作設定了

這是一支俱有VHF/UHF以及analog/DMR模式的無線電手機
澳洲火腿VK3KYY開發的DM-1801 firmware (open source)

URL: https://github.com/rogerclarkmelbourne/OpenGD77

最新(R)版 20200503 (D版 20200507)可以在 Linux 環境用 python 寫入機器裡.

tool: https://github.com/rogerclarkmelbourne/OpenGD77/blob/master/tools/Python/FirmwareLoader/gd-77_firmware_loader.py

udev-tool: https://github.com/rogerclarkmelbourne/OpenGD77/blob/master/Linux/etc/udev/rules.d/Ubuntu/99-gd77.rules

fw: https://github.com/rogerclarkmelbourne/OpenGD77/releases/download/R20200503/OpenDM1801.sgl

執行 gd-77_firmware_loader.py 需要先裝
python-usb(或python3-usb)
python-enum34
python-future(如果你是用python2)
(如果自行手動下載 OpenDM1801.sgl 就不需要裝 python-urllib3)

把下載的 99-gd77.rules 放到
/etc/udev/rules.d/ 下面(這是 Ubuntu的, 另外有 Fedora的,請見該網頁有關的文件說明)

連接電腦跟DM-1801的線一頭插在DM-1801的耳機、麥克風,另一頭插在電腦USB,
先不要開DM-1801的電源,用兩支手指按住DM-1801側面PTT下面的兩個鍵(一個標示
向上的尖頭「^」,一個標示向下的尖頭「v」)不要放,另一手轉開DM-1801的電源,
這時LCD螢幕沒有任何顯示,但是接近天線的LED會變成綠色恆亮,表示機器進入
「firmware更新模式」,然後放開手指,開始操作電腦。

不需要用 root 權限來執行 gd-77_firmware_loader.py
加 -f 來告知 firmware 的路徑跟檔名

gd-77_firmware_loader.py -f ~/Downloads/OpenDM1801.sgl

目前 CPS 的部份沒有 linux 能用的工具,只有 Windows 的工具, CPS 就是手機的
操作環境設定。所以你需要借用Windows來寫一次CPS。

不過 CPS 只要寫入一次,之後再upgrade firmware 並不會改變 CPS 內容,應該說
百分之九十五以上的內容不會因為firmware改變,目前只發現像是LCD背光被改變,
這只要手動改回來就好了。

2020-01-31

RTL airband掃描程式

很多RTL SDR相關程式出來很多年都沒再更新,忽然發現這支才更新沒幾天,
就來介紹一下。它除了RTL-SDR之外還支援SoapySDR, SDRPlay RSP1,
Airspy, MiriSDR.

https://github.com/szpajder/RTLSDR-Airband
最新update 2020 一月19日

這是一個很實用的飛航頻道掃描程式,
這一版要安裝以下幾項library for development:
libconfig++-dev, libfftw3-dev, libmp3lame-dev, libogg-dev,
libshout3-dev, libvorbis-dev, libpulse-dev

local直接聽的話就要用到 pulse server, 請修改設定以便接受這個掃描程式的聲音
/etc/pulse/default.pa
加入以下這一行
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;192.168.20.0/24 auth-anonymous=1
上面的192.168.20.0/24要按照你實際的ip範圍來寫

config 檔可以想成 C 語法來處理格式以及分隔號
我是在x86上使用pulse來聽,所以用以下參數compile
make PLATFORM=x86 PULSE=1

用pulse的話可以讓接收的電腦跟播放聲音的電腦分別在不同地方,只要網路tcp
有相連就能聽。

RTL-SDR頻寬只有2.56MHz,而飛航通訊在VHF部份大約有15MHz範圍,RTL-SDR
無法同時包含,
config用"scan"的話就可以掃描所有範圍,不過rtl_airband內定是每秒五個頻率。

以下是 config檔內容,你可以用任何檔名,也可以放在任何地方,只要在執行時
告訴它路徑
rtl_airband -f -c /PATH/myconfig

各機場頻率有所不同,你可以從ICAO找出各機場主頻率,從收聽主頻率可以記下
塔台跟飛行員告知的其他頻率,寫在
freqs = ( xxx, xxx, xxx );

devices:
(
 {
  type = "rtlsdr";
  #serial = "00000012"; /* for identify which "index" */
  index = 0;   /* (integer) - indicates which RTL device */
  gain = 25.0;  /* Typical gain range for RTLSDR is from 0.0 to 49.6 dB, between 20.0 and 40.0; */
  #centerfreq = 120.0;  # required in multichannel mode
  /* The default for RTLSDR is 2.56 Msps. It gives about 2.56 MHz of bandwidth
  (ie. plus and minus 1.28 MHz from the center frequency) */
  mode = "scan";
  /* Scanning speed in RTLSDR-Airband is currently hardcoded to 5 frequencies per second */
  #mode = "multichannel";
  #correction = 80;
  /*
  buffers = 10
  (integer, optional) - number of memory buffers to allocate for USB transfers.
  The default is 10. If you use more than three dongles simultaneously or you get error
  messages like "Failed to submit transfer 12!" you may need to lower this value. */
  afc = 1;
  # afc: automatic frequency correction 0 or positive int
  channels:
  (
    {
      freqs = ( 118.1, 118.7, 119.7, 121.5, 121.9, 123.6, 125.1, 125.5, 126.7 );
      outputs: (
        {
      type = "pulse";
          server = "127.0.0.1";
          #server = "192.168.20.16";
          /* type = "file";
          directory = "/home/ubuntu";
          filename_template = "TWR-scan1"; */
    }
      );
    }
  );
 }
);