観る画面の作り
ライブ・追っかけ・録画の観る画面の作りです (手を入れる人向け)。使い方は watch.md。
操作まわりは3画面で共通
Section titled “操作まわりは3画面で共通”同じものを2つ書かない。 ライブ (/live)・追っかけ (/chase/<id>)・観る画面
(/watch/<id>) はどれも映像の上にボタンを重ねる画面なので、部品は src/lib/components/player/ に寄せてあります。
| 何を持つか | |
|---|---|
icons.ts |
アイコン(Lucide。下)と、映像の上に置くボタンの色 |
Icon.svelte |
アイコン1つ(大きさと aria-hidden) |
ControlButton.svelte |
重ねるボタン。押されている間の見え方もここ。aria-pressed は切り替え (on を渡したもの) にだけ付け、名前は title にも出す (PC でマウスを重ねると読める) |
ControlBar.svelte |
映像に重ねる列。下端の操作バー(黒いぼかしつき)と、右端の縦の列(中身は画面ごと。上から観る画面は閉じる・切り抜き・削除、ライブは録画・d・切り抜き、追っかけは閉じる・切り抜き。丸は 48px (狭い枠は 40px) で、角から 8px、間も 8px。車に付けた全画面のタブレットで指が届くよう、横に寝かせず、閉じる・切り抜き・削除は映像の上に置く。観る画面の d は ⚙ の中)。スマホの縦でも下の操作バーは映像に重ね、触らなければ引っ込む |
controls.svelte.ts |
出すか消すかの決め方。マウスは動かせば、指は押せば出て、どちらも 2.5 秒で消える。止めていても消える(一時停止は映像の中の文字を見るためで、操作バーが残っては意味が無い)。残すのはキーボードで触っている間とメニューを開いている間だけ。消えている間は押せない (隠れた操作バーを押したつもりが映像に取られない) |
awake.svelte.ts |
観ている間、画面を暗くさせない(Wake Lock)。オン/オフは無く、止めている間も掛けたまま(一時停止して映像を見ている間に消えていた) |
frames.ts |
映した1枚ごとに呼ぶ。字幕の貼り直しと CM の跨ぎがこれに乗る(timeupdate は 250ms ごとにしか来ない) |
paint.ts |
字幕の面を映像が出ている枠に合わせる (fitRect。字幕の面と映像の縦横比が違うことがある) |
caption-draw.ts |
字幕の文字の配置を canvas に描く (ライブ・追っかけ・録画)。見えている大きさ (getBoundingClientRect。CSS の大きさは整数に丸めてあるので使わない) × 画面の画素で描き、全画面やデータ放送の小窓の出入りで描き直す。描き方は libaribcaption に揃えてある (api.md) |
caption-pref.ts |
字幕の出し入れと言語の覚え方 (3画面で同じ。端末ごと)。出し入れは既定で出す。言語は ISO 639 の名前で覚え、第何言語かは番組ごとに載っている言語から選び直す (無ければ第1言語)。選ぶのは再生の設定 (⚙) の「字幕」の行 (stream.md) |
PlayerStage.svelte |
舞台の枠。ポインタ・キー・全画面の配線と、黒地で 16:9 の枠。枠の大きさを測って詰め方を決める(幅 448px 未満か、16:9 より低く抑えられて高さ 300px 未満か、横にしたスマホ = data-compact。幅で compact で全画面でない = data-narrow: スマホの縦。読みものの上の段を省き、枠の高さの下限を外してちょうど 16:9 にする)。映像の上の通知 (StageNote) を積む列 (notes) も持つ。操作バーを映像に重ねている間は、操作バーと重なる字幕を操作バーの上まで持ち上げる (字幕の canvas の data-ink を見て translate) |
Extras.svelte |
狭い枠で「毎回は使わないもの」(音・字幕・速さ・Hybridcast・小窓)を操作バーから外し、再生の設定 (⚙) の頭に行として並べる (StageTail の fold。押すものは普通の行、切り替えはスイッチの行)。広い枠では何もしない。「ほか」(⋯) のボタンは無くした (狭い操作バーに ⋯ と ⚙ が並んでいた) |
MediaStack.svelte |
映像と重ねもの(前の映像・字幕 canvas)の束。データ放送を出すと、入れ物ごと BML の小窓へ寄せる (字幕も一緒に縮む) |
PlayerVeil.svelte |
ライブと追っかけの、読み込み中・失敗・待ちの幕 (観る画面は自前)。前の映像を貼っている間は塗り潰さない |
OverlayMenu.svelte |
映像の上のドロップダウンの共通部分(選択肢の並びと閉じ方)。開け閉めは画面のほかのメニューと同じ Menu.svelte (ブラウザの popover) |
StageTail.svelte |
操作バーの右端 (⚙・小窓・全画面。狭い枠では小窓も ⚙ の頭に入る)。3画面で同じ |
SettingsMenu.svelte / settings.ts |
再生の設定 (⚙)。端末ごとに決めて、たいていは決めたまま観るもの (CMスキップ・アンビエントモード・バックグラウンド再生・互換モード・字幕・音声・コーデック) を1つのメニューにまとめる。互換モードは入れるときに運転中の注意を出し、切り替えたらページを読み直す。字幕の行はオフと、字幕のストリーム・言語を並べる (ライブの字幕の選び直しもここ)。切り替えは行を押すとその場で変わり (menuitemcheckbox + aria-checked)、音声とコーデックは行にいまの値を出して選択肢の並びに入る (先頭が戻る行。Esc・← でも戻る)。⚙ は狭い枠でも畳まない。互換モードでこの端末が描けない形式は「(再生できません)」と出して押せなくする (3画面とも。観る画面の互換モードは MPEG-2 も並ぶ) |
SpeedMenu.svelte |
速さのメニュー。観ながら何度も変えるので操作バーに置く (再生の設定には入れない)。互換モードで canvas に描いている間は出さない (等速だけ) |
EdgeButton.svelte |
「今」へ張り付くボタン(ライブの「ライブ」・追っかけの「最新」) |
InfoBlock.svelte |
操作バーの中の読みもの(二段)。上が「時間帯 ・ 局 ・ 番組名」、下が画面ごとの状態(位置・遅延など) |
FactsAside.svelte |
右の「番組の中身」の列の枠(観る画面・追っかけ)。中身が長ければここだけ巻き取られ、押すものは外に貼り付く |
PlayerLayout.svelte |
3画面の外枠。映像が左、読むものが右 (768px から二段組。映像は上に寄せ、周りの余白は 1rem に詰める)。横にしたスマホ (指の端末で高さ 500px 未満) は見出しを隠し、枠を映像の縦横比 (16:9) で画面の高さいっぱいに、右の列は映像の下へ |
ControlRow.svelte / SeekBar.svelte / seek-track.ts |
下の操作バーの「押すものの行」と再生位置のバー (進んだぶんを塗る。観る画面はチャプターの切れ目で溝を区切り、CM の部分は色を分ける) |
CloseLink.svelte |
右端の列のいちばん上の「閉じる」(一覧へ戻る。観る画面・追っかけ) |
StageNote.svelte |
映像の上に浮かせる短い通知(角丸の黒いラベル。テーマ色を映像に乗せない)。置き場は持たず、舞台の通知の列に積む (同時に出ても重ならない) |
keys.ts |
キーの割り当て(空白/k 再生・← → 10秒・c 字幕・s 切り抜き・f 全画面・< > 速さ・m 消音)。観る画面と追っかけで同じ。修飾キー付きと IME 変換中は取らない(Ctrl+C を字幕に取られてコピーできなかった) |
center-tap.ts / stage-tap.ts |
真ん中あたりを素早く2回で再生/一時停止(指の端末だけ。1回目は操作列の出し入れ)。使うのはライブだけで、観る画面と追っかけは stage-tap.ts(読み方は ts/watch.ts の tap。マウス1回で再生/一時停止、端2回で 10秒) |
pip.svelte.ts / compose.ts |
小窓 (ピクチャーインピクチャー)。操作バーの全画面の左に置き、狭い枠では ⚙ の頭の「小窓」の行にする。ページから小窓を開かせられない端末 (iPhone・iPad のホーム画面から開いたもの・API の無いブラウザ) ではボタンごと出さない。canvas に描いているとき (放送のままの MPEG-2・互換モード) は worker が描いたフレームを別の <video> に流して出す (Chrome は worker が直に書き込む。canvas の画面への更新から取ると、窓が隠れたとき映像が止まる。Safari は canvas から取る。Firefox は放送のままの MPEG-2 ではボタンを出さない)。字幕も小窓に出す (Chrome・Edge だけ。compose.ts がコマごとに字幕の canvas を重ねたストリームを作る。小窓に出している間だけ重ねる)。小窓で押した止める・再開は操作バーにも反映する。操作列は小窓に付いていかない。denpa の別の画面へ移ると、再生ごと止まって小窓も閉じる |
fullscreen.svelte.ts / fullscreen.ts |
全画面の出入り(操作バーのボタンと f)。端末で全画面にする方法を決める(watch.md) |
background.svelte.ts / background.ts |
バックグラウンド再生のオン/オフ(再生の設定の行)。既定はオフで、裏に回したら止める(watch.md) |
ambient.svelte.ts / ambient.ts / AmbientGlow.svelte / glance-worker.ts |
アンビエントモード(再生の設定の行。既定はオン、端末ごとに覚える)。いまのコマを 32x18 に縮め (1秒に5回まで)、縁の色を外へ延ばして明るさを抑え、地に敷く (二段組は窓全体、縦に積むときは映像の下の中身)。<video> のコマは worker (glance-worker.ts) で縮め、canvas に描いているときは描いている worker に1枚もらう。周りに地が残らない横にしたスマホでは敷かず、全画面の間は写さない |
shot.svelte.ts / snapshot.ts |
いまの1コマを字幕ごと切り抜いて PNG に(番組名_YYYYMMDD-HHMMSS.png)。指の端末は共有シート(写真へ保存・そのまま送る)、PC はファイルに保存してクリップボードにも置く。放送のままの MPEG-2 と互換モードで見ているときは worker に1枚貰う(raw/engine.ts の grab) |
DataBroadcast.svelte / Remote.svelte / HybridcastFrame.svelte |
データ放送の表示枠、指で押せるリモコン、Hybridcast のアプリの枠 (stream.md) |
アイコンは Lucide を、組むときに埋め込みます
Section titled “アイコンは Lucide を、組むときに埋め込みます”アイコンは Lucide に揃えています(線の太さ 2・角丸。
currentColor で文字の色に従う)。読み込みは Iconify のアイコンデータの束 (@iconify-json/*) を
unplugin-icons で組むときに Svelte の部品へ
変えるやり方です(import Play from '~icons/lucide/play'。vite.config.ts)。
- 実行中に取得しない。 denpa は家の LAN だけ・オフラインでも開くものなので、
Iconify の API からアイコンデータを取る
@iconify/svelteの既定の使い方は採りません。束に入るのは 使ったアイコンの<svg>だけで、SSR でもそのまま出ます(後からアイコンが差し込まれてずれることもない)。 service worker が持つのも普通の JS の束です @iconify/svelteにアイコンデータを渡す方式は採りません。 実行時の部品とアイコンのデータを両方束に入れることになり、重くなりますlucide-svelteを直に使わないのは、ほかの集まりも同じ書き方で足せるから。 局やサービスのロゴが要るときは@iconify-json/simple-iconsを足して~icons/simple-icons/*- 足した依存はどちらも開発時だけ(
devDependencies)。束に入るのは Lucide のアイコン (ISC) だけです (licenses.md) - Lucide に無いアイコンは
src/lib/icons/*.svgに置きます(~icons/denpa/*)。いまはデータ放送の 「d」だけ(リモコンと同じ字。線の太さと角は Lucide に揃えた)
ロゴ・PWA のアイコン (static/)・局ロゴ・データ放送の画面は「アイコン」ではないので対象外です。