室內電話也成為一種復古互動體驗

室內電話也成為一種復古互動體驗

前年《大橋 1988》演完後,因為 Taipei Creative Coders #3 珍珠與威成的介紹,我們(馥谷餘)毛遂自薦加入了大橋的製作團隊,與複象公場Urban Baker 以及大橋工舍一起創造新的版本,提供了互動體驗的部份,最後於去年十二月演出。

去年上半年我們討論了蠻多種不同的互動形式,最後決定本著大橋的「聲音」與「復古」兩大原素,將室內電話作為 2012 年《大橋 1988:自由年代》實體互動的部份。

《大橋 1988》這齣劇是一個透過手機 App 傳遞故事的街區劇場。觀眾先在集合地點出發,手機的 App 會根據觀眾的位置引導觀眾行走,並以耳機發出的對白、音效作為媒介。這樣說起來感覺沒什麼,但實際上體驗時,耳機裡的對白加上街區實體的景物,沉浸感十足,除了聽到的,看到的,還包括味道,如廟裡的香,都為這個劇場增潻許多氣氛。GPS 定位的流暢度也是這整個體驗令人感到驚豔的地方,背景音樂的 loop 輪播搭配不同走路速度快慢,到達特定地點觸發的語音事件,那種密合的細緻感,是不親身體驗很難體會的。

第一年的《大橋 1988》有安排類似 NPC 的演員跟著一起演出,而第二年的《大橋 1988:自由年代》則是取消了實體演員,多了實體互動(裝置)。

改裝電話

最一開始我們在討論改裝電話時,想過拿現成的電話直接修改硬體,加裝一些感測器,聽筒拿起來時,播放特定的聲音(電話語音)。同時我們也尋覓其他不同的解決方案,最後決定用 VoIP Gateway 來實現這個互動。原因是彈性較大,我們可以有各種不同的組合,用軟體的方式解決,畢竟這就是一個可以直接使用的系統,只是大多用在辦公室總機分機、客服電話等用途。而如果需要的電話量較大時,也不需要一直動手改裝硬體。

有趣的是,去年參加 PyCon TW 2021 時,剛好看到一個講者,提到的密室逃脫機關,就是用電話改硬體的方式來做的。不過當時我們已經決定用 VoIP 來做了,只是聽到這個講題很有共鳴,聽得津津有味。

盒子裡有什麼

最終,我們用了三個防水機盒,每個裡面各有一台 Raspberry Pi(作為 SIP Server)、一台或兩台 VoIP Gateway(我們用了古老的 Linksys SPA3000 以及 Grandstream HT802)和一台 4G AP(TP-Link Archer MR600)。

最一開始的 prototype,就是用個紙箱裝的。因為希望它很 portable,行動方便,所以 server 的部份很早就鎖定用 Raspberry Pi。在裡面跑的 server,也是很早就想說用 asterisk 相關的東西。這大概是我念研究所的時候,還有點印象的詞彙,當時好像滿多學長在弄 SIP/VoIP 的專題。因此 Pi 上裝的就是 Raspberry Pi 版本FreePBX(裝載有 asterisk,都包好了的 Linux)。

Extension

我們可以在 FreePBX 的管理介面設定分機號碼(Extension),一個實體電話一個,我們也可以多設定分機號碼,接在軟體 SIP 電話上。下圖中的 10、11、12 是我們設定配給實體電話用的,而 76647777 則是我們測試用的軟體電話的號碼。

這邊設定好之後,實體電話搭配的 VoIP Gateway 也跟著設定,把 SIP Server 指向 FreePBX,以及其他帳號密碼等設好之後,我們的分機就可以互相撥號,互相語音通話了。

我們也可以安裝軟體的 SIP Softphone,如 Zoiper,一樣設定好 Server 等資訊,就可以類似 Skype / LINE 語音通話,撥打到這些接起來的實體電話。

Dialplan

上面的電話通了之後,就是要來寫 asterisk 的 dialplan 了。dialplan 滿像是這個 SIP Server 宇宙的撥號規則。除了上述設定的分機號碼可以直接連通到分機外(如果你看 FreePBX 的內部,上述從介面設定的 extension 也會在儲存套用後自動變成 dialplan 設定檔的一部份),你可以自訂任何號碼,並決定撥了會做什麼事情。FreePBX 裝好了他其實就有寫了「報時台」,也就是室話打「117」的「下面音響...」這個東西,只不過它是英文語音的,在大橋的系統是打 106 🤣

