-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Description
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:
-
A vendor hosts a generic playback document that handles messaging with a standard library.
-
An extension is configured in the AMP codebase declaratively. (Any vendors that are already using
amp-video-iframecan start here if they want their own component.) -
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
-
Transformer (🏗 Transform aliased configured components #26541)
-
Support
data-param-*inamp-video-iframe. -
Refactor
amp-video-iframeto use component config. -
Provide as an option for new players (generator).
-
Migrate existing players (TBD, support matrix)