Skip to content

I2I: Aliased amp-video-iframe for 3p vendors #26572

@alanorozco

Description

@alanorozco

Motivation

15 player components supported by the generic VideoInterface are vendor-specific 3p components. These are thin wrappers around a playback iframe that talks to the host document through a vendor-specific messaging interface.

amp-video-iframe can be used by video vendors who lack AMP compatibility. However, many of them are hesitant towards this approach (or avoid it entirely) since they would like to (a) provide more ergonomic APIs for publishers and (b) have a "fair spot" among existing 3p players (i.e. branding/presence in docs).

Otherwise, 3p extensions are currently costly due to maintenance and friction when implementing and/or initially contributing. Many are rejected when contributed for this reason.

Goal

Leverage/alias amp-video-iframe for logicless/declarative 3p video player component implementations, so a video vendor would do a one-time setup similar to what a publisher would do using amp-video-iframe.

The result is exposed as a vendor-specific video component:

<script async
  custom-element="amp-my-cool-video-player"
  src=".../v0/amp-my-cool-video-player-latest.js"
></script>

<amp-my-cool-video-player
  data-param-video-id="12345"
  data-param-channel-id="98765"
  data-param-foo="bar"
></amp-my-cool-video-player>

(This reduces the cost of maintaining any 3p player, so we can migrate existing extensions).

Details

Harness

Like an amp-video-iframe, a standard set of methods and events are passed between the host document and the iframe document:

  1. A vendor hosts a generic playback document that handles messaging with a standard library.

  2. An extension is configured in the AMP codebase declaratively. (Any vendors that are already using amp-video-iframe can start here if they want their own component.)

  3. A base runtime implementation is configured/built in order to retain the API of a custom player extension.

Extension generator

Define a local development task to generate (1) the protoascii validator definition and (2) the runtime code:

$ gulp create-video-player --config=amp-my-cool-video-player.json

(This task could in addition/otherwise be interactive).

The name of the JSON5 file is used as the component name. Its content specifies a VideoPlayerElementDef.

{
  src: 'https://my-cool-video.vendor/amp',

  // At least one attribute required to map document URL to specific video:
  requiredAttributes: ['video-id'],

  // All below are optional.

  // Describes existing support inside the <iframe> to avoid feature duplication.
  // (These are proxies for the same flag methods in the VideoInterface, and their
  // respective amp-video-iframe attributes)
  preimplementsMediaSessionAPI: false,
  preimplementsRotateToFullscreen: false,

  // Always uses data-param-* attributes as query params for src URL, others can be specified.
  // (This is meant for backwards compatibility with existing players).
  legacySrcQueryAttributes: ['video-id', 'channel-id'],
}

This will output validator and runtime code into extensions/ when task runs.

We could alternatively build all player binaries from a single definition table or directory, but that possibility is limited by others (e.g. build-time bundle config, extension docs) using extensions/ as an entry point.

Barebones definition

The minimum definition requires a src, and at least one requiredAttribute to point the <iframe>'s URL to the specific video:

src: 'https://my-cool-video.vendor/amp',
requiredAttributes: ['data-param-video-id'],

This exposes a custom element whose data-param-* attributes are appended as the iframe src's query:

<!-- Uses https://my-cool-video.vendor/amp?videoId=12345&channelId=98765#amp=1 -->
<amp-my-cool-video-player
  data-param-video-id="12345"
  data-param-channel-id="98765"
></amp-my-cool-video-player>

Legacy attribute-parameter mapping

Some existing players expose their URL parameters as attributes without the data-param-* prefix. Those can be explicitly annotated for use:

legacySrcQueryAttributes: ['vid', 'channelid', ...]

Standard video player attributes cannot be used for query, including: src, autoplay, dock, poster, noaudio, rotate-to-fullscreen, implements-*.

This is meant to grandparent existing player APIs, so it should be restricted for new components.

Runtime & Transformation

The definition is internally wrapped in a constructor function. The component implementation is registered as usual, except passing only its declarative configuration to the wrapper:

const TAG = 'amp-my-cool-video-player';

const AmpMyCoolVideoPlayer = configureComponent(VideoIframeElement, {
  // Declarative config, plus TAG.
  TAG,
  src: ...,
  requiredAttributes: ...,
});

AMP.extension(TAG, '0.1', AMP => {
  AMP.registerElement(TAG, AmpMyCoolVideoPlayer);
});

This is then transformed it on build time by inlining the wrapper and its configuration, in order to keep the performance properties of the binaries shipped currently:

const TAG = 'amp-my-cool-video-player';

const _src = ...;
const _requiredAttributes = ...;

class VideoIframeElement extends AMP.BaseElement { 
  // References to configuration object are inlined here.
}

const AmpMyCoolVendorPlayer = VideoIframeElement;

AMP.extension(TAG, '0.1', AMP => {
  AMP.registerElement(TAG, AmpMyCoolVendorPlayer);
});

By confining the runtime configuration to VideoPlayerElementDef, the build time transformation depends on mostly replacing object references, while able to execute and testing the runtime code without transformation (see #26541).

Milestones

  1. Transformer (🏗 Transform aliased configured components #26541)

  2. Support data-param-* in amp-video-iframe.

  3. Refactor amp-video-iframe to use component config.

  4. Provide as an option for new players (generator).

  5. Migrate existing players (TBD, support matrix)

Metadata

Metadata

Assignees

Labels

INTENT TO IMPLEMENTProposes implementation of a significant new feature. https://bit.ly/amp-contribute-codeStaleInactive for one year or moreWG: components

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions