Skip to content

Commit 3841f73

Browse files
committed
feat: high dynamic-range (HDR) detection
1 parent 59abd09 commit 3841f73

19 files changed

Lines changed: 273 additions & 0 deletions

File tree

docs/es-modules/hdr.html

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>Cloudinary Video Player</title>
6+
<link
7+
href="https://res.cloudinary.com/cloudinary-marketing/image/upload/f_auto,q_auto/c_scale,w_32,e_hue:290/creative_staging/cloudinary_internal/Website/Brand%20Updates/Favicon/cloudinary_web_favicon_192x192.png"
8+
rel="icon"
9+
type="image/png"
10+
/>
11+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
12+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
13+
</head>
14+
<body>
15+
<div class="container p-4 col-12 col-md-9 col-xl-6">
16+
<nav class="nav mb-2">
17+
<a href="/index.html">&#60;&#60; Back to examples index</a>
18+
</nav>
19+
<h1>Cloudinary Video Player</h1>
20+
<h3 class="mb-4">HDR</h3>
21+
22+
<div class="form-check mb-2">
23+
<input type="checkbox" class="form-check-input" id="hdr-toggle" checked>
24+
<label class="form-check-label" for="hdr-toggle">Enable HDR</label>
25+
</div>
26+
27+
<video
28+
id="player"
29+
playsinline
30+
controls
31+
muted
32+
autoplay
33+
class="cld-video-player"
34+
width="500"
35+
></video>
36+
</div>
37+
38+
<script type="module">
39+
import { videoPlayer } from 'cloudinary-video-player';
40+
import 'cloudinary-video-player/cld-video-player.min.css';
41+
42+
function loadSource(hdrEnabled) {
43+
player.source('video/examples/hdr', { hdr: hdrEnabled, info: { title: hdrEnabled ? 'HDR' : 'SDR' } });
44+
}
45+
46+
const player = videoPlayer('player', { cloudName: 'prod' });
47+
loadSource(true);
48+
49+
document.getElementById('hdr-toggle').addEventListener('change', function () {
50+
loadSource(this.checked);
51+
});
52+
</script>
53+
54+
<!-- Bootstrap -->
55+
<link
56+
href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
57+
rel="stylesheet"
58+
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
59+
crossorigin="anonymous"
60+
/>
61+
</body>
62+
</html>

docs/es-modules/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ <h3 class="mt-4">Code examples:</h3>
6060
<li><a href="./floating-player.html">Floating Player</a></li>
6161
<li><a href="./fluid.html">Fluid Layouts</a></li>
6262
<li><a href="./force-hls-subtitles.html">Force HLS Subtitles</a></li>
63+
<li><a href="./hdr.html">HDR</a></li>
6364
<li><a href="./interaction-area.html">Interaction Area</a></li>
6465
<li><a href="./multiple-players.html">Multiple Players</a></li>
6566
<li><a href="./playlist.html">Playlist</a></li>

docs/hdr.html

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Cloudinary Video Player</title>
6+
<link href="https://res.cloudinary.com/cloudinary-marketing/image/upload/f_auto,q_auto/c_scale,w_32/v1597183771/creative_staging/cloudinary_internal/Website/Brand%20Updates/Favicon/cloudinary_web_favicon_192x192.png" rel="icon" type="image/png">
7+
8+
<!-- Bootstrap -->
9+
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
10+
11+
<!-- highlight.js -->
12+
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/solarized-light.min.css">
13+
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
14+
<script>hljs.initHighlightingOnLoad();</script>
15+
16+
<!--
17+
We're loading scripts & style dynamically for development/testing.
18+
Real-world usage would look like this:
19+
20+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cloudinary-video-player/dist/cld-video-player.min.css">
21+
<script src="https://cdn.jsdelivr.net/npm/cloudinary-video-player/dist/cld-video-player.min.js"></script>
22+
-->
23+
24+
<script type="text/javascript" src="./scripts.js"></script>
25+
26+
<script type="text/javascript">
27+
var player;
28+
29+
function loadSource(hdrEnabled) {
30+
player.source('video/examples/hdr', { hdr: hdrEnabled, info: { title: hdrEnabled ? 'HDR' : 'SDR' } });
31+
}
32+
33+
window.addEventListener('load', function(){
34+
player = cloudinary.videoPlayer('player', { cloud_name: 'prod' });
35+
loadSource(true);
36+
37+
document.getElementById('hdr-toggle').addEventListener('change', function() {
38+
loadSource(this.checked);
39+
});
40+
}, false);
41+
</script>
42+
43+
</head>
44+
<body>
45+
<div class="container p-4 col-12 col-md-9 col-xl-6">
46+
<nav class="nav mb-2">
47+
<a href="./index.html">&#60;&#60; Back to examples index</a>
48+
</nav>
49+
<h1>Cloudinary Video Player</h1>
50+
<h3 class="mb-4">HDR</h3>
51+
52+
<div class="form-check mb-2">
53+
<input type="checkbox" class="form-check-input" id="hdr-toggle" checked>
54+
<label class="form-check-label" for="hdr-toggle">Enable HDR</label>
55+
</div>
56+
57+
<video
58+
id="player"
59+
playsinline
60+
controls
61+
muted
62+
autoplay
63+
class="cld-video-player"
64+
width="500">
65+
</video>
66+
67+
<p class="mt-4">
68+
<a href="https://cloudinary.com/documentation/cloudinary_video_player">Full documentation</a>
69+
</p>
70+
71+
<h3 class="mt-4">Example Code:</h3>
72+
<pre>
73+
<code class="language-html">
74+
&lt;video
75+
id="player"
76+
playsinline
77+
controls
78+
muted
79+
autoplay
80+
class="cld-video-player"
81+
width="500"&gt;
82+
&lt;/video&gt;
83+
</code>
84+
<code class="language-javascript">
85+
player = cloudinary.videoPlayer('player', { cloud_name: 'prod' });
86+
player.source('video/examples/hdr', { hdr: true, info: { title: 'HDR' } });
87+
</code>
88+
</pre>
89+
</div>
90+
91+
</body>
92+
</html>

