Serving HLS Content from CUE Front
The tomorrow-online
demo publication supplied with
CUE Front handles video content in general, but does not support HLS
streaming. You can modify it to support HLS streaming using the
VideoJS video player as
follows:
-
Make sure the videoJS library is loaded by adding the following lines to
templates/_patterns/01-globals/05-nonvisual/_scriptsBlock.twig
:<script src="https://vjs.zencdn.net/7.8.4/video.js"></script> <script src="https://unpkg.com/@videojs/http-streaming@2.1.0/dist/videojs-http-streaming.min.js"></script>
-
Include the VideoJS stylesheet in
templates/_patterns/01-globals/05-nonvisual/_stylesheet.twig
:<link href="https://vjs.zencdn.net/7.8.4/video-js.css" rel="stylesheet" />
-
Make the following highlighted changes to
templates/_patterns/02-atoms/03-videos/04-cloud-video.twig
:{% set video = article.mediaInfo.videos[1] %} {# Change the index value to the appropriate video source #} {% set captions = article.caption_href %} <div class="video-teaser"> {% if article.mediaInfo.headers is not empty %} {% for header in article.mediaInfo.headers if header.key == "Set-Cookie" %} {{ set_header("Set-Cookie", header.value) }} {% endfor %} {% endif %} <video id="video-js-{{ article.id }}" class="video-js" width="{{ video.width }}" height="{{ video.height }}" controls> {# <source src="{{ video.uri }}" type="{{ video.mimeType }}">#} {% if captions is not empty %} <track kind="subtitles" src="{{ captions | relativize }}" default> {% endif %} Your browser does not support HTML5 video. </video> <script type="text/javascript"> document.addEventListener("DOMContentLoaded", () => { const player = videojs("video-js-{{ article.id }}"); player.pause(); player.fluid(true); player.src({ src: '{{ video.uri }}', type: '{{ video.mimeType }}', withCredentials: true, }); player.load(); }); </script> </div>
-
To be able to render inline HLS video in storylines, you also need to make the following highlighted additions to
templates/_patterns/02-atoms/11-storyline-elements/storyline-element-video.twig
:{% set video = element.relation.mediaInfo.videos[1] %} {% set autoplay = 0 %} {% set allowFullScreen = 0 %} {% set closedcaption = 0 %} {% for fieldValue in element.fields %} {% if fieldValue.name == 'closedcaption' and fieldValue.booleanValue == 1 %} {% set closecaption = 1 %} {% endif %} {% if fieldValue.name == 'autoplay' and fieldValue.booleanValue == 1 %} {% set autoplay = 1 %} {% endif %} {% if fieldValue.name == 'allowfullscreen' and fieldValue.booleanValue == 1 %} {% set allowFullScreen = 1 %} {% endif %} {% endfor %} {% if element.relation.mediaInfo.headers is not empty %} {% for header in element.relation.mediaInfo.headers if header.key == "Set-Cookie" %} {{ set_header("Set-Cookie", header.value) }} {% endfor %} {% endif %} <video id="video-js-{{ element.relation.id }}" class="video-js mb2" width="{{ video.width }}" height="{{ video.height }}" controls> {# <source src="{{element.relation.mediaInfo.videos[1].uri}}" >#} <track label="English" srclang="en" src="{{ element.relation.caption_href }}" {% if closecaption == 1 %} kind="subtitles" {% endif %} default > Your browser does not support HTML5 video. </video> {% if element.relation.fields.description is not empty %} <div class="f6 header-font mt3 primary mb4"> {{ element.relation.fields.description }} </div> {% endif %} <script type="text/javascript"> document.addEventListener("DOMContentLoaded", () => { const player = videojs("video-js-{{ element.relation.id }}", { autoplay: {% if autoplay == 1 %}true{% else %}false{% endif %}, BigPlayButton: true, fluid: true, children: { controlBar: { subtitlesButton: true, captionsButton: true, fullscreenToggle: {% if allowFullScreen == 1 %} true {% else %} false {% endif %} } } }); player.pause(); player.src({ src: '{{ video.uri }}', type: '{{ video.mimeType }}', withCredentials: true, }); player.load(); player.ready(() => { {% if allowFullScreen == 0 %} // Disable entering full screen on double click player.tech_.off('dblclick'); {% endif %} }); }); </script>
-
If you are using signed cookies for access control, then you will also need to add the following GraphQL code to
recipe/queries/video.graphql
:... on Video { mediaInfo { headers { key value } } }
This makes sure that the requires headers are included in the JSON data returned by the Cook. The template changes listed above for
04-cloud-video.twig
and03-videos/04-cloud-video.twig
include code for forwarding any supplied headers:{% if article.mediaInfo.headers is not empty %} {% for header in article.mediaInfo.headers if header.key == "Set-Cookie" %} {{ set_header("Set-Cookie", header.value) }} {% endfor %} {% endif %}
If you are not intending to use signed cookies, then you can omit this code from both templates.