libaribhtml5 0.1.3 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,7 @@
1
1
  /** Current demo receiver identifier (48-bit hexadecimal ACAS source value). */
2
2
  export declare const DEFAULT_RECEIVER_DEVICE_IDENTIFIER = "4194c4ae4730";
3
+ /** Legacy BML browser.getIRDID() type used for the receiver/CAS identifier. */
4
+ export declare const RECEIVER_IRD_ID_TYPE = 5;
5
+ export declare function getDefaultReceiverIrdId(type: number): string | null;
3
6
  export type ReceiverDeviceIdentifierProvider = (kind: number) => string | null | undefined | Promise<string | null | undefined>;
4
7
  export declare function resolveReceiverDeviceIdentifier(kind: number, provider?: ReceiverDeviceIdentifierProvider): Promise<string>;
@@ -0,0 +1,4 @@
1
+ type PointerTransparentIframe = Pick<HTMLIFrameElement, 'inert' | 'style' | 'tabIndex'>;
2
+ /** Keep the application plane visible without making it an input or focus target. */
3
+ export declare function makeIframePointerTransparent(iframe: PointerTransparentIframe): void;
4
+ export {};
@@ -1,5 +1,6 @@
1
1
  export { AribReceiverHost } from './receiver-host';
2
2
  export type { AribApplicationInformation, AribApplicationReplaceHandler, AribApplicationReplaceRequest, AribCaptionPacket, AribBroadcastClock, AribExitManagedStateHandler, AribReceiverLifecycleEvent, AribReceiverHostOptions, } from './receiver-host';
3
+ export type { AribApplicationPresentationState, AribViewerParticipationEvent, AribViewerParticipationNotification, } from './viewer-participation';
3
4
  export { BehindIframeMediaPlaneAdapter, DomObjectMediaPlaneAdapter, } from './media-plane';
4
5
  export type { AribMediaPlane, AribMediaPlaneAdapter, AribMediaPlaneLayer, AribMediaPlaneStackEntry, AribMediaPlaneUnmountReason, AribVideoPlane, BehindIframeMediaPlaneAdapterOptions, DomObjectMediaPlaneAdapterOptions, } from './media-plane';
5
6
  export { installRuntime } from './runtime/install';
@@ -9,9 +10,12 @@ export { cloneProgramInfo } from './program-info';
9
10
  export type { ProgramInfo } from './program-info';
10
11
  export { runtimeEventMatchesSelector } from './runtime/stream-event';
11
12
  export type { RuntimeEvent, RuntimeEventSelector, RuntimeEventSource, } from './runtime/stream-event';
12
- export type { RuntimeApplicationInformation, RuntimeOptions, RuntimeWindow, } from './runtime/install';
13
- export { DEFAULT_RECEIVER_DEVICE_IDENTIFIER, resolveReceiverDeviceIdentifier, } from './device-identifier';
13
+ export type { AribPermissionManagedArea, RuntimeApplicationInformation, RuntimePermissionManagedArea, RuntimeOptions, RuntimeWindow, } from './runtime/install';
14
+ export { ARIB_PERMISSION_BITS, AribApplicationBoundaryPolicy, } from './runtime/application-boundary';
15
+ export type { AribPermissionBit, AribPermissionEvaluation, } from './runtime/application-boundary';
16
+ export { DEFAULT_RECEIVER_DEVICE_IDENTIFIER, getDefaultReceiverIrdId, RECEIVER_IRD_ID_TYPE, resolveReceiverDeviceIdentifier, } from './device-identifier';
14
17
  export type { ReceiverDeviceIdentifierProvider } from './device-identifier';
18
+ export { normalizeLctBackgroundColor } from './layout';
15
19
  export type { BroadcastResourceCacheEvent, BroadcastResourceCacheListener, BroadcastResourceChange, BroadcastResourceStore, } from './runtime/resources';
16
20
  export { installBroadcastClock } from './runtime/clock';
17
21
  export type { BroadcastNowProvider } from './runtime/clock';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Convert the ARIB STD-B60 24-bit LCT background colour to a CSS colour.
