CD 從抓軌到搭建流媒體伺服器 —— 以《月臨寐鄉》為例

八衛門狸 發表於 2022-07-19

2022-07-19

v0.0.1

由於某些原因,進了 Static World 的群併入坑了 月臨寐鄉 ,夢開始了。作為幻想鄉的新人,也算是有了自己喜歡的社團。但是更細節的東西,狐狐腦子一下子塞不下那麼多東西,只能慢慢探索了惹。CD 從抓軌到搭建流媒體伺服器 —— 以《月臨寐鄉》為例

所以,關於音訊格式、後設資料、 alsa 、 ffmpeg(待續) 的部分應該有好多錯誤(拍飛),大佬們多批評。

緣起

之前在 幻想遊園郷Memories of a Town 的時候並沒有注意過 tag 的問題,而是用 K3B 抓軌後將純粹的 wav 算了 md5sum 就扔進曲庫了。但是這次顯然要做精緻一點。

月2

wav 格式的音訊檔案支援後設資料嗎?答案是不支援。但是這並不意味著不可以嵌入 ID3 tag 。既然能嵌入 ID3 tag 那麼就一定可以嵌入專輯封面,但是無語的地方在於 Windows 並不能識別 wav 裡的 ID3 tag,如果你加入了 ID3 tag ,雖然 VLC 、 mpv 、 mplayer 都可以認到,但是 Windows 資源管理器、 Groove 、 Windows Media Player 甚至 Audacious 都是認不到的,它們只會去讀 wav 的一個 RIFF INFO,而且 Windows 資源管理器、 Groove 、 Windows Media Player 會在 UTF-16/UTF-8 亂碼。

當然 RIFF INFO 就沒有專輯封面了,所以在 Windows 預設的幾個播放器以及資源管理器都將無法顯示專輯封面。如果你並不 care Windows 的操作,那麼你可以在 Linux 下歡快地享受 ID3 tag 的強大。

當然另一個解決方法是將其轉換為 flac 等其他無損格式,當然這也就是另一個話題了。

抓軌

有一臺光碟機就能抓。

我在 Debian 下使用了 K3B ,預設設定即可,將得到 wav 格式的檔案。

如果在 Windows 下也可以使用群友推薦的 EAC 即 Exact Audio Copy ,支援從 freedb 拉取後設資料,也支援 AccurateRip ,就不用自己敲後設資料了。當然對於比較早拿到新碟的來說,遠端資料庫大概率也是沒有。

匯入後設資料

Kid3 和 Mp3tag 是我嘗試下來最好用的兩個軟體,分別也是 Linux 和 Windows 下比較好的解決方案。這裡列舉了幾個常見可行的方法,大家也可以一一嘗試。

Kid3

Kid3 作為 K 家的軟體,其功能強大自不必說。支援 Linux 和 Windows ,可以批量編輯,操作非常靈活,我主要就用它。 ID3 相關功能方面,支援 ID3 tag 的編輯並且可以在 ID3v1.1 、 ID3v2.3 和 ID3v2.4 之間一鍵轉換。

在 File->Open Folder 就可以匯入整個資料夾的曲目,並且全選曲目再在編輯框中編輯就可以批量編輯,也可以批量轉換 tag 版本。

在編輯區, Tag2 部分就是 ID3v2.x 的編輯區域,在這裡也可以插入專輯封面,而且看起來並沒有圖片大小限制;Tag3 部分是 RIFF INFO 的編輯區域,是的,它支援 RIFF INFO ,可惜是 UTF-16 編碼,在 Windows 直接亂碼,只能回到 Windows 來解決。、

月2 with Kid3

月2 批量編輯

Mp3tag

Windows only (不要跟我說可以 wine)。

Mp3tag 是一個在 Windows 下常用的 tag 編輯器,預設會新增 ID3 tag 和 RIFF INFO 且沒有編碼問題,可以被 Windows 資源管理器和 Groove 、 Windows Media Player 正常識別。但是新增的專輯封面由於在 ID3 tag 中,依然無法被識別。

還記得 Kid3 編輯的 RIFF INFO 會有編碼問題嗎,一個簡便但是奇怪的方法就是在 Kid3 中編輯好後設資料和封面,然後再到 Mp3tag 開啟,重新儲存,這樣 Mp3tag 會將後設資料重新寫入成可以被 Windows 識別的編碼。

Mp3tag 預設支援從 MusicBrainz 和 freedb 檢索後設資料,另外 THBWiki 提供了一個 API 來檢索東方相關專輯和曲目和獲取資料,並提供了一個 Mp3tag 外掛來自動填入 ID3 tag ,其幫助頁面介紹瞭如何使用該外掛。

Mp3tag with THBWiki

以 Windows10 為例,首先下載 THBWiki.src ,將其放到 %appdata%\Mp3tag\data\sources 目錄下。啟動 Mp3tag ,在“Tag Sources”下拉框下就可以找到 THBWiki 的選項。

月1 with Mp3tag

注意此時圖中顯示了歌曲後設資料是因為我之前有新增過。

月2 with THBWiki

在搜尋框中搜尋後,將會返回搜尋結果,檢查後點選 OK 即可。

月2 new tags with THBWik

所有資訊將被加入並儲存,仔細看應該可以看出後設資料已經變掉了。

Audacity

Audacity 是 Linux 下一個著名的音訊編輯軟體,將曲目匯入,在匯出的時候就可以編輯後設資料。或者在 Edit->Metadata 編輯,但是不能插入專輯封面。同樣是支援 Linux 和 Windows ,但是不是很推薦這個軟體啦。首先它本身不是一個專門編輯後設資料的軟體,其次它的後設資料編輯功能完全可以被 Kid3 代替,甚至生成的 RIFF INFO 在 Windows 的表現還不如 Kid3 。

EasyTAG

EasyTAG 支援的格式也非常廣泛,就是不支援 wav (*_*)。

puddletag

puddletag 也是不支援 wav ,別的格式可以考慮用一下啦。

foobar2000

foobar2000 是 windows only,很多人用,但是我試了試感覺巨難用。

流媒體伺服器

這裡選擇的是 icecast2 ,這是一個比較流行的流媒體伺服器軟體。最新的 Release 是 Release 2.5.0-beta3 ,但是遺憾的是它依然是 beta ;最近的穩定版是 2018 年釋出的 2.4.4 。

icecast 2.4.4

我的服務連結,基於 2.4.4 版本。

如果你在比較新的 Debian 或者 Ubuntu 上安裝,都將會安裝上 2.4.4 的版本:

$ sudo apt-get install icecast2

打包者為我們做好了大部分配置工作。在 Debian11 上,會自動新增 icecast 使用者組和 icecast 使用者,這是由於 icecast2 是預設由 icecast 使用者啟動的。自啟動 demon 放在是 /etc/init.d/icecast2 ,配置檔案是 /etc/icecast2/icecast.xml ,可以發現 /etc/icecast2/icecast.xml 的所有者也是 icecast 。

icecast 2.4.4 的配置比較簡單,可以參考官網的2.4.1文件以及 FAQ

對於簡單的配置:

  • <location><admin> 只用於 Web 端顯示,設定即可
  • <source-password> 用於推流時使用; <relay-password> 用於中繼,但是由於只有一臺伺服器所以用不到;<admin-user><admin-password> 用於 Web 頁面的管理員登入
  • 預設監聽 0.0.0.0:8000 ,如果需要更改則在配置中的 <listen-socket> 指定 <port><bind-address><listen-socket> 可以有多個
  • 使用 systemctl 重啟 systemctl restart icecast2.service ,或在非 systemd 的系統上 sudo service icecast2 restart

如果出現了 UTF-8 亂碼,可以參考 <mount> 的配置:

<mount type="normal">
    <mount-name>/sw1</mount-name>
    <charset>UTF8</charset>
</mount>

另外如果希望你的流媒體服務可以在 icacast2 的列表中被搜尋到,可以選擇加入如下的配置:

<!-- Uncomment this if you want directory listings -->
<directory>
    <yp-url-timeout>15</yp-url-timeout>
    <yp-url>http://dir.xiph.org/cgi-bin/yp-cgi</yp-url>
</directory>

通常在一臺伺服器上,我們會同時開多個服務,但是 80 埠只有一個,這時候就可以使用 nginx 來作為 proxy 根據規則轉發請求,同時配置簡單的限流措施。儘管有人給出了一個非常全的 nginx 配置 ,然而給 icecast2.4.x 套一個 nginx 後,儘管網頁可以開啟,遠端推流將無法正常進行(當然直接在伺服器上不過 nginx 推是可以的),在很多主流播放器(比如 VLC)上收聽也會斷斷續續。

所以我只能用 stream 來實現:

stream {
        limit_conn_zone $binary_remote_addr zone=sperip:2M;

        upstream icecast {
                server 127.0.0.1:50110;
        }

        server {
                listen 2011;
                listen [::]:2011;

                limit_conn sperip 5;

                proxy_ssl off;

                proxy_pass icecast;
        }
}

糟糕的是,如果這樣寫, icecast2 生成的 XSFP 和在 dir.xiph.org 上的埠都將顯示成 50110 而不是 2011 ,意義不是很大。

所以我只能嘗試更新的 2.5.0-beta3 。

icecast 2.5.0-beta3

實踐證明在 Debian11 下 2.5.0-beta3 在 nginx 代理的情況下,推流會頻繁掉線,所以如果沒啥興趣沒必要看這部分了。 Icecast2 官方給出了兩個關於 nginx 代理的頁面,分別為 known reverse proxy restrictionsknown https restrictions 。 還可以參考這篇筆記,有趣的是這篇筆記在 icecast 2.5.0 下成功用 nginx 代理並給出了配置,不知道我沒有成功是否和 nginx 的版本也相關。最後我還是擺了,讓 Icecast2 直接監聽在了 0.0.0.0:2011

從官方下載原始碼包,這裡放上鍊接: tarballzip ball,編譯三部曲如下:

$ ./configure
$ make
$ sudo make install

但是我並沒有這麼幹,因為第一步就沒過(bushi)。

其實 debian 打過這個包,把它的編譯指令碼拿來抄作業就好了,找到 2.4.4 的 tarball ,這裡給出北外源的連結,在 debian/control 就可以看到編譯依賴。或者把 debian 目錄放到新的 2.5.0-beta3 的原始碼目錄下,直接打 debian 包不香嗎。

打包前記得修改包版本,修改 changelog 即可:

$ dch -s

icecast2 (2.5.0-beta3) unstable; urgency=high

  * 資訊自己寫,這只是個示例

 -- weilinfox <[email protected]>  Sun, 17 Jul 2022 16:21:13 +0000

沒想到的是,測試沒有過。首先 icecast2 在 2.5.0-beta2 引入了測試,測試放在了 tests/ 目錄下,可以切換過去並 make check-TESTS 執行測試;其次, icecast2 不允許使用 root 使用者執行,所以偷懶用 root 打包會直接測試失敗;再次,測試需要依賴 ffmpeg ,如果你的環境沒有,需要單獨安裝;最後,即使你都注意到了,其中有 4 個測試是無法通過的,雖然看起來對功能影響不大。

測試記錄如下:

FAIL: admin.test 5 - buildm3u-user
FAIL: admin.test 6 - buildm3u-fakeuser
FAIL: admin.test 46 - mount-sourceauth
FAIL: admin.test 57 - on-connect-test-sourceauth


============================================================================
Testsuite summary for Icecast 2.4.99.3
============================================================================
# TOTAL: 61
# PASS:  57
# SKIP:  0
# XFAIL: 0
# FAIL:  4
# XPASS: 0
# ERROR: 0
============================================================================
See tests/test-suite.log
Please report to [email protected]
============================================================================

確認了問題不大後,我將 admin.test 的測試取消了。在 tests/Makefile.am 和 中可以看到下面的三行:

TESTS = \
    startup.test \
    admin.test

直接改成:

TESTS = \
    startup.test

dpkg-buildpackage 打包就可以了。

打包命令簡單寫在下面:

$ mk-build-deps
$ sudo apt-get install ./icecast2-build-deps_2.5.0-beta3_all.deb
$ dpkg-buildpackage -b -uc -us

在上級目錄可以找到 debian 包 icecast2_2.5.0-beta3_amd64.deb

注意 2.5.0-beta3 並不能直接使用 2.4.4 的配置檔案,配置理論上應該參考官網的 2.5.0 文件,但是它指向的似乎……還是 2.4.1 的文件啊,甚至 tarball 中的 doc 也是老的文件。事實上有些選項已經不適用了,所以只能把 conf/icecast.xml.in 或者打完 debian 包後生成的 /etc/icecast2/icecast.xml 檔案做為模板,重新寫配置,大部分配置還是一樣的,已經改變的地方只能從註釋中找尋蛛絲馬跡。

