播放緩衝區(playout buffer)
想像一個必須以完全穩定速度轉動的水車,由一條壓力時強時弱的水管供水。若你把水管直接接到水車上,它會一頓一頓的。於是你先讓水匯集到一個小水箱裡,再以固定速率從水箱取水——水箱吸收了那些起伏。播放緩衝區就是抵達媒體的那個水箱:接收端上的一個短佇列,封包以(因抖動而不均勻的)抵達順序落入其中,播放器則從中以平順、固定的速率取用。
它的運作方式是刻意延遲播放。當媒體開始抵達時,接收端不會立刻播放第一個封包;它會等待一段選定的時間——比方說 60 毫秒——累積一點儲備。然後它以固定的時程開始播放,於是第 n 個封包在它的時間戳加上那個固定偏移量時播放。只要某個封包在其排定的播放時間之前出現,抖動就是看不見的:緩衝區有一個墊子可以取用。這個墊子的大小是核心的取捨。較大的緩衝區藏住更多抖動,卻替每一個字都加上更多延遲;較小的緩衝區感覺更靈敏,卻讓遲到的封包錯過它的時段,那就算作遺失。有些系統會隨量測到的抖動起落而調整緩衝區大小。
為什麼重要:播放緩衝區是即時媒體中最重要的單一用戶端技巧,它體現了一個深刻的取捨——你花一點延遲,換來大量的平順。對延遲幾乎無所謂的儲存式串流,緩衝區可以很大(數秒)。對每一毫秒延遲都會傷害品質的即時對話,它必須維持很小(數十毫秒),這正是對話式媒體困難得多的原因。一個在排定播放時刻之後才抵達的封包是無用的,會被直接丟棄——所以緩衝區並未消除遺失,它把「過度遲到」轉換成遺失,再由遺失隱藏設法掩蓋。
接收端設了一個 60 毫秒的播放緩衝區。一個時間戳排定在 1000 毫秒播放的封包在 1040 抵達——在預算內,平順播出。較後一個排定在 1200 的封包直到 1280 才到,超過了它 1260 的期限;它被當作遺失而丟棄,再由隱藏填補那 20 毫秒的空缺。
緩衝區藏住夠準時的封包;超過期限的封包則變成遺失。
播放緩衝區用延遲換平順——它無法兩者兼得。調整它的大小是一場拉鋸:太小,遲到的封包會遺失;太大,對話會覺得遲鈍。