3
+ * A null value removes the current LCT override and restores host fallback
4
+ * selection.
5
+ */
6
+ export declare function normalizeLctBackgroundColor(value: number | null): string | null;
7
+ export declare function resolveReceiverBackgroundColor(lctColor: string | null, stageColor: string | null): string;
@@ -11,6 +11,11 @@ export type AribMediaPlaneStackEntry = {
11
11
  export type AribMediaPlaneLayer = {
12
12
  documentOrder: number;
13
13
  stackingPath: AribMediaPlaneStackEntry[];
14
+ /**
15
+ * External compositor fallback for a media-only foreground wrapper.
16
+ * Omitted/behind-application keeps the host surface below the iframe.
17
+ */
18
+ externalPlacement?: 'behind-application' | 'above-application';
14
19
  };
15
20
  export type AribMediaPlane = {
16
21
  slotId: string;
@@ -62,15 +67,22 @@ export declare class DomObjectMediaPlaneAdapter implements AribMediaPlaneAdapter
62
67
  export type BehindIframeMediaPlaneAdapterOptions = {
63
68
  surface: HTMLElement;
64
69
  keepVisible?: boolean;
70
+ /** Stacking level used for the ordinary media plane behind the iframe. */
71
+ behindZIndex?: string | number;
72
+ /** Stacking level used for a foreground media-only wrapper. */
73
+ aboveZIndex?: string | number;
65
74
  };
66
75
  /**
67
- * Simplified compatibility fallback. It cannot interleave media with elements
68
- * inside the application iframe; the complete iframe is always above it.
76
+ * Simplified iframe compositor. It normally keeps media behind the complete
77
+ * application iframe, but can raise a foreground media-only slot as a whole.
78
+ * It still cannot interleave that surface with individual elements in iframe.
69
79
  */
70
80
  export declare class BehindIframeMediaPlaneAdapter implements AribMediaPlaneAdapter {
71
81
  readonly renderMode: "external";
72
82
  private readonly surface;
73
83
  private readonly keepVisible;
84
+ private readonly behindZIndex;
85
+ private readonly aboveZIndex;
74
86
  constructor(options: BehindIframeMediaPlaneAdapterOptions);
75
87
  mountMediaPlane(_object: HTMLElement, plane: AribMediaPlane): void;
76
88
  updateMediaPlane(_object: HTMLElement, plane: AribMediaPlane): void;
@@ -5,6 +5,7 @@ import type { ReceiverDeviceIdentifierProvider } from './device-identifier';
5
5
  import { type AribMediaPlane, type AribMediaPlaneAdapter } from './media-plane';
6
6
  import type { BroadcastResourceChange, BroadcastResourceStore } from './runtime/resources';
7
7
  import { type AribProgramGuideHandler, type AribProgramGuideRequest, type AribProgramGuideUnavailableHandler } from './program-guide';
8
+ import { type AribApplicationPresentationState, type AribViewerParticipationEvent, type AribViewerParticipationNotification } from './viewer-participation';
8
9
  export type { AribMediaPlane, AribMediaPlaneAdapter, AribMediaPlaneLayer, AribMediaPlaneStackEntry, AribMediaPlaneUnmountReason, AribVideoPlane, } from './media-plane';
9
10
  export type AribCaptionPacket = {
10
11
  componentTag: number;
@@ -90,6 +91,8 @@ export type AribReceiverHostOptions = {
90
91
  systemInformation?: ReceiverSystemInformationOverrides;
91
92
  /** Resolve receiver/CAS identifiers; defaults to the bundled Huggy demo identity. */
92
93
  getDeviceIdentifier?: ReceiverDeviceIdentifierProvider;
94
+ /** Receiver UI hook for a TR-B39 viewer-participation corner notification. */
95
+ onViewerParticipation?: (event: AribViewerParticipationEvent) => void;
93
96
  };
94
97
  export declare class AribReceiverHost {
95
98
  readonly iframe: HTMLIFrameElement;
@@ -115,6 +118,8 @@ export declare class AribReceiverHost {
115
118
  private readonly onProgramGuideUnavailable?;
116
119
  private readonly systemInformation?;
117
120
  private readonly getDeviceIdentifier?;
121
+ private readonly onViewerParticipation?;
122
+ private readonly viewerParticipation;
118
123
  private readonly resizeObserver;
119
124
  private activeRuntimeId;
120
125
  private logicalWidth;
@@ -124,6 +129,8 @@ export declare class AribReceiverHost {
124
129
  private programInfo;
125
130
  private readonly pendingStreamEvents;
126
131
  private broadcastClock;
132
+ private lctBackgroundColor;
133
+ private stageBackgroundColor;
127
134
  private video;
128
135
  private mediaPlaneEnabled;
129
136
  private applicationExited;
@@ -133,12 +140,25 @@ export declare class AribReceiverHost {
133
140
  installRuntime(target: RuntimeWindow): void;
134
141
  /** Set the MH-AIT identity exposed by applicationManager.getOwnerApplication(). */
135
142
  setApplicationInformation(application: AribApplicationInformation | null): void;
143
+ /**
144
+ * Set the receiver-owned background plane from the current LCT
145
+ * Background_Color_Descriptor. Pass null when changing service/session or
146
+ * when the active LCT no longer carries the descriptor.
147
+ */
148
+ setLctBackgroundColor(backgroundColorRgb: number | null): void;
136
149
  /** @deprecated Pass an AribMediaPlaneAdapter to the constructor. */
137
150
  attachVideo(video: HTMLVideoElement): void;
138
151
  loadApplication(url: string, status?: string): void;
139
152
  /** Leave data-broadcast mode and restore media to the ordinary player. */
140
153
  exitApplication(status?: string): void;
141
- dispatchKey(code: number): void;
154
+ dispatchKey(code: number): boolean;
155
+ /** Transfer or release receiver-key ownership for the broadcast application. */
156
+ setApplicationInputActive(active: boolean): void;
157
+ getApplicationPresentationState(): AribApplicationPresentationState;
158
+ /** Handle the descriptor-less TR-B39 receiver notification outside the application. */
159
+ notifyViewerParticipationCorner(notification: AribViewerParticipationNotification): void;
160
+ /** Discard notification versions while changing service or playback session. */
161
+ resetViewerParticipationNotifications(): void;
142
162
  setCaptionTracks(componentTags: number[]): void;
143
163
  pushCaption(packet: AribCaptionPacket): void;
144
164
  resetCaptions(): void;
@@ -172,4 +192,5 @@ export declare class AribReceiverHost {
172
192
  private invalidateRuntime;
173
193
  private fitBroadcastCanvas;
174
194
  private assertAlive;
195
+ private applyReceiverBackgroundColor;
175
196
  }
@@ -0,0 +1,45 @@
1
+ export declare const ARIB_PERMISSION_BITS: {
2
+ readonly broadcastMedia: 12;
3
+ readonly monomediaOverBroadcastVideo: 11;
4
+ readonly currentEventInformation: 10;
5
+ readonly persistentStorage: 9;
6
+ readonly boundaryExtension: 8;
7
+ readonly deviceIdentifier: 7;
8
+ readonly ipNetworkConfirmation: 6;
9
+ readonly broadcastResources: 5;
10
+ readonly scheduling: 4;
11
+ readonly cas: 3;
12
+ };
13
+ export type AribPermissionBit = typeof ARIB_PERMISSION_BITS[keyof typeof ARIB_PERMISSION_BITS];
14
+ /** One loop of the MH-application boundary and permission descriptor. */
15
+ export type RuntimePermissionManagedArea = {
16
+ /** Raw 16-bit permission_bitmap values, including the three-bit bitmap id. */
17
+ permissionBitmaps: readonly number[] | null;
18
+ /** managed_URL values. null or an empty array means all locations. */
19
+ managedUrls: readonly string[] | null;
20
+ };
21
+ /** Shape exposed by ApplicationBoundaryAndPermissionDescriptor in ARIB STD-B62. */
22
+ export type AribPermissionManagedArea = {
23
+ /** Raw 16-bit permission_bitmap values, or null for maximum permission. */
24
+ permission: number[] | null;
25
+ /** Managed URL strings, or null for all locations. */
26
+ urls: string[] | null;
27
+ };
28
+ export type AribPermissionEvaluation = {
29
+ withinBoundary: boolean;
30
+ permissionBits: number;
31
+ };
32
+ export declare class AribApplicationBoundaryPolicy {
33
+ private readonly broadcastBaseUrl;
34
+ private readonly documentUrl;
35
+ private baseAreas;
36
+ private readonly addedAreas;
37
+ constructor(broadcastBaseUrl: string | URL, documentUrl: string | URL, areas?: readonly RuntimePermissionManagedArea[]);
38
+ /** Apply a new MH-AIT descriptor without discarding areas added by the application. */
39
+ update(areas?: readonly RuntimePermissionManagedArea[]): void;
40
+ hasDescriptor(): boolean;
41
+ getCurrentBoundary(): AribPermissionManagedArea[];
42
+ addPermissionManagedArea(area: AribPermissionManagedArea): void;
43
+ evaluate(value: string | URL): AribPermissionEvaluation;
44
+ permits(value: string | URL, bit: AribPermissionBit): boolean;
45
+ }
@@ -3,8 +3,10 @@ import type { AribMediaPlaneAdapter } from '../media-plane';
3
3
  import { type BroadcastResourceStore } from './resources';
4
4
  import { type ReceiverSystemInformationOverrides } from './system-information';
5
5
  import { type ReceiverDeviceIdentifierProvider } from '../device-identifier';
6
+ import { type RuntimePermissionManagedArea } from './application-boundary';
6
7
  export type { ProgramInfo } from '../program-info';
7
8
  export type { RuntimeEvent, RuntimeEventSelector, RuntimeEventSource, } from './stream-event';
9
+ export type { AribPermissionManagedArea, RuntimePermissionManagedArea, } from './application-boundary';
8
10
  export type RuntimeWindow = Window & typeof globalThis & Record<string, unknown>;
9
11
  export type RuntimeOptions = {
10
12
  /** Permit HTTP requests outside the receiver-managed application origin. */
@@ -30,5 +32,7 @@ export type RuntimeApplicationInformation = {
30
32
  applicationId?: number;
31
33
  controlCode?: string;
32
34
  autostartPriority?: number;
35
+ /** Decoded loops from MH-AIT descriptor 0x802C. Omit when absent. */
36
+ permissionManagedAreas?: readonly RuntimePermissionManagedArea[];
33
37
  };
34
38
  export declare function installRuntime(target: RuntimeWindow, options?: RuntimeOptions): void;
@@ -0,0 +1,13 @@
1
+ export type BroadcastMediaSlot = {
2
+ element: HTMLElement;
3
+ rect: DOMRect;
4
+ };
5
+ /**
6
+ * Resolve the receiver video slot represented by a broadcast object.
7
+ *
8
+ * Chromium gives an unsized `<object>` its replaced-element fallback size
9
+ * (normally 300 x 150). Broadcast applications also use an unsized object as
10
+ * the sole child of a positioned video-slot wrapper. In that case the wrapper,
11
+ * rather than the browser fallback box, is the receiver media plane.
12
+ */
13
+ export declare const resolveBroadcastMediaSlot: (object: HTMLElement) => BroadcastMediaSlot;
@@ -0,0 +1,4 @@
1
+ type NavigatorPlatform = Pick<Navigator, 'maxTouchPoints' | 'platform' | 'userAgent'>;
2
+ /** iOS media elements can replace the receiver player's active media session. */
3
+ export declare function shouldSuppressRomSoundPlayback(navigator: NavigatorPlatform): boolean;
4
+ export {};
@@ -0,0 +1,29 @@
1
+ export type AribApplicationPresentationState = {
2
+ visible: boolean;
3
+ inputActive: boolean;
4
+ };
5
+ export type AribViewerParticipationNotification = {
6
+ contextId: number;
7
+ sourcePacketId: number;
8
+ eventMessageTag: number;
9
+ dataEventId: number;
10
+ messageGroupId: number;
11
+ version: number;
12
+ currentNext: boolean;
13
+ sectionNumber: number;
14
+ lastSectionNumber: number;
15
+ inputOffset: bigint;
16
+ };
17
+ export type AribViewerParticipationEvent = AribViewerParticipationNotification & {
18
+ requiresUserAction: true;
19
+ };
20
+ export declare class ViewerParticipationController {
21
+ private state;
22
+ private generation;
23
+ private readonly delivered;
24
+ get presentation(): AribApplicationPresentationState;
25
+ setPresentation(state: Partial<AribApplicationPresentationState>): void;
26
+ resetPresentation(): void;
27
+ resetSession(): void;
28
+ notify(notification: AribViewerParticipationNotification): AribViewerParticipationEvent | null;
29
+ }
@@ -65,6 +65,40 @@ const host = new AribReceiverHost({
65
65
  許可境界と外部 network policy を receiver 側で検証し、対応する場合だけ
66
66
  `onExitManagedState` で処理します。
67
67
 
68
+ ## アプリケーション境界と権限
69
+
70
+ MH-AIT の `MH-Application Boundary and Permission Descriptor` (`descriptor_tag=0x802C`)
71
+ は、decoder 側で一つの application に属する loop を平坦化し、次の形で渡します。
72
+
73
+ ```ts
74
+ host.setApplicationInformation({
75
+ organizationId: application.organizationId,
76
+ applicationId: application.applicationId,
77
+ permissionManagedAreas: application.boundaryDescriptors.flatMap(descriptor =>
78
+ descriptor.areas.map(area => ({
79
+ // bitmap ID を含む raw 16-bit 値
80
+ permissionBitmaps: area.permissionBitmaps,
81
+ managedUrls: area.managedUrls,
82
+ })),
83
+ ),
84
+ })
85
+ ```
86
+
87
+ descriptor がない場合は `permissionManagedAreas` 自体を省略します。この場合は境界が無限で
88
+ 全権限です。descriptor が存在し、ある area の `managed_URL_count` が 0 の場合は
89
+ `managedUrls: []`(または `null`)で全 location を表します。より狭い domain/sub-directory の
90
+ 設定が一致した場合はそちらを優先します。放送 VFS (`broadcastBaseUrl`) から取得した content は、
91
+ TR-B39 の規定どおり descriptor にかかわらず境界内・全権限として扱います。
92
+
93
+ runtime は bitmap 0/1 を解釈し、bit 12/10/9/8/7/5 を現在実装済みの broadcast media、番組情報、
94
+ persistent array、boundary extension、receiver ID、application/cache/EMT/system-information API に
95
+ 適用します。権限がない同期 API は `Error` (`code="NOT_AUTHORIZED_ERR"`) を送出し、AIT 更新後も
96
+ 同じ runtime に直ちに反映します。更新によって現在の communication document が境界外になった場合、
97
+ host は application を終了します。
98
+
99
+ 境界権限と `allowExternalNetwork` は別条件です。MH-AIT が URL を許可しても、host の network policy が
100
+ offline なら外部 HTTP へは遷移・通信できません。
101
+
68
102
  ## AUTOSTART と PRESENT の同居
69
103
 
70
104
  一つの tuning/session generation につき managed application slot は一つにします。
@@ -25,11 +25,44 @@ object だけを子に持つ media-only wrapper は wrapper 自身も隠しま
25
25
  独立した compositing layer を作る場合、背景だけを透明化しても Chromium が外部 video の上へその layer を
26
26
  残すためです。字幕、ダイアログ、操作 UI を含む祖先は media-only wrapper として扱いません。
27
27
 
28
+ 放送ページが object 自身に `width` / `height` を指定せず、positioned wrapper だけに映像枠の寸法を
29
+ 指定する場合があります。通常ブラウザはその object を 300 x 150 の既定 replaced-element として計測しますが、
30
+ receiver runtime は object が wrapper の唯一の子である場合に限り wrapper を media slot として採用します。
31
+ この wrapper は外部合成中だけ object と一緒に透明化されるため、放送ページが指定した高い `z-index` を
32
+ 削除したり、host の video を iframe より前へ出したりする必要はありません。
33
+
34
+ ただし、異なる寸法の media-only wrapper が正の `z-index` を持つ場合、その video slot はページ背景の
35
+ 前に置くことを意図した foreground media です。runtime は `layer.externalPlacement` を
36
+ `above-application` として報告します。external adapter はこの場合だけ media surface を application
37
+ iframe より前の layer に置きます。標準の `BehindIframeMediaPlaneAdapter` は通常 `z=0`、この場合だけ
38
+ `z=2` を使います(必要なら `behindZIndex` / `aboveZIndex` で host の stacking context に合わせます)。
39
+ 通常の全面映像や application background として使われる slot は `behind-application` のままです。
40
+
28
41
  `display: none`、`visibility: hidden`、`content-visibility: hidden` は矩形計測または可視判定を壊すため
29
42
  使用しません。runtime は隠す前の computed opacity を media-plane report に使い、host 側の video は
30
43
  object の CSS を複製せず、報告された `getBoundingClientRect()` を logical viewport に対する割合へ
31
44
  変換して配置します。
32
45
 
46
+ ## プレーヤー操作への pointer 穿透
47
+
48
+ データ放送 iframe は全面が透明でも、一つの不透明な矩形と同じように hit test されます。そのまま
49
+ プレーヤーへ重ねると、特に touch device で下の再生 UI がクリックできなくなります。
50
+
51
+ `AribReceiverHost` は iframe を表示専用の application plane として扱い、既定で `inert`、
52
+ `pointer-events: none !important`、`tabindex="-1"` を設定します。`tabindex="-1"` だけでは iframe 内の
53
+ document が focus を取得できるため不十分です。`inert` によって子 document 全体を focus と hit test の
54
+ 対象から外し、下のプレーヤー container へ mouse / touch event と `:hover` を渡します。描画、timer、通信、
55
+ media-plane report は継続します。リモコン入力は iframe の focus に頼らず `host.dispatchKey()` で
56
+ document へ送ってください。
57
+
58
+ iframe 内の pointer event を親へ再送する実装は使いません。iframe の event は親 document へ bubble
59
+ しないため、再送には座標から対象要素を再決定する処理が必要になり、player controller の click、drag、
60
+ pointer capture を壊します。
61
+
62
+ HTML/iframe には SVG の `pointer-events: painted` に相当する、非透明 pixel だけを hit test する
63
+ モードはありません。透明度や root の背景色を見て iframe を `display: none` にすると、debug overlay
64
+ 以外の application UI や後から表示される画面まで失われるため使用しません。
65
+
33
66
  ## Chromium の白い iframe backdrop
34
67
 
35
68
  Chromium は iframe owner と iframe 内 root の used `color-scheme` が異なる場合、透明 iframe の
@@ -26,6 +26,24 @@ MMT の source of truth は LCT です。実装時の優先順位は次の通り
26
26
  fallback として使ってよい。ただし、これはアプリケーション CSS を LCT と解釈するものではない。
27
27
  3. どちらも得られない間の receiver-owned fallback は黒 (`#000`) とする。
28
28
 
29
+ `tlvdemux` の WASM 回調は LCT の 24 bit RGB を `backgroundColorRgb` として渡す。
30
+ その値はページ CSS に変換せず、receiver host の背景プレーンへ渡す。
31
+
32
+ ```ts
33
+ const demuxer = new TlvDemuxer({
34
+ onLayoutConfiguration(layout) {
35
+ host.setLctBackgroundColor(layout.backgroundColorRgb)
36
+ },
37
+ })
38
+
39
+ // 選局・別サービス・別チューニング session へ移る前に前回の LCT を破棄する。
40
+ host.setLctBackgroundColor(null)
41
+ ```
42
+
43
+ LCT の色が設定されている間、後から到着した application stage の CSS 色は
44
+ 背景プレーンを上書きしない。`null` で LCT 色を解除した場合だけ、stage 色または
45
+ 黒の fallback へ戻る。
46
+
29
47
  この fallback は規格上の既定色ではありません。白いブラウザ canvas の露出を避けるための
30
48
  実装上の選択です。確認に使った NHK BS8K の `8k.mmts` から抽出したファイルも、
31
49
  `top/source/top.css` の `body` と `#vstream`、および
@@ -127,6 +145,11 @@ window.__ARIB_HTML5_INSTALL__ = (child: RuntimeWindow) => {
127
145
  }
128
146
  ```
129
147
 
148
+ `AribReceiverHost` は全面 iframe を表示専用の inert overlay として扱うため、データ放送の描画を
149
+ 残したまま touch/mouse 操作と `:hover` は下のプレーヤー UI へ通り、iframe 内へ browser focus も
150
+ 移りません。`pointer-events: none !important` と `tabindex="-1"` も互換用 fallback として設定します。
151
+ 放送アプリケーションのリモコン操作には `host.dispatchKey()` を使用してください。
152
+
130
153
  データ放送への出入りは次の二つだけです。
131
154
 
132
155
  ```ts
@@ -242,6 +265,7 @@ type AribMediaPlane = {
242
265
  opacity: number
243
266
  transform: string
244
267
  }>
268
+ externalPlacement?: 'behind-application' | 'above-application'
245
269
  }
246
270
  }
247
271
  ```
@@ -254,6 +278,12 @@ type AribMediaPlane = {
254
278
  合成方針を決めます。ブラウザ用 `DomObjectMediaPlaneAdapter` では DOM 自身が合成するため、
255
279
  この変換は不要です。
256
280
 
281
+ `externalPlacement` は iframe 外の video を使うブラウザ統合向けの限定的なヒントです。
282
+ `above-application` は、既定寸法の object を包む media-only wrapper が正の `z-index` を持つ場合にだけ
283
+ 報告されます。この場合、host は media surface 全体を iframe より前の stacking level にできます。
284
+ ただし iframe 内部との完全な interleave はできないため、映像枠と重なる application UI がある実装では
285
+ `in-object` adapter を使用してください。
286
+
257
287
  ## なぜ iframe 背面方式では不足するか
258
288
 
259
289
  iframe と親 document の間で選べるのは次の順序だけです。