(文章)

在瀏覽器裡輸出 MP3:離線算繪、編碼區塊與取樣時間軸

網頁取樣機用離線算繪排出整首卡帶,單聲道編成 192 kbps MP3,再輸出完整音檔或各音色 ZIP。

磨人開發團隊・2026-02-20

目錄

網頁取樣機的使用者編完卡帶之後,需要一個能帶走、能上傳、能放進剪輯軟體的 MP3。這份檔案由編曲引擎在瀏覽器內直接算出,不經過伺服器混音,也不錄製即時播放的聲音。本文依序說明算繪、後處理、編碼、兩種輸出與取樣檔的時間軸。即時播放用的排程與時鐘另見 取樣機的拍點時鐘設計,這裡只談輸出。

輸出改用離線算繪,不錄製即時播放

錄製即時播放的聲音,輸出要等整首播完,所需時間等於作品長度;手機切換應用程式時,音訊也可能暫停。

離線算繪不必等待播放,也不依賴播放當下的裝置狀態。W3C 的 Web Audio API 規格中,OfflineAudioContext 的時間軸不與即時播放時鐘綁定,結果寫進一個 AudioBuffer;MDN 的說明說明這個介面不輸出到裝置硬體,而是盡可能快地產生結果,寫進 AudioBuffer。每個音符的位置由排程時間決定,與播放當下的瀏覽器狀態無關。

圖 1卡帶在瀏覽器內經五個步驟變成 MP3,全程不經過即時播放
  1. 卡帶資料4 個序列、12 個音色格
  2. 離線算繪重建音訊圖,依序列、音色格、步數排程
  3. 整包後處理Limiter 與整體降 3 dB
  4. 轉為單聲道取得 Float32 取樣點
  5. MP3 編碼192 kbps,每次 1152 個取樣點

流程依輸出整包完整音檔的路徑繪製。

用同一份卡帶資料重建音訊圖

編曲資料是 4 個序列,每個序列有 12 個音色格,每格 32 個步;一步是一個 8 分音符,一小節 8 步,所以 32 步等於 4 小節。每個序列各自設定 1 到 4 小節的 loop 長度。即時播放與離線算繪讀的是同一份序列、音色格與步資料。

輸出時呼叫 Tone.js 的 Tone.Offline,傳入一個回呼函式與總長度(秒)。回呼在獨立的離線環境裡執行,音訊圖要在裡面重建:每個有資料的音色格建立一個 player,接上 PitchShift 與 Filter,再接到全域處理的輸入或主通道。

排程只用一次 transport.scheduleOnce,時間點是 0:0:0。回呼裡用序列、音色格、步數三層迴圈,對每個啟用的步直接呼叫 player.start,並在同一時間點設定音量。第 N 個序列的起點,是前面 N-1 個序列的長度總和,四個序列因此依序排成一條連續的時間軸。

總長度由四個序列的 loop 長度與 BPM 算出:每個序列的秒數是 loop 小節數 × 8 × (60 ÷ BPM ÷ 2)。BPM 預設 120,此時一步 0.25 秒,一小節 2 秒;四個序列各設 2 小節,總長就是 16 秒。輸出長度只取決於 loop 長度與 BPM,與放了幾個音無關。

一人蹲著,用扳手鎖緊藍色管線接頭的螺栓,地上擺著幾段管子。

整包輸出前的處理與單聲道

整包輸出時,全域處理鏈的輸出會先經過 Limiter,門檻 -1 dB,整體再降 3 dB,為多個音色同時發聲時的疊加留出餘量。處理完成後,取得的 AudioBuffer 轉成單聲道,交給編碼器。

MP3 編碼:lamejs、192 kbps 與 1152 個取樣點

編碼用 lamejs,這是能在瀏覽器內執行的 MP3 編碼器,建立方式是 Mp3Encoder(聲道數, 取樣率, kbps)。聲道數與取樣率直接取自算繪出來的 buffer,位元率設為 192 kbps。

編碼分區塊進行。MIT Media Lab 的 MPEG Audio FAQ說明 Layer III 把聲音切成 1152 個取樣點的區塊,這是二手整理,不是 ISO 原文。lamejs 的 README 範例同樣取 1152,註解說明區塊大小可以任意,取 576 的倍數對編碼器較省力。這套編曲引擎每次餵給編碼器 1152 個取樣點。

Web Audio 的取樣點是 -1 到 1 之間的浮點數,編碼器吃的是 16 位元整數。轉換時先把每個值夾在 -1 到 1 之間,負值乘 32768,正值乘 32767,剛好對應 int16 的範圍 -32768 到 32767,不會溢位。

