Skip to content

Commit 2dfb862

Browse files
authored
feat(VIDEO-20110): video-elements - add support for poster (#926)
* feat(VIDEO-20110): video-elements - add support for poster * chore: bundlewatch * chore: fix options.resource_type * chore: tx query string * chore: e2e example page * chore: poster analytics and E2e
1 parent 210a235 commit 2dfb862

File tree

5 files changed

+79
-5
lines changed

5 files changed

+79
-5
lines changed

docs/es-modules/poster.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ <h4>Raw URL - default with no poster image</h4>
5353
<video id="player-raw" playsinline controls class="cld-video-player cld-fluid"></video>
5454
</div>
5555

56+
<div class="video-container mb-4">
57+
<h4>Applet poster (poster: true)</h4>
58+
<h6>Uses applet service URL for poster</h6>
59+
<video id="player-applet-poster" playsinline controls class="cld-video-player cld-fluid"></video>
60+
</div>
61+
5662
<p class="mt-4">
5763
<a href="https://cloudinary.com/documentation/cloudinary_video_player"
5864
>Full documentation</a
@@ -89,6 +95,12 @@ <h4>Raw URL - default with no poster image</h4>
8995
cloudName: 'demo',
9096
publicId: 'https://res.cloudinary.com/demo/video/upload/sp_auto/sea_turtle.m3u8'
9197
});
98+
99+
const playerAppletPoster = videoPlayer('player-applet-poster', {
100+
cloudName: 'demo',
101+
publicId: 'snow_horses',
102+
poster: true
103+
});
92104
</script>
93105

94106
<!-- Bootstrap -->

docs/poster.html

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@
5656
publicId: 'https://res.cloudinary.com/demo/video/upload/sp_auto/sea_turtle.m3u8'
5757
});
5858

59+
player5 = cloudinary.videoPlayer('player-applet-poster', {
60+
cloud_name: 'demo',
61+
publicId: 'snow_horses',
62+
poster: true
63+
});
64+
5965
}, false);
6066
</script>
6167

@@ -113,6 +119,17 @@ <h4>Raw URL - default with no poster image</h4>
113119
></video>
114120
</div>
115121

122+
<div class="video-container mb-4">
123+
<h4>Applet poster (poster: true)</h4>
124+
<h6>Uses applet service URL for poster</h6>
125+
<video
126+
id="player-applet-poster"
127+
playsinline
128+
controls
129+
class="cld-video-player cld-fluid"
130+
></video>
131+
</div>
132+
116133
<p class="mt-4">
117134
<a href="https://cloudinary.com/documentation/video_player_api_reference#posteroptions">Full documentation</a>
118135
</p>
@@ -151,6 +168,13 @@ <h3 class="mt-4">Example Code:</h3>
151168
class="cld-video-player cld-fluid"
152169
&lt;/video&gt;
153170

171+
&lt;video
172+
id="player-applet-poster"
173+
playsinline
174+
controls
175+
class="cld-video-player cld-fluid"
176+
&lt;/video&gt;
177+
154178
</code>
155179
<code class="language-javascript">
156180

@@ -179,6 +203,12 @@ <h3 class="mt-4">Example Code:</h3>
179203
publicId: 'https://res.cloudinary.com/demo/video/upload/sp_auto/sea_turtle.m3u8'
180204
});
181205

206+
player5 = cloudinary.videoPlayer('player-applet-poster', {
207+
cloud_name: 'demo',
208+
publicId: 'snow_horses',
209+
poster: true
210+
});
211+
182212
</code>
183213
</pre>
184214
</div>

src/plugins/cloudinary/index.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,14 @@ class CloudinaryContext {
122122
options.cloudinaryConfig = extendCloudinaryConfig(this.cloudinaryConfig(), options.cloudinaryConfig || {});
123123
options.transformation = mergeTransformations(this.transformation(), options.transformation || {});
124124
options.sourceTransformation = options.sourceTransformation || this.sourceTransformation();
125-
options.sourceTypes = options.sourceTypes || this.sourceTypes();
126-
options.poster = options.poster || posterOptionsForCurrent();
125+
options.sourceTypes = options.sourceTypes || this.sourceTypes();
126+
127+
128+
const defaultPosterOptions = posterOptionsForCurrent();
129+
const userPosterOptions = options.posterOptions || {};
130+
options.poster = options.poster || defaultPosterOptions;
131+
options.posterOptions = Object.assign({}, defaultPosterOptions, userPosterOptions);
132+
127133
options.queryParams = Object.assign(options.queryParams || {}, options.allowUsageReport ? { _s: `vp-${VERSION}` } : {});
128134

129135
if (options.sourceTypes.indexOf('audio') > -1) {

src/plugins/cloudinary/models/video-source/video-source.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ import {
1414
hasCodec,
1515
normalizeFormat
1616
} from './video-source.utils';
17-
import { normalizeOptions, isSrcEqual, isRawUrl, mergeTransformations } from '../../common';
17+
import { normalizeOptions, isSrcEqual, isRawUrl, mergeTransformations, getCloudinaryUrlPrefix } from '../../common';
18+
import { utf8ToBase64 } from 'utils/utf8Base64';
19+
import Transformation from '@cloudinary/url-gen/backwards/transformation';
1820
import BaseSource from '../base-source';
1921
import ImageSource from '../image-source';
2022

@@ -127,9 +129,28 @@ class VideoSource extends BaseSource {
127129
}
128130

129131
options.cloudinaryConfig = options.cloudinaryConfig || this.cloudinaryConfig();
130-
132+
131133
options.resource_type = this.resourceType() || options.resource_type;
132-
134+
135+
if (publicId === true) {
136+
const urlPrefix = getCloudinaryUrlPrefix(options.cloudinaryConfig);
137+
const deliveryType = this.getInitOptions().type || 'upload';
138+
const base64PublicId = utf8ToBase64(this.publicId());
139+
let appletUrl = `${urlPrefix}/_applet_/video_service/elements/${deliveryType}/${base64PublicId}/poster`;
140+
141+
const transformation = this.getInitOptions().posterOptions?.transformation;
142+
if (transformation) {
143+
const transformationString = new Transformation(transformation).toString();
144+
appletUrl += `?tx=${transformationString}`;
145+
}
146+
147+
this._poster = new ImageSource(appletUrl, {
148+
cloudinaryConfig: options.cloudinaryConfig
149+
});
150+
151+
return this;
152+
}
153+
133154
this._poster = new ImageSource(publicId, options);
134155

135156
return this;

src/utils/get-analytics-player-options.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ const filterDefaultsAndNulls = (obj) => Object.entries(obj).reduce((filtered, [k
1212
}, {});
1313

1414
const getSourceOptions = (sourceOptions = {}) => ({
15+
poster: (() => {
16+
if (sourceOptions.poster === true) return 'auto';
17+
if (typeof sourceOptions.poster === 'string') return 'url';
18+
return undefined;
19+
})(),
1520
posterOptions: hasConfig(sourceOptions.posterOptions),
1621
posterOptionsPublicId: sourceOptions.posterOptions && hasConfig(sourceOptions.posterOptions.publicId),
1722
autoShowRecommendations: sourceOptions.autoShowRecommendations,

0 commit comments

Comments
 (0)