Remotion LabRemotion Lab
媒體整合Audio Pitch:用 playbackRate 改音高——窮人版的 pitch shift
audiopitchplayback-ratesfxintermediate

Audio Pitch:用 playbackRate 改音高——窮人版的 pitch shift

用 Remotion 的 playbackRate 一行字把音效變低音/高音。原理是「速度跟音高綁在一起」,做出來的 BASS / CHIPMUNK 效果免費又好用。順便講為什麼這不是真正的 pitch shift。

成品預覽

一個 source chime 透過三條不同的 playbackRate 線分別播放——1.0(原版)、0.6(低八度)、1.5(高八度)。同一個音檔,三種感覺,沒有外掛、沒有 ffmpeg、就是 Remotion 內建的一個 prop。


這篇會做出什麼

把同一個音效檔變成三種不同個性的聲音:

  • ORIGINAL (playbackRate=1.0):原版
  • BASS (playbackRate=0.6):降速 40%,音高同時降低八度,變成「重低音」
  • CHIPMUNK (playbackRate=1.5):加速 50%,音高升高,變成「卡通松鼠」

整篇只教一個技術<Audio playbackRate> 這個 prop。


前置知識


Step 1:基礎用法

Claude Code:

新增 Composition "PitchDemo":
- 1920x1080 fps 30 durationInFrames 300(10 秒)
- 新建 src/compositions/PitchDemo.tsx 並在 Root.tsx 註冊

掛三個 <Audio>,全部用同一個 source 檔,但 playbackRate 不同:

<Sequence from={30} durationInFrames={50}>
  <Audio src={staticFile("audio/chime.mp3")} playbackRate={1.0} />
</Sequence>
<Sequence from={90} durationInFrames={50}>
  <Audio src={staticFile("audio/chime.mp3")} playbackRate={0.6} />
</Sequence>
<Sequence from={150} durationInFrames={50}>
  <Audio src={staticFile("audio/chime.mp3")} playbackRate={1.5} />
</Sequence>

播一次:你會聽到同一個 chime 變成三個完全不同的聲音。第一行字就讓你做出 pitch shift

💡 playbackRate 對音訊與影片都有效,完整行為在 /docs/audio-pitch


Step 2:原理——為什麼速度會改音高?

數位音訊就是一串波形 sample(例如每秒 44,100 個點)。playbackRate=0.6 等於:

「把每個 sample 之間的時間拉長 1.67 倍」

時間拉長 → 波形變慢 → 頻率變低 → 聽起來音高下降

數學上:新音高 = 原音高 × playbackRate

playbackRate聽感半音差
0.5降一個八度−12
0.6降六度−9
0.8降三度−4
1.0原音0
1.2升三度+3
1.5升五度+7
2.0升一個八度+12

知道這張表你就能用 playbackRate 「彈奏」任何音效——例如 4 個不同 rate 的 kick drum 就是一條 bassline。


Step 3:實戰應用

A. 重低音版本的 SFX

UI 音效(pop / whoosh / ding)通常是中高頻。想做「重磅落地」感:

// 普通 whoosh
<Audio src={staticFile("audio/whoosh.mp3")} playbackRate={1.0} />
 
// 重低音版本(搭配畫面震動更有感)
<Audio src={staticFile("audio/whoosh.mp3")} playbackRate={0.55} volume={1.0} />

一個 whoosh 檔案可以有「飛行版」(1.0)、「砸地版」(0.6)、「微氣流版」(1.4)三個不同用途。

B. 卡通對話

把人聲錄音的 playbackRate 開到 1.4~1.6,瞬間變成卡通松鼠的對話。<Audio><OffthreadVideo> 都吃這個 prop,可以視訊一起變速。

C. 自製 bassline

把同一個 piano hit 用不同 playbackRate 排成一條 sequence:

const NOTES = [
  { from: 0,  rate: 0.50 }, // C2
  { from: 30, rate: 0.56 }, // D2
  { from: 60, rate: 0.63 }, // E2
  { from: 90, rate: 0.67 }, // F2
];
 
{NOTES.map((n, i) => (
  <Sequence key={i} from={n.from} durationInFrames={30}>
    <Audio src={staticFile("audio/piano-c4.mp3")} playbackRate={n.rate} />
  </Sequence>
))}

