Skip to content

Commit 9a0f608

Browse files
committed
Added amp-brightcove component
1 parent 95a6d8e commit 9a0f608

9 files changed

Lines changed: 255 additions & 1 deletion

File tree

examples/brightcove.amp.html

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!doctype html>
2+
<html >
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Brightcove Player Example</title>
6+
<link rel="canonical" href="amps.html" >
7+
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
8+
<link href='https://fonts.googleapis.com/css?family=Georgia|Open+Sans|Roboto' rel='stylesheet' type='text/css'>
9+
<script async custom-element="amp-brightcove" src="/dist/v0/amp-brightcove-0.1.max.js"></script>
10+
<style>body {opacity: 0}</style><noscript><style>body {opacity: 1}</style></noscript>
11+
<script async src="https://cdn.ampproject.org/v0.js"></script>
12+
</head>
13+
<body>
14+
<h2>Brightcove Player</h2>
15+
16+
<amp-brightcove
17+
data-account="906043040001"
18+
data-video-id="1401169490001"
19+
data-player-id="180a5658-8be8-4f33-8eba-d562ab41b40c"
20+
layout="responsive" width="480" height="270">
21+
</amp-brightcove>
22+
23+
</body>
24+
</html>

extensions/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Current list of extended components:
2020
| --------------------------------------------- | ------------------------------------------------------------------------------------------- |
2121
| [`amp-anim`](amp-anim/amp-anim.md) | Runtime-managed animated image, most typically a GIF. |
2222
| [`amp-audio`](amp-audio/amp-audio.md) | Replacement for the HTML5 `audio` tag. |
23+
| [`amp-brightcove`](amp-brightcove/amp-brightcove.md) | Displays a Brightcove Video Cloud or Perform player. |
2324
| [`amp-carousel`](amp-carousel/amp-carousel.md) | Generic carousel for displaying multiple similar pieces of content along a horizontal axis. |
2425
| [`amp-fit-text`](amp-fit-text/amp-fit-text.md) | Expand or shrink font size to fit the content within the space given. |
2526
| [`amp-font`](amp-font/amp-font.md) | Trigger and monitor the loading of custom fonts. |
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* Copyright 2015 The AMP HTML Authors. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS-IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {isLayoutSizeDefined} from '../../../src/layout';
18+
import {loadPromise} from '../../../src/event-helper';
19+
20+
21+
class AmpBrightcove extends AMP.BaseElement {
22+
23+
/** @override */
24+
createdCallback() {
25+
this.preconnect.url('https://players.brightcove.net');
26+
}
27+
28+
/** @override */
29+
isLayoutSupported(layout) {
30+
return isLayoutSizeDefined(layout);
31+
}
32+
33+
/** @override */
34+
layoutCallback() {
35+
const width = this.element.getAttribute('width');
36+
const height = this.element.getAttribute('height');
37+
const account = AMP.assert(
38+
this.element.getAttribute('data-account'),
39+
'The data-account attribute is required for <amp-brightcove> %s',
40+
this.element);
41+
const playerid = (this.element.getAttribute('data-player-id') || 'default');
42+
const embed = (this.element.getAttribute('data-embed') || 'default');
43+
const iframe = document.createElement('iframe');
44+
let src = 'https://players.brightcove.net/' + encodeURIComponent(account) + '/' + encodeURIComponent(playerid) + '_' + encodeURIComponent(embed) + '/index.html';
45+
if (this.element.getAttribute('data-playlist-id')) {
46+
src += '?playlistId=';
47+
src += this.encodeId_(this.element.getAttribute('data-playlist-id'));
48+
} else if (this.element.getAttribute('data-video-id')) {
49+
src += '?videoId=';
50+
src += this.encodeId_(this.element.getAttribute('data-video-id'));
51+
}
52+
iframe.setAttribute('frameborder', '0');
53+
iframe.setAttribute('allowfullscreen', 'true');
54+
iframe.src = src;
55+
this.applyFillContent(iframe);
56+
iframe.width = width;
57+
iframe.height = height;
58+
this.element.appendChild(iframe);
59+
/** @private {?Element} */
60+
this.iframe_ = iframe;
61+
return loadPromise(iframe);
62+
}
63+
64+
/** @private */
65+
encodeId_(id) {
66+
/* id is either a Brightcove-assigned id, or a customer-generated reference id.
67+
reference ids are prefixed 'ref:' and the colon must be preserved unencoded */
68+
if (id.substring(0,4) === 'ref:') {
69+
return 'ref:' + encodeURIComponent(id.substring(4));
70+
} else {
71+
return encodeURIComponent(id);
72+
}
73+
}
74+
75+
/** @override */
76+
documentInactiveCallback() {
77+
/*
78+
This stops playback with the postMessage API.
79+
Add this script to the player in the player configuration in the Studio
80+
or via the Player Management API:
81+
82+
http://players.brightcove.net/906043040001/plugins/postmessage_pause.js
83+
84+
It's not a 'real' video.js plugin, just a plain script running in
85+
the iframe so needs no configuration options.
86+
*/
87+
this.iframe_.contentWindow./*OK*/postMessage('pause', 'https://players.brightcove.net');
88+
return false;
89+
}
90+
};
91+
92+
AMP.registerElement('amp-brightcove', AmpBrightcove);
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* Copyright 2015 The AMP HTML Authors. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS-IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {createIframePromise} from '../../../../testing/iframe';
18+
require('../amp-brightcove');
19+
import {adopt} from '../../../../src/runtime';
20+
21+
adopt(window);
22+
23+
describe('amp-brightcove', () => {
24+
25+
function getBrightcove(accountId, videoId, opt_responsive) {
26+
return createIframePromise().then(iframe => {
27+
const bc = iframe.doc.createElement('amp-brightcove');
28+
bc.setAttribute('data-account', accountId);
29+
bc.setAttribute('width', '111');
30+
bc.setAttribute('height', '222');
31+
if (videoId) {
32+
bc.setAttribute('data-video-id', videoId);
33+
}
34+
if (opt_responsive) {
35+
bc.setAttribute('layout', 'responsive');
36+
}
37+
iframe.doc.body.appendChild(bc);
38+
bc.implementation_.layoutCallback();
39+
return bc;
40+
});
41+
}
42+
43+
it('renders', () => {
44+
return getBrightcove('906043040001','ref:ampdemo').then(bc => {
45+
const iframe = bc.querySelector('iframe');
46+
expect(iframe).to.not.be.null;
47+
expect(iframe.tagName).to.equal('IFRAME');
48+
expect(iframe.src).to.equal(
49+
'https://players.brightcove.net/906043040001/default_default/index.html?videoId=ref:ampdemo');
50+
expect(iframe.getAttribute('width')).to.equal('111');
51+
expect(iframe.getAttribute('height')).to.equal('222');
52+
});
53+
});
54+
55+
it('renders responsively', () => {
56+
return getBrightcove('906043040001', 'ref:ampdemo', true).then(bc => {
57+
const iframe = bc.querySelector('iframe');
58+
expect(iframe).to.not.be.null;
59+
expect(iframe.className).to.match(/-amp-fill-content/);
60+
});
61+
});
62+
63+
it('requires data-account', () => {
64+
return getBrightcove('').should.eventually.be.rejectedWith(
65+
/The data-account attribute is required for/);
66+
});
67+
});
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<!---
2+
Copyright 2015 Brightcove. All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS-IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
17+
### <a name="amp-brightcove"></a> `amp-brightcove`
18+
19+
An `amp-brightcove` component displays a Brightcove [Video Cloud](https://www.brightcove.com/en/online-video-platform) or [Perform](https://www.brightcove.com/en/perform) player.
20+
21+
Example:
22+
```html
23+
<amp-brightcove
24+
data-account="12345"
25+
data-player="default"
26+
data-embed="default"
27+
data-video-id="1234"
28+
layout="responsive"
29+
width="480" height="270">
30+
</amp-brightcove>
31+
```
32+
33+
The width and height will determine the aspect ratio of the player embed in responsive layouts.
34+
35+
#### Attributes
36+
37+
**data-account**
38+
39+
The Brightcove Video Cloud or Perform account id
40+
41+
**data-player**
42+
43+
The Brightcove player id. This is a GUID or "default". The default value is "default".
44+
45+
**data-embed**
46+
47+
The Brightcove player id. This is a GUID or "default". The default value and most common value is "default".
48+
49+
**data-video-id**
50+
51+
The Video Cloud video id. Most Video Cloud players will need this.
52+
This is not used for Perform players.
53+
54+
**data-playlist-id**
55+
56+
The Video Cloud playlist id. For AMP HTML uses a video id will normally be used instead. If both a playlist and a video are specified, the playlist takes precedence.
57+
This is not used for Perform players.
58+
59+
#### Player configuration
60+
61+
This script should be added to the configuration of Brightcove Players used with this component. This allows the AMP document to pause the player. Only the script need be added, no plugin name or JSON are needed.
62+
63+
* http://players.brightcove.net/906043040001/plugins/postmessage_pause.js

gulpfile.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ function buildExtensions(options) {
6767
// Each extension and version must be listed individually here.
6868
buildExtension('amp-anim', '0.1', false, options);
6969
buildExtension('amp-audio', '0.1', false, options);
70+
buildExtension('amp-brightcove', '0.1', false, options);
7071
buildExtension('amp-carousel', '0.1', true, options);
7172
buildExtension('amp-fit-text', '0.1', true, options);
7273
buildExtension('amp-font', '0.1', false, options);
@@ -84,7 +85,7 @@ function buildExtensions(options) {
8485
*/
8586
buildExtension('amp-slides', '0.1', false, options);
8687
buildExtension('amp-twitter', '0.1', false, options);
87-
buildExtension('amp-vine', '0.1', false, options);
88+
buildExtension('amp-vine', '0.1', false, options);
8889
buildExtension('amp-youtube', '0.1', false, options);
8990
}
9091

spec/amp-html-components.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ In these cases, services may set up endpoints that produce data that conforms to
178178
- [amp-ad](../builtins/amp-ad.md)
179179
- [amp-pixel](../builtins/amp-pixel.md)
180180
- [amp-video](../builtins/amp-video.md)
181+
- [amp-brightcove](../extensions/amp-brightcove/amp-brightcove.md)
181182
- [amp-carousel](../extensions/amp-carousel/amp-carousel.md)
182183
- [amp-font](../extensions/amp-font/amp-font.md)
183184
- [amp-lightbox](../extensions/amp-lightbox/amp-lightbox.md)

src/layout.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export const naturalDimensions_ = {
7272
*/
7373
export const LOADING_ELEMENTS_ = {
7474
'AMP-ANIM': true,
75+
'AMP-BRIGHTCOVE': true,
7576
'AMP-IFRAME': true,
7677
'AMP-IMG': true,
7778
'AMP-INSTAGRAM': true,

test/integration/test-example-validation.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ describe('example', function() {
3636

3737
const examples = [
3838
'ads.amp.html',
39+
'brightcove.amp.html',
3940
'metadata-examples/article-json-ld.amp.html',
4041
'metadata-examples/article-microdata.amp.html',
4142
'metadata-examples/recipe-json-ld.amp.html',
@@ -67,6 +68,9 @@ describe('example', function() {
6768

6869
// TODO(dvoytenko): Remove once validator supports "amp-font" element.
6970
/DISALLOWED_TAG amp-font/,
71+
72+
// Remove once validator supports "amp-brightcove".
73+
/DISALLOWED_TAG amp-brightcove/
7074
];
7175

7276
const usedWhitelist = [];

0 commit comments

Comments
 (0)