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

第77話:イトは、fpsを上げなかった|音だけ80 ms遅れた?

ピコルート第77話。停止frameは3.000秒、警告音は3.080秒。イトはfpsでごまかさず、映像と音のpresentation timestampを同じ時間軸へ戻します。

動画データフレームpresentation timestamp映像と音の同期10分更新

第76話で分かれたblue toneとamber toneのtrayを、イトはanimation screenへつないだ。

low toneは、最初のframeを開く合図。

high toneは、停止frameで画面を止める合図だ。

六秒だけのtest animationを再生する。

三秒のところで、画面の人物がred leverへ手を置いた。

amber toneが鳴る。

けれど音が出たときには、leverの先にある二枚のframeがもう画面へ出ていた。

stop video frame   3.000 s
amber audio block  3.080 s
audio offset       +80 ms
late frames        2

イトは、video側の60 fps presetへ手を伸ばした。

「絵を増やして滑らかにすれば、音も追いつくかもしれない」

次のhandoffでは、停止frameとamber toneが同じ瞬間にそろわなければならない。

音が二枚遅れれば、止めるはずのframeをoutputへ渡してしまう。

絵を増やしても、音の時刻は戻らない

ユイは元の六秒を保ったまま、60 fpsのpreviewを一件だけ作った。

途中の絵が増え、leverへ伸びる手は滑らかに動いた。

それでもamber toneは、3.080秒で鳴った。

videoの密度を変えても、audio blockへ付いた時刻は変わっていない。

イト

fpsは一秒へ置く絵の数。音をいつ鳴らすかまで、自動では直してくれないんだ

ユイ

前話のsample rateも、音の中を測る細かさでした。videoとの待ち合わせ時刻とは別です

マコト

絵の列と音の列を、同じ時計の上で比べよう

Picoは60 fps presetにもaudio railにも触れない。

videoとaudioの先頭へ、一本のcyan lightを通しただけだった。

三つの直し方

A:fpsを30から60へ上げる

一秒あたりのframe数は増える。

けれど今回の+80 ms offsetを作ったaudioのtime originは残る。

B:口の動きを見ながら、音を少しずつ左へずらす

演出として音の位置を決める編集なら、目と耳の判断も必要だ。

しかしsource markerを確認せず毎回ずらせば、なぜ80 ms遅れたかも、別の箇所まで同じ量だけずれているかも分からない。

C:二つのtrackをcommon media timelineへ写し、timestampを比べる

sourceで同時だったmarkerを一件決める。

video frameとaudio blockのpresentation timestampを同じtime originで比較し、誤ったtimeline mappingをoutput copyで直す。

イトは60 fps previewを閉じた。

目分量でaudio waveformを動かすpanelも閉じる。

「C。絵の枚数ではなく、二つが何秒を名乗っているかを調べる」

frameは、一枚の絵と表示時刻を持つ

videoは、時間に沿って表示するframeの列として扱える。

このconstant-rate fixtureは30 fps。

一frameの長さは約33.333 msだ。

one second / 30 frames = 0.033333... s per frame

先頭をindex 0とすると、frame index 90は3.000秒から始まる。

frame rateは一秒へ何枚置くかを示す。

しかし、audioの一sampleをどのvideo frameへ合わせるかは、30と16,000という二つのrateを見比べるだけでは決まらない。

必要なのは、両方を同じ時間軸へ置く手掛かりだ。

presentation timestampが、いつ見せるかを示す

presentation timestampは、そのframeやaudio dataをmedia timelineのいつ提示するかを示す時刻だ。

durationは、そこからどれくらい続くかを示す。

WebCodecsのVideoFrameとAudioDataにも、presentation timestampがmicrosecond単位である。

Media Source Extensionsでは、coded frameのpresentation timestampがrenderする時刻を示し、trackのtimestampを同じmedia timelineへmapする。

decodeする順番の事情は別にある。

この話で直すのは、見せる時刻と鳴らす時刻だ。

video frame
  presentation timestamp  3.000000 s
  duration                ~0.033333 s

audio block
  presentation timestamp  3.080000 s
  duration                 0.020000 s