所以,我們就可以自己定義我們在「大橋宇宙」裡的所有電話號碼,以及相對應會有的動作。其實 asterisk 的 dialplan 真的很像天書,很難理解,我是爬了許多資料,trial & error 好多遍才做出一些我想要的效果。

以下截錄部份 extensions_custom.conf(在 asterisk 裡面 dialplan 都寫在 extensions*.conf,自己客製化寫的都會放在 extensions_custom.conf 裡)

exten => 25053609,1,Goto(dq-1124-constructor,s,1)

[dq-1124-constructor]
exten => s,1,Answer
   same => n,Ringing()
   same => n,Wait(3)
   same => n,Playback(silence/2&/home/asterisk/projects/freepbx-extensions/audio/1124/constructor)
   same => n,Hangup

當我打了 2505-3609 這個號碼時,它會響鈴等三秒,接著接通,然後等兩秒(silence/2),再播放 constructor 這個音檔,最後掛斷。

《大橋 1988:自由年代》一開始發放故事角色的名片,第一站就是要打電話給她,也是整個故事的開端

低音質

處理聲音我雖然不是專業的,但某些軟體還算熟悉,最常用的就是 Ableton Live,所以我想在把這些音檔放進去應該很簡單。但是我發現我錯了。當時找的資料發現它預設吃的檔案副檔名是 .sln,取樣頻率只有 8kHz 單聲道。我發現 Ableton Live 根本無法輸出 8kHz 的檔案 🤣,最後還是得靠網路上大家用的方法 "sox" 這個轉檔程式。

轉成 8kHz 之後,就有一種 Lo-Fi 感,就開始很復古了!

更新檔案

在接近開演的時候,我們的三個機箱已經都在現場了,但你知道的,這種東西一定都是改到最後一刻的。之前有過很多次類似的經驗,所以我做了一個簡單的更新方式。這個方式的前提是我們機箱要有便捷的連入方式,以及便捷的網際網路存取。

更新檔案的部份不外乎就是 Raspberry Pi 上(FreePBX)的音檔、 extensions_custom.conf,以及我們在 extensions_custom.conf 上有呼叫到的 python scripts。所以首要是,當我更新的時候,我的筆電要可以輕易的連上 Raspberry Pi,因些在我們的機箱上有一台 WiFi AP,筆電開了接上 WiFi 我就可以 ssh 進去了。

但這樣要更新檔案也很麻煩,總不要我一個一個檔案從我電腦本地端 scp 進去吧,所以我開了個 git repository 來做版本控管,而 extensions_custom.conf 原本是放在 /etc/asterisk 底下的,我就砍了之後做了一個 symbolic link 指到我 git repo 底下的 extensions_custom.conf。

root@raspbx:/etc/asterisk# ls -al extensions_custom.conf 
lrwxrwxrwx 1 asterisk asterisk 65 Sep 18  2021 extensions_custom.conf -> /home/asterisk/projects/freepbx-extensions/extensions_custom.conf

而音檔、scripts 也都在這個 repo 裡面,所以,我連上後就只要 git pull origin main,接著更新(重啟)asterisk 的 dialplan 即可。

剩下的問題就是網路了。因此當時買的 AP 是一台 4G 的 AP,可以插 SIM 卡,去電信公司買三張預付卡,一張 300 元就搞定了。簡潔有力,一台更新大概可以在 30 秒內完成,所以最後一秒鐘的語音更新對我們來說也不是太大的負擔。

回馬槍

在這個互動當中,有一個部份是掛了電話後,會回撥回來,電話會響鈴的。這個就有賴 python 了。我們用了 pycall 這個套件,很簡單的就可以撥打指定的分機,很像是在 python 裡面寫 asterisk 的 dialplan 😱 下面就是列在 pycall 文件上的範例

# Initiate an outbound call to 1-888-222-3333 and say
# 'hello world!' when the caller answers.

from pycall import CallFile, Call, Application

call = Call('SIP/flowroute/18882223333')
action = Application('Playback', 'hello-world')

c = CallFile(call, action)
c.spool()

真.復古電話

大橋工舍那邊一直都有一個非常復古的轉盤式電話。我對電話系統沒那什熟悉,尤其是這麼古早的,想說有電話盒可以接上電話線,就應該可以通。這隻電話插上中華電信的線路是會通的,可以打,也可以接聽,也會響鈴,可是接上我們的 VoIP Gateway(SPA 3000 這一台)就沒有作用。

