テレビのアニメはどこから来る? / 第78話

第78話:イトは、bufferを0にしなかった|ライブなのに420 ms遅い?

ピコルート第78話。映像と音は合っているのに420 ms遅い。イトはbufferを0にせず、配信経路をstage別に測って最大の待ち時間だけを縮めます。

ライブ配信エンコード遅延バッファとジッター10分更新

第77話のlive cameraの前で、イトはもう一度手をたたいた。

現実の手が合わさる。

遠くのscreenでも、videoとaudioはぴたりと合っている。

けれどscreenの拍手は、420 msあとだった。

audio / video offset    0 ms
end-to-end latency    420 ms
viewer stalls           0

二本のtrackのtime mappingは直っている。

今度は、そろった二本がまとめて遅い。

イトはviewer側のbuffer dialへ手を伸ばした。

「待っている箱を0にすれば、もっと今に近づける」

次のrehearsalのacceptance lineは、end-to-end 320 ms以下、stall 0、audio / video offset 0。

同じarrival jitter traceを流し、三つを同時に満たさなければhandoffできない。

bufferを0にすると、画面が四回止まった

ユイは、viewer buffer 0の試作を一件だけ再生した。

screenの拍手は420 msから360 msへ近づいた。

しかしnetworkから届く間隔が揺れたところで、frameが足りなくなる。

六秒のtest中に、画面は四回止まった。

viewer buffer target    0 ms
end-to-end latency    360 ms
viewer stalls           4
acceptance             FAIL

速く始めても、次のdataがpresentation時刻までにそろわなければ滑らかには続かない。

イト

待ち時間を全部なくすと、届く間隔の揺れを受け止める場所までなくなるんだ

ユイ

遅延を一つの箱だけのせいにせず、captureからscreenまで分けて測りましょう

マコト

残す待ちと、縮められる待ちを見分けるんだね

Picoはbuffer dialにもpipeline gateにも触れない。

cameraとscreenの間へ、五つのcyan markerを置いただけだった。

三つの直し方

A:viewer bufferを0にする

意図的な待ちは一つ減る。

けれど今回のjitter traceではstallが増え、320 msのlineにも届かなかった。

B:resolutionとbitrateを先に下げる

encode処理やupload容量がbottleneckなら、有効な場合がある。

しかし今回の測定前に画質を落としても、どのstageが180 ms待っているかは分からない。

C:同じunitへstage timestampを付け、largest controllable waitを一つ縮める

captureからviewer presentationまでを分ける。

合計だけでなく、各stageの差を見てから一か所だけ変え、同じjitter traceで再試験する。

イトはbuffer 0試作を閉じた。

resolution presetも元へ戻す。

「C。全部を急がせず、いちばん長く止めている場所から直す」

live latencyは、途中で使った時間の合計

この話でいうend-to-end latencyは、cameraが一件をcaptureしてからviewer screenへpresentするまでの時間だ。

イトは、同じclap unitが各markerを通った時刻を並べた。

capture                         0 ms
encode ready                  +90 ms
chunk release                +180 ms
server / network arrival      +70 ms
viewer jitter buffer          +60 ms
decode / render               +20 ms
total                         420 ms

+90 +180 +70 +60 +20 = 420。

「回線が遅い」でまとめると、encodeやchunk holdやviewer準備の時間が見えなくなる。

反対に、server / network 70 msだけを0にしても、残り350 msは消えない。

この数値は六秒のclosed lab fixtureであり、すべての配信へ共通する内訳ではない。

protocol、codec、端末、回線、配信設定、混雑でstageも値も変わる。

jitterとbufferは、遅延と同じ言葉ではない

latencyは、captureからpresentationまでどれくらい離れたか。

jitterは、dataが届く間隔の揺れ。

viewer bufferは、届いたdataを少し持ち、揺れがあってもpresentationを続けやすくする待機場所だ。

W3C WebRTC Statistics APIには、sampleやframeがjitter bufferへ入ってから出るまでを積算するjitterBufferDelay、target delay、freezeなどの観測項目がある。

Media Source Extensionsのbuffer modelでも、再生位置に必要なdataが足りなければplayback interruptionにつながる。

