FFmpeg 9.1 AAC 編碼器重寫
FFmpeg 9.1 AAC 編碼器重寫
FFmpeg 9.1 引入了一個全新重寫的原生 AAC 編碼器,旨在取代先前次優的原生實作。新編碼器在各種位元率下提供更優秀的音訊品質,於 Google 的 Zimtohrli 與 ViSQOL 等指標上超越 fdk-aac 與 Apple 的 qaac。
技術架構與最佳化
全新編碼器從頭開始重寫了速率控制、率失真最佳化(RDO)以及所有核心編碼工具。主要技術改進包括:
- 完整 RDO 整合:所有編碼工具——包括感知噪聲置換(PNS)、時間噪聲整形(TNS)、強度立體聲(I/S)與中/側(M/S)編碼——皆納入 RDO 迴路。編碼器不會使用任意的位元率截斷或啟發式規則,而是僅在給定位元預算下提供最佳品質的工具。
- 感知最佳化:不同於某些競爭者僅依賴簡單的頻段能量曲線,新編碼器使用受遮蔽的頻段能量進行 RDO,以更好地將位元分配給可聽頻率。
- 嚴格的 CBR 實作:編碼器針對恆定位元率(CBR)進行最佳化,因為固定的位元預算目標能顯著提升編碼效率。開發者建議不要使用
-q:a(真實 VBR 模式)。 - 策略性頻段歸零:編碼器會透過歸零或 PNS 處理受遮蔽的頻段,故意在頻譜圖中留下「洞」。此設計優先確保可聽頻段的高品質編碼,而非嘗試以低品質編碼所有頻段。
效能基準
根據開發者的說法,新編碼器(特別是 nmr 編碼器)在大多數位元率下,於 Zimtohrli 與 ViSQOL(Zim 越低、ViS 越高越好)測量中均優於 fdk-aac 與 Apple 的編碼器。
| 位元率 (kbps) | 8.1 fast | 8.1 twoloop | nmr | fdk-aac | apple | libopus |
|---|---|---|---|---|---|---|
| 64 | 0.01315 / 2.65 | 0.00696 / 3.24 | 0.00309 / 3.83 | 0.00322 / 3.69 | 0.00612 / 3.29 | 0.00100 / 4.59 |
| 96 | 0.00338 / 3.77 | 0.00268 / 3.99 | 0.00134 / 4.04 | 0.00153 / 3.98 | 0.00175 / 3.87 | 0.00039 / 4.62 |
| 128 | 0.00229 / 4.10 | 0.00170 / 4.28 | 0.00072 / 4.47 | 0.00143 / 4.27 | 0.00081 / 4.44 | 0.00020 / 4.68 |
| 160 | 0.00129 / 4.30 | 0.00108 / 4.44 | 0.00051 / 4.56 | 0.00065 / 4.31 | 0.00117 / 4.51 | 0.00084 / 4.68 |
| 256 | 0.00105 / 4.41 | 0.00121 / 4.55 | 0.00031 / 4.61 | 0.00103 / 4.45 | 0.00067 / 4.63 | 0.00002 / 4.73 |
註:表中列出 Zim / ViS 數值。整體而言 Opus 仍是最佳表現者。
使用指南與限制
為了在新編碼器上取得最佳效果,使用者應遵循以下特定設定:
- 取樣率:編碼器主要針對 48kHz 音訊進行最佳化。雖然支援 44.1kHz 與 96kHz,但建議使用 48kHz 以獲得最高品質。
- 混音:若輸出預計會被混音,下混時應使用
-aac_is 0 -aac_pns 0以保留原始訊號相位。 - 頻寬截斷:開發者建議在 128kbps 時將頻寬降低至 16kHz,160kbps 以上則降低至 18kHz,使用
-cutoff參數實現。
社群回饋與已知問題
在 HydrogenAudio 上的早期使用者測試指出以下幾點值得注意:
- 整體品質:使用者在 134kbps 與 200kbps 時報告「極致聆聽」體驗,明顯優於舊原生編碼器的「啁啾」雜訊。
- TNS 嘀嗒聲:有使用者在高位元率(192kbps)時聽到「嘀嗒聲」,在關閉 TNS (
-aac_tns 0) 後消失。開發者推測可能是libavcodec/aacenc_tns.c中過於激進的 TNS 設定所致。 - 低位元率立體聲影像:在 64kbps 立體聲下,有些使用者覺得新編碼器較舊編碼器更「模糊」或「金屬感」,開發者則指出 64kbps 通常對高品質立體聲 AAC 來說過低。
命令列範例
對於轉換至新編碼器的使用者,建議使用以下指令:
# 標準高品質編碼
ffmpeg -i input.flac -map 0:0 -c:a aac -b:a 128000 output.m4a
# 編碼時停用強度立體聲以保留相位
ffmpeg -i input.flac -map 0:0 -c:a aac -aac_is 0 -b:a 128000 output.m4a
# 編碼時停用 PNS 以保留相位
ffmpeg -i input.flac -map 0:0 -c:a aac -aac_pns 0 -b:a 128000 output.m4a