一個 piano sample,零成本做出旋律。


Step 4:limitation——為什麼這不是「真的」pitch shift

專業 DAW(Pro Tools、Ableton)的 pitch shift 可以做到:

改音高、不改速度

Remotion 的 playbackRate 做不到——它是「速度跟音高綁在一起」的單一 knob。

需求Remotion playbackRate真正的 pitch shift
改音高
改速度✅(強制)❌(可以保持)
即時、無 artifact❌(需要相位重建演算法)
一行 prop 搞定❌(要外掛 / ffmpeg)

什麼時候 Remotion 夠用:SFX(whoosh、kick、impact、pop)。這些東西本來就短促、不在乎速度被改、不在乎變調 artifact。

什麼時候要用 ffmpeg:人聲對話、主旋律樂器、長音樂段——這些東西必須保持速度但改變音高。預先用 ffmpeg 的 rubberband filter 處理:

ffmpeg -i in.mp3 -af "rubberband=pitch=0.5" out-bass.mp3

然後在 Remotion 用 <Audio src={staticFile("out-bass.mp3")} /> 載入處理過的版本。

💡 audio-pitch 的進階用法、限制與替代方案在 /docs/audio-pitch


Step 5:讓 playbackRate 動態變化

playbackRate 一經 <Audio> 設定就是固定的,不能寫成 frame 函式——因為 Remotion 要靠這個值規劃整段音訊在 timeline 上的長度。

想要「音高漸變」效果(例如 pitch sweep),用兩種方法:

方法 1:多段拼接

{[0.6, 0.7, 0.8, 0.9, 1.0].map((rate, i) => (
  <Sequence key={i} from={i * 6} durationInFrames={6}>
    <Audio src={staticFile("audio/tone.mp3")} playbackRate={rate} />
  </Sequence>
))}

每 6 幀換一段更高的 rate,聽起來像 pitch up sweep。

方法 2:預先處理

用 ffmpeg 的 asetrate filter 預先做出 sweep 版本:

ffmpeg -i tone.mp3 -af "asetrate=44100*1.5" tone-sweep.mp3

然後 Remotion 直接 <Audio src=…> 載入。


Step 6:渲染

渲染 PitchDemo:
- 1920x1080 H.264
- 音訊 codec aac
- 音訊 bitrate 192k
- 輸出 out/audio-pitch.mp4

戴耳機聽——三段 chime 的音高高低差很明顯,但也聽得出來時間長度也跟著變了(BASS 比 ORIGINAL 久、CHIPMUNK 比 ORIGINAL 短)。這就是 playbackRate 的本質。


完成!回顧學到的概念

概念重點
<Audio playbackRate>一個數字改速度 + 音高
速度 ↔ 音高公式新音高 = 原音高 × playbackRate
八度數學0.5x = −12 半音2.0x = +12 半音
只能設靜態值想動態變化要拼多段 Sequence
不是真 pitch shift速度也會跟著變;只適合 SFX

本篇涵蓋的官方文件


常見問題

Q:playbackRate={2} 把 1 秒的音檔變成 0.5 秒,那 <Sequence durationInFrames={30}> 裝得下什麼? A:Remotion 會在 sequence 結束時自動截掉沒播完的部分。如果你的 sequence 比加速後的音訊還長,多出來那段就是靜音。

Q:playbackRate={0.5} 會讓音檔變兩倍長嗎? A:是。<Sequence durationInFrames> 要相對應地給足時間,不然會被切掉。

Q:可以把 playbackRatevolume 函式同時用嗎? A:可以。volume 接函式、playbackRate 接靜態值,互不干擾。

Q:低 playbackRate 為什麼會出現 artifact(像 robot 聲)? A:digital sample 之間靠 interpolation 補出來——速度越慢,補的點越多,artifact 越明顯。0.6 還可以接受,0.3 以下就會很明顯。

Q:播放 mp3 跟 wav 結果有差嗎? A:理論上沒有。實務上 mp3 在低 bitrate(<128k)做大幅度 pitch shift 時 artifact 會比 wav 明顯。


下一步

有問題歡迎到 FB 社群 討論!