bufferを大きくすれば必ず正解でも、0なら必ず最速の成功でもない。

今回必要なのは、同じjitter traceを止めずに通せる範囲を残すことだ。

180 msのholdだけが長かった

五つの差のうち、最長はchunk release前の180 msだった。

encoderは90 msでunitを作り終えている。

それなのにpackaging gateが、次のまとまりを待って180 ms保持していた。

イトはsource video / audio、codec、resolution、bitrateを固定した。

viewer jitter buffer 60 msも外さない。

自分の両手で、center queueのhold gateだけを180 ms notchから60 ms notchへ移す。

イトがcameraとviewer screenを結ぶlive pipeline中央で、blue videoとamber audioが一体のcapsuleを早くreleaseするためlarge hold gateだけを両手で短くし、right側のcyan bufferは接続したまま残している
viewer bufferを外さず、測定で最長だったcenter queueのholdだけを縮める。
changed stage       chunk hold
before                    180 ms
after                      60 ms
viewer buffer              60 ms kept
source media changes        0

small chunkを早くreleaseすれば、送る回数やheader overheadなど別のtrade-offが増える場合もある。

だから60 msを全配信の正解にはしない。

このfixtureで一か所を変え、結果を測る。

一本のstreamを、途中で分けて届ける

encodeされたblue videoとamber audioは、一つのpaired unitとしてserverへ進んだ。

配信者がviewer一台ずつへ同じdataを直接作り直さなくても、serverやdelivery拠点から複数のviewerへ分けて届けられる構成がある。

server、CDN、edgeなどの名前だけを覚えても、delay budgetは決まらない。

どの地点で受け取り、どこで待ち、いつviewerへ渡したかを同じunitで追う。

420 msが300 msになり、四回の停止も消えた

イトはbuffer 0試作で使ったarrival jitter traceを、そのまま再注入した。

arrival variation   12 ms, 47 ms, 55 ms, 18 ms
viewer buffer       60 ms

frameはpresentation前にそろい、六秒のscreenは一度も止まらない。

audio / video offsetも0 msのままだ。

end-to-end latency    300 ms
viewer stalls           0
audio / video offset    0 ms
dropped test units      0
acceptance             PASS

90 + 60 + 70 + 60 + 20 = 300。

イトは同じclapを三回流し、各stage markerとviewer resultを自分で照合した。

そこで初めて、live routeのhandoffを許可する。

viewer bufferは消えていない。

不要に長かったholdだけが、120 ms短くなった。

速くする前に、どこで待ったかを見る

今回の最初の一手は、bufferを0にすることではない。

1. captureとviewer presentationへ同じunitのmarkerを置く
2. stageごとの差とtotalを出す
3. largest controllable waitを一つ選ぶ
4. source条件を固定して一か所だけ変える
5. 同じjitter traceでlatency / stall / syncを再確認する

もし最大がencodeなら、codec設定や処理能力を調べる。

uploadが詰まっているなら、bitrateや回線条件が先になることもある。

offsetやstallが試行ごとに変わるなら、一回の最小値だけで完了にしない。

短い数字ではなく、同じ条件で続けて届くかを見る。

viewerからの光だけが、別の道を戻った

live screenは、audioとvideoをそろえたまま300 msで届いた。

遠くのviewerが、screenの横にあるcyan buttonを押す。

その反応の光は、video packageの枝を逆向きに戻らなかった。

細い別のrailへ入り、配信者側のlampを点けた。

viewerへ送るone-way streamと、viewerから返すsignalは同じ荷物ではない。

イトはcameraからscreenへ進む太いrailと、screenから戻る細いrailを見比べた。

bufferを全部外さず待ち場所を測ったから、今度は「戻り道」を送り道の遅さへ混ぜずに済んだ。

「見るだけの道に、返事の道を足すと何が変わるの?」

次回、ピコルート第79話。

リアルタイム通信は、どうやって往復する?

この物語を、解説で深める

第78話で生まれた疑問を、解説記事で少し深く見ていきます。物語で感じた不思議さを残したまま、言葉と仕組みを順番に整理しましょう。

ライブ配信の仕組み|今の映像と音をほぼリアルタイムで届ける流れを読む