項目設定
算繪Tone.Offline,總長由 loop 長度與 BPM 算出
聲道單聲道
編碼器lamejs 的 Mp3Encoder
位元率192 kbps
每次編碼1152 個取樣點
浮點轉整數夾在 -1 到 1,負值乘 32768、正值乘 32767
輸出型別Blob,audio/mp3

兩種輸出:完整音檔與各音色 ZIP

輸出視窗提供兩種結果。完整音檔是整首卡帶混成的單一 MP3;各音色 ZIP 則把每個音色各自算繪,再打包成壓縮檔,每個音色可以單獨取用。

圖 2輸出依用途分成三條路,公開卡帶一律上傳完整音檔
  1. 卡帶完成編排尚未編排時先顯示提示
  • 要一份完整的成品
    單一 MP3整包算繪,下載到使用者的裝置
  • 要在剪輯軟體裡逐音色調整
    各音色 ZIP每個音色各算繪一次,打包成 download.zip
  • 公開卡帶
    上傳完整音檔上限 20 MB,只收 MP3

各音色 ZIP 的做法如下。

  • 12 個音色格逐一檢查,有取樣、且四個序列中至少有一步落在 loop 範圍內的格子才輸出。
  • 每個音色格各跑一次 Tone.Offline,同樣取單聲道、同樣以 lamejs 編碼。
  • 檔名依格子編號為 sample-0.mp3 到 sample-11.mp3,用 JSZip 打包成 download.zip 下載。

公開卡帶前,系統會要求先輸出一份完整音檔並上傳。檔案以表單送到後端,後端只收 MP3,大小上限 20 MB,成功後回傳檔案網址;前端把網址與輸出時間記進卡帶資料。

成員把一張張卡片歸進大櫃子的抽屜

取樣檔的時間軸

MP3 以固定長度的 frame 編碼,多數編碼器會在檔案開頭加入一段延遲,不同軟體輸出的延遲長度也不相同。播放端若沒有補償,檔案開頭就多出一小段靜音。單次播放聽不出差異,但取樣在序列中循環時,每一圈都從頭開始,起點與拍點之間的偏移固定存在,多個音色同時發聲時,拍點就對不齊。

取樣機的做法是在上傳時處理。使用者上傳的 MP3 與 WAV,後端先轉成未壓縮的 AIFF,再用同一條流程轉成 MP3。所有取樣都由同一個編碼流程輸出,開頭的延遲不再隨來源軟體改變。前端不必逐檔偵測開頭的靜音長度,也不必替各軟體的差異各寫一套補償。

輸出前的提示

公開卡帶前必須先輸出完整音檔。卡帶尚未編排任何步時,輸出視窗會顯示「尚無打擊音樂,無法輸出音檔」,並提供「如何打擊」的入口,引導使用者先完成編排。

不適合離線算繪的情境

OfflineAudioContext 建立時就要指定長度,整段結果存放在記憶體裡。需要即時錄下麥克風或外接樂器的輸入,或是輸出長度事先未知的場景,改用錄製路線較合適。長度由 loop 與 BPM 決定的卡帶輸出,則符合離線算繪的前提。

延伸閱讀與官方教學影片

取樣機的整體做法與使用情境,見 北流雲取樣機案例;即時播放的拍點排程見 網頁步進編曲的時鐘設計。

輸出與取樣的操作示範,可看官方教學影片:3-2 卡帶編輯與輸出、2-1 錄製音色取樣。

網頁上需要音訊算繪、匯出或取樣功能,可從 網頁互動功能開發 了解範圍,並透過 說明網頁音訊功能的需求 與開發團隊聯繫。

(聯絡)

Start a project.

三個步驟,取得可判斷的做法與預算區間。

  1. 01預約第一場會議:選擇時段,不需要完整規格。
  2. 02線上諮詢 15 至 30 分鐘:取得做法方向、預算區間與時程草案。
  3. 03檢視素材後,約 3 至 5 個工作天提供報價單暨交付規格明細表。
信箱
hello@polish-design.com.tw
通訊地址
(104) 台北市中山區植福路191-1號3F

預約第一場會議

週一至週五 16:00–18:00線上 30 分鐘

先選時段,再用 Google 帳號或信箱確認,預約完成可加入行事曆。

選擇時段

或先送出資料

還沒想好時段,可以先留下專案內容,專人以信箱回覆。送出後也能接著預約。

補充資料(選填):服務項目、目前階段、現有連結、得知管道

資料僅用於本次專案評估。

ISO/IEC 27001:2022 證書

(Certificate)

ISO/IEC 27001:2022

驗證機構
ARES International Certification
驗證範圍
互動沉浸式 3D 系統之開發流程,及網路與基礎設施之維運與管理。

到驗證機構網站查證