docs/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ <h3 class="mt-4">Some code examples:</h3>
6464
<li><a href="./floating-player.html">Floating Player</a></li>
6565
<li><a href="./fluid.html">Fluid Layouts</a></li>
6666
<li><a href="./force-hls-subtitles-ios.html">Force HLS Subtitles</a></li>
67+
<li><a href="./hdr.html">HDR</a></li>
6768
<li><a href="./interaction-area.html">Interaction Area</a></li>
6869
<li><a href="./live-streaming.html">Live Streaming</a></li>
6970
<li><a href="./multiple-players.html">Multiple Players</a></li>

src/config/configSchema.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@
143143
"type": "boolean",
144144
"default": false
145145
},
146+
"hdr": {
147+
"type": "boolean",
148+
"default": false
149+
},
146150
"seekThumbnails": {
147151
"type": "boolean",
148152
"default": true

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export const DEFAULT_POSTER_PARAMS = { format: 'jpg', resource_type: 'video' };
33
export const DEFAULT_VIDEO_PARAMS = {
44
resource_type: 'video',
55
type: 'upload',
6+
hdr: false,
67
transformation: [],
78
sourceTransformation: {},
89
sourceTypes: ['auto'],

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,14 @@ class VideoSource extends BaseSource {
204204
}
205205
}
206206

207+
// dr (dynamic range) is not yet exposed by @cloudinary/url-gen, so we use raw_transformation
208+
if (this.hdr() === true && window.matchMedia && window.matchMedia('(dynamic-range: high)').matches) {
209+
opts.transformation = mergeTransformations(opts.transformation, {
210+
video_codec: 'h265',
211+
raw_transformation: 'dr_high'
212+
});
213+
}
214+
207215
const src = appendQueryParams(this.config().url(this.publicId(), opts), this.queryParams());
208216

209217
return {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const getSourceOptions = (sourceOptions = {}) => ({
3030
})(),
3131
visualSearch: sourceOptions.visualSearch,
3232
download: hasConfig(sourceOptions.download),
33+
hdr: hasConfig(sourceOptions.hdr),
3334
recommendations: sourceOptions.recommendations && sourceOptions.recommendations.length,
3435
...(hasConfig(sourceOptions.adaptiveStreaming) ? {
3536
abrStrategy: sourceOptions?.adaptiveStreaming?.strategy === defaults.adaptiveStreaming.strategy ? undefined : sourceOptions?.adaptiveStreaming?.strategy,

src/validators/validators.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export const playerValidators = {
8585

8686
export const sourceValidators = {
8787
raw_transformation: validator.isString,
88+
hdr: validator.isBoolean,
8889
resourceType: validator.isString,
8990
shoppable: validator.isPlainObject,
9091
chapters: validator.or(validator.isBoolean, validator.isPlainObject),

src/video-player.const.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export const SOURCE_PARAMS = [
77
'cloudinaryConfig',
88
'description',
99
'download',
10+
'hdr',
1011
'info',
1112
'interactionAreas',
1213
'poster',

0 commit comments

Comments
 (0)