Skip to content
54 changes: 54 additions & 0 deletions extensions/amp-video/0.1/test/test-video-cache.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as Preact from '#core/dom/jsx';
import {createElementWithAttributes} from '#core/dom';

import {Services} from '#service';
Expand Down Expand Up @@ -494,6 +495,59 @@ describes.realWin('amp-video cached-sources', {amp: true}, (env) => {
});
});

describe('captions_url field', async () => {
it('should append track element if the cache responds with captions_url', async () => {
env.sandbox.stub(xhrService, 'fetch').resolves({
json: () =>
Promise.resolve({
'captions_url': 'captions_url_response.vtt',
'sources': [
{'url': 'video.mp4', 'bitrate_kbps': 700, 'type': 'video/mp4'},
],
}),
});
const videoEl = createVideo([{src: 'video.mp4'}]);
await fetchCachedSources(videoEl, env.ampdoc);

const trackEl = videoEl.querySelector('track');
expect(trackEl).to.exist;
});
it('should not append track element if video already has a track child', async () => {
Comment thread
processprocess marked this conversation as resolved.
env.sandbox.stub(xhrService, 'fetch').resolves({
json: () =>
Promise.resolve({
'captions_url': 'captions_url_response.vtt',
'sources': [
{'url': 'video.mp4', 'bitrate_kbps': 700, 'type': 'video/mp4'},
],
}),
});
const videoEl = createVideo([{src: 'video.mp4'}]);
videoEl.appendChild(<track />);
await fetchCachedSources(videoEl, env.ampdoc);

const trackEl = videoEl.querySelector(
'track[src="captions_url_response.vtt"]'
);
expect(trackEl).to.not.exist;
});
it('should not append track element if captions_url does not exist', async () => {
env.sandbox.stub(xhrService, 'fetch').resolves({
json: () =>
Promise.resolve({
'sources': [
{'url': 'video.mp4', 'bitrate_kbps': 700, 'type': 'video/mp4'},
],
}),
});
const videoEl = createVideo([{src: 'video.mp4'}]);
await fetchCachedSources(videoEl, env.ampdoc);

const trackEl = videoEl.querySelector('track');
expect(trackEl).to.not.exist;
});
});

describe('web stories: inlined video', async () => {
it('should use the inlined source for the first video in the story instead of sending an XHR request', async () => {
// Set up an inlined source response for the first video in the story
Expand Down
18 changes: 18 additions & 0 deletions extensions/amp-video/0.1/video-cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export function fetchCachedSources(
.then((response) => {
applySourcesToVideo(videoEl, response['sources'], maxBitrate);
applyAudioInfoToVideo(videoEl, response['has_audio']);
applyCaptionsTrackToVideo(videoEl, response['captions_url']);
})
.catch(() => {
// If cache fails, video should still load properly.
Expand Down Expand Up @@ -156,6 +157,23 @@ function applyAudioInfoToVideo(videoEl, hasAudio) {
}
}

/**
* Appends captions track to video if captions url is defined and video
* element doesn't have a track child specified in the document.
* @param {!Element} videoEl
* @param {string|undefined} captionsUrl
*/
function applyCaptionsTrackToVideo(videoEl, captionsUrl) {
if (!captionsUrl || videoEl.querySelector('track')) {
return;
}
const trackEl = createElementWithAttributes(videoEl.ownerDocument, 'track', {
'src': captionsUrl,
'kind': 'captions',
});
videoEl.appendChild(trackEl);
}

/**
* If present, moves the src attribute to a source element to enable playing
* from multiple sources: the cached ones and the fallback initial src.
Expand Down