Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/es-modules/fluid.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ <h3 class="mb-4">Fluid Layouts</h3>
</div>

<script type="module">
import { videoPlayer } from 'cloudinary-video-player';
import videoPlayer from 'cloudinary-video-player/videoPlayer';
import 'cloudinary-video-player/cld-video-player.min.css';

const player = videoPlayer('player', { cloudName: 'demo' });
Expand Down
10 changes: 5 additions & 5 deletions docs/es-modules/transformations.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ <h4 class="mt-4 mb-2">via data-cld-transformation</h4>

<script type="module">
import 'cloudinary-video-player/cld-video-player.min.css';
import { videoPlayer } from 'cloudinary-video-player';
import player from 'cloudinary-video-player/player';

const player = videoPlayer('player-1', {
const myPlayer = player('player-1', {
cloudName: 'demo'
});

player.source({
myPlayer.source({
publicId: 'snow_horses',
info: { title: 'Snow Horses', subtitle: 'A movie about horses' },
transformation: [
Expand All @@ -70,7 +70,7 @@ <h4 class="mt-4 mb-2">via data-cld-transformation</h4>
]
});

videoPlayer('player-2', {
player('player-2', {
cloudName: 'demo',
transformation: [
{ width: 400, crop: 'limit' },
Expand All @@ -79,7 +79,7 @@ <h4 class="mt-4 mb-2">via data-cld-transformation</h4>
]
});

videoPlayer('player-3', {
player('player-3', {
cloudName: 'demo'
});
</script>
Expand Down
25 changes: 13 additions & 12 deletions src/index.all.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@

import cloudinary from './index.js';

export * from './index.js';
export * from './plugins/adaptive-streaming/adaptive-streaming.js';
export * from './plugins/chapters/chapters.js';
export * from './plugins/colors/colors.js';
export * from './plugins/ima/ima.js';
export * from './plugins/playlist/playlist.js';
export * from './plugins/interaction-areas/interaction-areas.service.js';
export * from './plugins/visual-search/visual-search.js';
export * from './plugins/text-tracks-manager/index.js';
export * from './plugins/share/share.js';
export * from './components/shoppable-bar/shoppable-widget.js';
export * from './components/recommendations-overlay/recommendations-overlay.js';
// Import plugin implementations so webpack bundles them in /all.js
import './plugins/adaptive-streaming/adaptive-streaming.js';
import './plugins/chapters/chapters.js';
import './plugins/colors/colors.js';
import './plugins/ima/ima.js';
import './plugins/playlist/playlist.js';
import './plugins/interaction-areas/interaction-areas.service.js';
import './plugins/visual-search/visual-search.js';
import './plugins/share/share.js';
import './plugins/text-tracks-manager/text-tracks-manager.js';
import './components/shoppable-bar/shoppable-widget.js';
import './components/recommendations-overlay/recommendations-overlay.js';

export * from './index.js';
export default cloudinary;
19 changes: 0 additions & 19 deletions src/index.es.js

This file was deleted.

201 changes: 9 additions & 192 deletions src/plugins/text-tracks-manager/index.js
Original file line number Diff line number Diff line change
@@ -1,194 +1,11 @@
import { utf8ToBase64 } from '../../utils/utf8Base64';
import { getCloudinaryUrlPrefix } from '../cloudinary/common';
import { transcriptParser } from './parsers/transcriptParser';
import { srtParser } from './parsers/srtParser';
import { vttParser } from './parsers/vttParser';
import { addTextTrackCues, fetchFileContent, refreshTextTrack, removeAllTextTrackCues } from './utils';

const getTranscriptionFileUrl = (urlPrefix, deliveryType, publicId, languageCode = null) =>
`${urlPrefix}/_applet_/video_service/transcription/${deliveryType}/${languageCode ? `${languageCode}/` : ''}${utf8ToBase64(publicId)}.transcript`;

function textTracksManager() {
export default async function lazyTextTracksManagerPlugin() {
const player = this;
const textTracksData = new WeakMap();
let activeTrack = null;

const removeAllTextTracks = () => {
const currentTracks = player.remoteTextTracks();
if (currentTracks) {
for (let i = currentTracks.tracks_.length - 1; i >= 0; i--) {
player.removeRemoteTextTrack(currentTracks.tracks_[i]);
}
}
};

const createTextTrackData = (textTrack, loadMethod) => {
const controller = new AbortController();
textTracksData.set(textTrack, {
status: 'idle',
load: async () => {
const { status } = textTracksData.get(textTrack);
if (status === 'idle') {
await loadMethod(controller.signal);
refreshTextTrack(textTrack);
}
},
abortLoading: () => {
const { status } = textTracksData.get(textTrack);
if (status === 'pending') {
controller.abort();
}
},
});
};

const updateTextTrackData = (textTrack, dataToUpdate) => {
const existingData = textTracksData.get(textTrack);
textTracksData.set(textTrack, {
...existingData,
...dataToUpdate,
});
};
const updateTextTrackStatusToPending = (textTrack) => updateTextTrackData(textTrack, { status: 'pending' });
const updateTextTrackStatusToSuccess = (textTrack) => updateTextTrackData(textTrack, { status: 'success' });
const updateTextTrackStatusToError = (textTrack, error) => updateTextTrackData(textTrack, { status: 'error', error });
const updateTextTrackStatusToApplied = (textTrack) => updateTextTrackData(textTrack, { status: 'applied' });

const addTextTrack = (type, config) => {
const {
kind = type === 'transcript' ? 'captions' : 'subtitles',
label = type === 'transcript' ? 'Captions' : 'Subtitles',
default: isDefault,
srclang,
src,
} = config;

if (type === 'transcript') {
player.textTrackDisplay.el().classList.add('cld-paced-text-tracks');
}

const { track } = player.addRemoteTextTrack({
kind,
label,
srclang,
default: isDefault,
mode: isDefault ? 'showing' : 'disabled',
});

const createParser = () => {
if (type === 'srt') return srtParser;
if (type === 'vtt') return vttParser;
return (text) => transcriptParser(text, {
maxWords: config.maxWords,
wordHighlight: config.wordHighlight,
timeOffset: config.timeOffset ?? 0,
});
};

const createSourceUrl = () => {
if (src) return src;
if (type !== 'transcript') return undefined;

const source = player.cloudinary.source();
const publicId = source.publicId();
const deliveryType = source.resourceConfig().type;
const urlPrefix = getCloudinaryUrlPrefix(player.cloudinary.cloudinaryConfig());
const baseUrl = getTranscriptionFileUrl(urlPrefix, deliveryType, publicId);
const localizedUrl = srclang ? getTranscriptionFileUrl(urlPrefix, deliveryType, publicId, srclang) : null;

return localizedUrl ? localizedUrl : baseUrl;
};

createTextTrackData(track, async (signal) => {
updateTextTrackStatusToPending(track);

const sourceUrl = createSourceUrl();
const response = await fetchFileContent(
sourceUrl,
{
signal,
polling: type === 'transcript' && !src,
interval: 2000,
maxAttempts: 10,
responseStatusAsPending: 202,
onSuccess: () => updateTextTrackStatusToSuccess(track),
onError: (error) => {
updateTextTrackStatusToError(track, error);
console.warn(`[${track.label}] Text track could not be loaded`);
},

}
);

if (response) {
const parser = createParser();
const data = await parser(response);
removeAllTextTrackCues(track);
addTextTrackCues(track, data);
updateTextTrackStatusToApplied(track);
}
});
};


const addTextTracks = (textTracks) => {
textTracks.forEach(textTrackConfig => {
if (textTrackConfig.src && textTrackConfig.src.endsWith('.vtt')) {
addTextTrack('vtt', textTrackConfig);
} else if (textTrackConfig.src && textTrackConfig.src.endsWith('.srt')) {
addTextTrack('srt', textTrackConfig);
} else if (!textTrackConfig.src || textTrackConfig.src.endsWith('.transcript')) {
addTextTrack('transcript', textTrackConfig);
}
});

const defaultTextTrack = Array.from(player.remoteTextTracks()).find((textTrack) => textTrack.default);
if (defaultTextTrack) {
onChangeActiveTrack(defaultTextTrack);
}
};

const onChangeActiveTrack = (textTrack) => {
const prevActiveTrack = activeTrack;
activeTrack = textTrack;

const prevTextTrackData = textTracksData.get(prevActiveTrack);
if (prevTextTrackData) {
prevTextTrackData.abortLoading();
}

const selectedTextTrackData = textTracksData.get(activeTrack);
if (selectedTextTrackData) {
selectedTextTrackData.load();
}
};

player.on('texttrackchange', () => {
const textTracks = player.textTracks();
let newActiveTrack = null;

for (let i = 0; i < textTracks.length; i++) {
const track = textTracks[i];

if (track.mode === 'showing') {
newActiveTrack = track;
break;
}
}

if (activeTrack !== newActiveTrack) {
onChangeActiveTrack(newActiveTrack);
}
});

return {
removeAllTextTracks,
addTextTracks: (...args) => {
player.one('loadedmetadata', () => {
addTextTracks(...args);
});
},
};
try {
const { default: textTracksManager } = await import(
/* webpackChunkName: "text-tracks" */ './text-tracks-manager'
);
return textTracksManager.call(player);
} catch (error) {
console.error('Failed to load text tracks manager plugin:', error);
}
}

export default textTracksManager;
Loading
Loading