推流

DarkIce

DarkIce 是一個音訊推流工具,它從音效卡或其他音訊裝置採集聲音,然後編碼並推送,支援 IceCast 1.3.x 和 2.x 。最新 Release 1.4 。

由於 Debian 和 Ubuntu 源中均為 1.3 版本,不相容 2.5.0-beta3 的協議,如果使用了 2.5.0-beta3 的伺服器就需要自行編譯 1.4 版本。

$ sudo apt-get install darkice

預設配置檔案在 /etc/darkice.cfg ,這個檔案通常需要自己建立,可以檢視幫助文件:

$ man darkice
$ man darkice.cfg

這裡給出一個配置檔案的示例:

[general]
duration        = 0
bufferSecs      = 10
reconnect       = yes

[input]
device          = default
sampleRate      = 44100
bitsPerSample   = 16
channel         = 2

[icecast2-0]
format          = mp3
bitrateMode     = vbr
#bitrate         = 1411
quality         = 0.8
server          = sw.inuyasha.love
port            = <port>
password        = <your password>
mountPoint      = <mount point>
sampleRate      = 44100
channel         = 2
name            = 白玉製作所 channel 1
description     = 白玉製作所 Audio Streaming Channel 1
url             = http://sw.inuyasha.love:2011/<mount point>
genre           =
public          = yes
localDumpFile   = /tmp/live_sw.mp3
fileAddDate     = no
#fileDateFormat  =
#lowpass         =
#highpass        =

bitrateMode = vbr 的好處在於,可以根據資料本身的情況動態調整位元速率,在保證質量的前提下節約了頻寬。

最主要的坑就在於 [input] 下的 device ,這個裝置可以是 OSS DSP , ALSA 裝置, PalseAudio 裝置,或者 Jack 裝置。這裡的 default 是預設的 ALSA 裝置,如果測試不能使用就需要根據具體情況修改,後面將會提到。

編譯 DarkIce 1.4 的過程和前面編譯 Icecast2 類似,首先下載 DarkIce Relase 1.4,然後下載 debian 打包 1.3 時使用的指令碼,這裡同樣給出北外源的連結。同樣,將 debian 目錄移動到 darkice 原始碼目錄。

修改包版本,修改 changelog 即可:

$ dch -s

darkice (1.4) experimental; urgency=high

  * Compiled with C++11 stadard
  * 資訊自己寫,這只是個示例

 -- weilinfox <[email protected]>  Mon, 18 Jul 2022 21:32:10 +0800
$ mk-build-deps
$ sudo apt-get install ./darkice-build-deps_1.4_amd64.deb
$ dpkg-buildpackage -b -uc -us

DarkIce1.4 在構建時可能出現一個常見的編譯錯誤,我在 g++11.2 復現如下:

In file included from Connector.h:39,
                 from Connector.cpp:33:
Referable.h:102:57: error: ISO C++17 does not allow dynamic exception specifications
  102 |         ~Referable ( void )                             throw ( Exception )
      |                                                         ^~~~~
Referable.h:121:57: error: ISO C++17 does not allow dynamic exception specifications
  121 |         increaseReferenceCount ( void )                 throw ( Exception )
      |                                                         ^~~~~
Referable.h:139:57: error: ISO C++17 does not allow dynamic exception specifications
  139 |         decreaseReferenceCount ( void )                 throw ( Exception )
      |                                                         ^~~~~
Referable.h: In destructor ‘virtual Referable::~Referable()’:
Referable.h:105:17: warning: ‘throw’ will always call ‘terminate’ [-Wterminate]
  105 |                 throw Exception( __FILE__, __LINE__,
      |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  106 |                                  "reference count positive in destructor",
      |                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  107 |                                  referenceCount);
      |                                  ~~~~~~~~~~~~~~~
Referable.h:105:17: note: in C++11 destructors default to ‘noexcept’
In file included from Connector.h:40,
                 from Connector.cpp:33:
Ref.h: At global scope:
Ref.h:114:49: error: ISO C++17 does not allow dynamic exception specifications
  114 |         Ref ( const Ref<T> &    other )         throw ( Exception )
      |                                                 ^~~~~
Ref.h:127:49: error: ISO C++17 does not allow dynamic exception specifications
  127 |         Ref ( T   * obj )                       throw ( Exception )
      |                                                 ^~~~~