經過一翻查詢,我們現在普遍看到的電話用的訊號是 DTMF,也就是號碼按下去會出現某種固定的聲音;然後這種轉盤式的電話,則是用「脈衝撥號」,如果你聽聽筒的聲音,會有噠噠噠的聲音,看你撥的號碼是多少,就會噠多少次,例如 1 就是 1 次,2 是 2 次,0 則是 10 次。因為想像你要用這支電話來撥現代的手機號碼,其實是相當痛苦的,因為我們手機號碼有 10 碼,而且都是 09XX 開頭,光是播前兩號就已經覺得不耐煩了 🤣

SPA 3000 不支援脈衝撥號,只支援 DTMF,所以這台接上 SPA 3000 是無法撥號的,但是可以接聽。只是不知道為什麼鈴響很無力。它裡面是真的有東西在敲兩的響鈴的,只是很像沒有足夠的力氣,聲音都被悶住了。

SPA 3000 其實是一台很老舊的機器,它早就已經停止支援(end of support)了,可能是這些機器庫存也相當老舊,我們在前面 prototype 的階段就壞了好幾台。後來,在正式演出時,入口體驗電話的點為了消化人流增設了兩隻電話變為總共三隻電話,我們就加購另一台 VoIP Gateway,也就是前述的 Grandstream HT802

特別提起它是因為它的說明文件寫道它支援脈衝撥號,於是乎我們把轉盤電話接上,確實是可以撥號了,但是鈴響的部份還是一樣。再度經過一番研究,發現在鈴響時線路需要 90V,但這兩台 VoIP Gateway 似乎都不會到 90V,所以可能需要另外的設備如 RG-10A 來讓它響鈴正常。然而,我們最後並沒有購買此設備來測試,所以也無法確認是否就是這個原因讓它響鈴無力。因此最終我們並沒有讓這台轉盤式電話出現在劇中,仍然覺得有些惋惜。

VoIP Gateway 上的設定

前文有提到 asterisk 的 dialplan,其實在 VoIP Gateway 上也有個 dialplan 的設定,主要是拿來設定哪些號碼可以撥出去、打進來。當時設定的主要的考量,是我們有部份的號碼是三碼,例如 310,但又有部份的號碼是七碼、八碼或九碼等,所以如果 dialplan 沒設的話,Gateway 會不知道你號碼撥完沒,就必須等到它逾時,才會真的撥到 SIP Server 上,等待時間會很久,也不符合我們一般打電話的體驗。

每一家 dialplan 的格式都不太一樣,文件說明也不盡詳細,所以還是有網上考古與 trial & error 的部份在。這些 dialplan 的格式也都有一點 regular expression 的影子,但又不是 regular expression。

SPA3000 上的 Dial Plan 設定
Grandstream HT802 上的 Dial Plan 設定

這些 VoIP Gateway 上有一大堆關於電話相關的設定,沒碰過還真的不曉得。我們電話接在 SPA 3000 時,一直有一個困擾,如果我掛上電話的速度太快,馬上又把話筒拿起來,它的行為就會怪怪的,好像會有切換線路的感覺。查了很久,才知道以前電話有些奇特的功能,其中一個叫做 Hook Flash。如果你快速的按一下電話掛上的開關,它可以切換到另一條線,所以你可以在線路一通話到一半的時候,切到線路二打另一通,然後切換的方式就是快速的掛上再拿起。

HT802 就沒有這個功能,就沒這個困擾。在 SPA 3000,需要特別把 Hook Flash Timer 關掉才可以避免。

我們把 Hook Flash Timer Min、Max、Callee On Hook Delay 跟 Recorder Delay 都設成 0

總結

以上就是我們這次在《大橋 1988:自由年代》運用 VoIP 所做的互動體驗。雖然電話似乎就是一個簡單的互動,但是設定起來依然有很多眉眉角角要注意。我對 telephony 電話系統不熟悉,很多專有詞彙完全不曉得,造成搜尋資料的困難,要下什麼關鍵字都不知道。不過整體而言我是覺得滿有趣的,按下復古電話的號碼按鈕是一個相當療癒的過程,不可思議的療癒!簡直就是舒壓按鈕,但看起來有多一點意義?!最後,放個《大橋 1988:自由年代》的活動紀錄影片作為結尾。