別々のtrackでも、同じtimelineの3.000秒を名乗れば同じpresentation位置へ置ける。

同じ順番で保存されていることや、近くに並んでいることだけでは足りない。

イトがaudio trackのtime originを戻した

イトはsource video frameとsource audio sampleをread-onlyで固定した。

三秒markerの元記録を開く。

leverへ触れた光とamber toneは、sourceでは同じ3.000秒に発生している。

ところがhandoff時に、audio trackのtime originだけへ+80 msが足されていた。

内容の音が遅いのではない。

output timelineへ置く時刻が遅い。

イトは自分の手で、output copyのaudio track mappingを-80 ms戻した。

イトがparallelに並ぶblue video railとamber audio railの間で、二slot遅れていた一つの音声pulse cartridgeを、停止frameと同じcyan presentation gateの真下へ両手で固定している
frame数を増やさず、videoとaudioが名乗るpresentation timeを同じ起点へ戻す。
before
  video marker  3.000 s
  audio marker  3.080 s
  offset        +0.080 s

after
  video marker  3.000 s
  audio marker  3.000 s
  offset         0.000 s

sourceのframe pixelも、audio sample値も変えていない。

直したのは、output trackをcommon timelineへ写す規則だ。

一点だけ合わせず、最初・中・最後を見る

三秒だけ合っても、六秒の最後でまたずれるなら修理は終わっていない。

イトは、sourceで同時だったmarkerを三か所選んだ。

position   before offset   after offset
start          +80 ms          0 ms
middle         +80 ms          0 ms
end            +80 ms          0 ms

三か所とも同じ+80 msなら、今回のようなfixed offsetを疑える。

もし0 ms → +40 ms → +80 msのように差が広がるなら、単純な一回のshiftでは隠さない。

clock rate、timestamp換算、欠けたdataなど、時間とともに増えるdriftの原因を別に調べる。

目と耳で一か所だけ合ったことを、全編のsync完了にはしない。

停止frameと警告音が、同時に届いた

イトは六秒のfixtureを、最初からもう一度流した。

3.000秒。

画面の人物がred leverへ触れた瞬間、amber toneが鳴る。

停止frameの先にあった二枚は、今度はoutputへ出なかった。

late warning frames       0
start / middle / end      0 ms
source video changes      0
source audio changes      0
timeline mapping changes  1

イトは三つのmarkerを自分で照合し、そこで初めてvideo packageのhandoffを許可した。

blue frame railとamber audio railは、一本のcyan gateの下で同時に閉じた。

fps、sample rate、syncを混ぜない

fpsは、一秒へ置くvideo frameの数。

sample rateは、一秒間に取るaudio sampleの数。

presentation timestampは、それぞれを共通のmedia timeのどこへ置くか。

containerはtrackとtimestampを運べる入れ物、codecは映像や音をencode / decodeする規則だ。compressionやresolutionの調整も、今回のfixed offsetとは別の問題になる。

最初の一手は、fpsを上げることでも、音量を変えることでもない。

1. sourceで同時だったmarkerを決める
2. video / audio timestampを同じtime originへ写す
3. offsetが固定か、時間とともに広がるかを見る
4. sourceを保護してoutput mappingを直す
5. start / middle / endを一件ずつ再生する

source上の正しい時刻が分からないなら、目分量の位置を事実として上書きしない。

演出として選ぶ位置と、記録上同時だった位置を分けて残す。

そろっているのに、画面全体が遅かった

video packageのframeとaudioは、同じ時刻にそろった。

マコトがlive cameraを一台つなぐ。

イトが手をたたく。

遠くのscreenでも、手が合わさる映像と音は同時だった。

けれど、現実の拍手からscreenの拍手までは、少し待たされた。

audioだけが遅いのではない。

videoだけが遅いのでもない。

そろった二つが、まとめて後から届いている。

イトは、同じcyan gateを通る二本のtrackを見た。

絵の枚数で音の時刻を直さなかったから、遅れている場所を取り違えずに済んだ。

「映像と音が合っていても、今この瞬間より遅いのはどうして?」

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

ライブ配信は、なぜ少し遅れて届く?

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

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

動画データの仕組みとは?フレーム・fps・圧縮の違いを読む