Ref.h:139:49: error: ISO C++17 does not allow dynamic exception specifications
  139 |         ~Ref ( void )                           throw ( Exception )
      |                                                 ^~~~~
Ref.h:150:49: error: ISO C++17 does not allow dynamic exception specifications
  150 |         operator->() const                      throw ( Exception )
      |                                                 ^~~~~
Ref.h:167:49: error: ISO C++17 does not allow dynamic exception specifications
  167 |         operator= ( Ref<T>  other )             throw ( Exception )
      |                                                 ^~~~~
Ref.h:181:49: error: ISO C++17 does not allow dynamic exception specifications
  181 |         operator= ( T*  obj )                   throw ( Exception )
      |                                                 ^~~~~
Ref.h:195:49: error: ISO C++17 does not allow dynamic exception specifications
  195 |         set ( T   * newobj )                    throw ( Exception )
      |

如果出現了相同的錯誤,可以將版本切為 C++11 ,可以在 debian/rules 的開頭新增一行:

DEB_CXXFLAGS_MAINT_APPEND := -std=c++11

重新構建即可。

構建成功後可以對 1.3 平滑升級,不需要更改任何配置。

ALSA (The Advanced Linux Sound Architecture)

要不是這個專我大概這輩子都不會去碰這個東西

為啥會扯到 ALSA 呢,還記得 DarkIce 要採集嗎,推流的時候需要把播放器播放的重新採集編碼,所以這裡使用 Loopback 虛擬音效卡裝置。

曾經試過 Loopback + palseaudio ,但是 palseaudio 不太穩定。關於 palseaudio 可以使用 pacmd list-sink-inputspacmd list-source-outputs 檢視輸入和輸出的源,實測 mplayer 會隨機從 snd_aloop 裝置掉到預設音效卡裝置。最終直接採用 ALSA Loopback sound card 。

需要安裝 alsa 工具:

$ sudo apt-get install alsa-utils

使用 aplay -L 檢視現有裝置:

$ aplay -L

null
    Discard all samples (playback) or generate zero samples (capture)
default
    Playback/recording through the PulseAudio sound server
lavrate
    Rate Converter Plugin Using Libav/FFmpeg Library
samplerate
    Rate Converter Plugin Using Samplerate Library
speexrate
    Rate Converter Plugin Using Speex Resampler
jack
    JACK Audio Connection Kit
oss
    Open Sound System
pulse
    PulseAudio Sound Server
upmix
    Plugin for channel upmix (4,6,8)
vdownmix
    Plugin for channel downmix (stereo) with a simple spacialization
hw:CARD=RK809,DEV=0
    Analog RK809, fe410000.i2s-rk817-hifi rk817-hifi-0
    Direct hardware device without any conversions
plughw:CARD=RK809,DEV=0
    Analog RK809, fe410000.i2s-rk817-hifi rk817-hifi-0
    Hardware device with all software conversions
sysdefault:CARD=RK809
    Analog RK809, fe410000.i2s-rk817-hifi rk817-hifi-0
    Default Audio Device
dmix:CARD=RK809,DEV=0
    Analog RK809, fe410000.i2s-rk817-hifi rk817-hifi-0
    Direct sample mixing device
usbstream:CARD=RK809
    Analog RK809
    USB Stream Output

如果只顯示為 null ,也就是沒有音效卡裝置,那麼需要排查自己的使用者是否在 audio 使用者組。如果 sudo aplay -L 可以看到音效卡裝置,則你的使用者大概率不在 audio 使用者組,把自己的使用者加入該組後重新登入:

$ usermod -a -G audio <your_username>
$ exit

如果你的使用者確實在 audio 使用者組,且 sudo aplay -L也沒有音效卡裝置,那你可以建立虛擬音效卡,需要載入相關核心模組:

$ sudo modprobe snd-dummy
$ sudo aplay -L

null
    Discard all samples (playback) or generate zero samples (capture)
hw:CARD=Dummy,DEV=0
    Dummy, Dummy PCM
    Direct hardware device without any conversions
plughw:CARD=Dummy,DEV=0
    Dummy, Dummy PCM
    Hardware device with all software conversions
default:CARD=Dummy
    Dummy, Dummy PCM
    Default Audio Device
sysdefault:CARD=Dummy
    Dummy, Dummy PCM
    Default Audio Device
dmix:CARD=Dummy,DEV=0
    Dummy, Dummy PCM
    Direct sample mixing device

如上顯示則虛擬音效卡裝置正常,可以將這一行加入 /etc/modules ,使系統啟動時自動載入該核心模組:

$ echo snd-dummy | sudo tee -a /etc/modules

檢查音效卡裝置正常後,就可以使用 Loopback 裝置,載入相關的核心模組:

$ sudo modprobe snd-aloop
$ aplay -L

# 應當多出來下面的裝置
hw:CARD=Loopback,DEV=0
    Loopback, Loopback PCM
    Direct hardware device without any conversions
hw:CARD=Loopback,DEV=1
    Loopback, Loopback PCM
    Direct hardware device without any conversions
plughw:CARD=Loopback,DEV=0
    Loopback, Loopback PCM
    Hardware device with all software conversions
plughw:CARD=Loopback,DEV=1
    Loopback, Loopback PCM
    Hardware device with all software conversions
sysdefault:CARD=Loopback
    Loopback, Loopback PCM
    Default Audio Device
front:CARD=Loopback,DEV=0
    Loopback, Loopback PCM
    Front output / input
surround21:CARD=Loopback,DEV=0
    Loopback, Loopback PCM
    2.1 Surround output to Front and Subwoofer speakers
surround40:CARD=Loopback,DEV=0
    Loopback, Loopback PCM
    4.0 Surround output to Front and Rear speakers
surround41:CARD=Loopback,DEV=0
    Loopback, Loopback PCM
    4.1 Surround output to Front, Rear and Subwoofer speakers
# 這裡省略後面的輸出

如果可以看到 Loopback 裝置則成功,可以將該核心模組加入 /etc/modules ,使系統啟動時自動載入該核心模組:

$ echo snd-aloop | sudo tee -a /etc/modules

觀察 Loopback 音效卡的裝置資訊可以看到, hw:CARD=Loopbackplughw:CARD=Loopback 都有 DEV=0DEV=1 兩個裝置,實測它們的行為就像管道一樣,一端輸入一端採集即可。

hw:CARD=Loopback 為例, DarkIce 的配置改為 device = hw:CARD=Loopback,DEV=1 , aplay 的播放命令為 aplay -D hw:CARD=Loopback,DEV=0 xxxx.wav

這裡給出我的定時推流指令碼以及 DarkIce 的 [input] 部分配置:

#!/bin/bash

# 開始時間 18:30
START_TIME="1830"
# 結束時間 21:00
# 每一輪播完才會檢查結束時間
END_TIME="2100"

start=0
killall darkice

while true; do
        time_now=$(date +%H%M)
        if [ "${time_now}" -lt "${START_TIME}" ] || [ "${time_now}" -ge "${END_TIME}" ]; then
                [ "${start}" != "0" ] && killall darkice && echo 'Stop broadcast now.'
                start=0; sleep 5s; continue
        fi
        if [ "${start}" == "0" ] && [ "${time_now}" -ge "${START_TIME}" ]; then
                start=1
                darkice -c /etc/darkice.cfg &
                echo Start broadcast now

                # 開播前放兩次 攻撃戦
                for i in $(seq 2); do
                        aplay -D hw:CARD=Loopback,DEV=0 /home/hachi/Music/North\ Korean\ Archives\ -\ 攻撃戦だ.wav
                done

                sleep 5s
        fi

        aplay -D hw:CARD=Loopback,DEV=0 /home/hachi/Music/SW/月溯蓮臺/*.wav
        sleep 5s
        aplay -D hw:CARD=Loopback,DEV=0 /home/hachi/Music/SW/月臨寐鄉/*.wav
        sleep 5s
done

或者簡單粗暴一點:

#!/bin/bash

while 1; do
        aplay -D hw:CARD=Loopback,DEV=0 /home/hachi/Music/SW/月溯蓮臺/*.wav
        aplay -D hw:CARD=Loopback,DEV=0 /home/hachi/Music/SW/月臨寐鄉/*.wav
done
# /etc/darkice.cfg
# 只給出 input 部分作為播放指令碼的參考
# hw:CARD=Loopback,1 和 hw:CARD=Loopback,DEV=1 含義一致
[input]
device          = default
device          = hw:CARD=Loopback,1
sampleRate      = 44100
bitsPerSample   = 16
channel         = 2

by SDUST weilinfox