cloudinary-video-player
Version:
Cloudinary Video Player
130 lines (124 loc) • 4.14 kB
JavaScript
import './download-button.js';
import { g as getCloudinaryUrl, o as omit } from './index2.js';
import './_videojs-proxy.js';
import './_commonjsHelpers.js';
import './video-player.const.js';
import './cloudinary-config-from-options.js';
import './cloudinary-url-prefix.js';
const SharePlugin = function () {
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
let playerInstance = arguments.length > 1 ? arguments[1] : undefined;
const player = playerInstance || this;
player.addClass('vjs-share');
const addDownloadButton = () => {
const controlBar = player.getChild('ControlBar');
if (!controlBar || controlBar.getChild('ShareDownloadButton')) {
return;
}
const children = controlBar.children();
const insertBeforeIndex = children.findIndex(c => c.name_ === 'FullscreenToggle');
controlBar.addChild('ShareDownloadButton', {}, insertBeforeIndex !== -1 ? insertBeforeIndex : undefined);
};
const removeDownloadButton = () => {
if (!player.controlBar) {
return;
}
const btn = player.controlBar.getChild('ShareDownloadButton');
if (btn) {
player.controlBar.removeChild(btn);
}
};
const getDownloadUrl = () => {
const source = player.currentSource?.();
if (!source) {
return null;
}
// Strip format / codec related transformation arrays
const STRIP_KEYS = ['format', 'video_codec', 'streaming_profile'];
const stripKeysDeep = value => {
if (Array.isArray(value)) {
return value.map(stripKeysDeep);
}
if (value && typeof value === 'object') {
const cleaned = omit(value, STRIP_KEYS);
Object.keys(cleaned).forEach(k => {
cleaned[k] = stripKeysDeep(cleaned[k]);
});
return cleaned;
}
return value;
};
const transformations = stripKeysDeep(player.cloudinary.transformation() || {});
const filename = player.cloudinary.currentPublicId()?.split('/')?.pop();
const baseOptions = {
...player.cloudinary.cloudinaryConfig(),
...transformations,
resource_type: 'video',
format: 'mp4',
video_codec: 'h264',
flags: `streaming_attachment:${filename}`
};
// For ABR - download a limited-size video
if (source.isAdaptive) {
Object.assign(baseOptions, {
crop: 'limit',
width: 1920,
height: 1920
});
}
// For audio sources, set the format to mp3
if (player.cloudinary.source()?.getType() === 'AudioSource') {
Object.assign(baseOptions, {
format: 'mp3',
video_codec: undefined
});
}
return getCloudinaryUrl(player.cloudinary.currentPublicId(), baseOptions);
};
const download = () => {
const url = getDownloadUrl();
if (!url) {
console.warn('Share plugin: Unable to resolve download URL.');
return;
}
const MAX_ATTEMPTS = 60; // 60 tries / 10s interval
const INTERVAL_MS = 10000;
const RETRY_STATUS_CODES = [423];
const triggerDownload = () => {
const a = document.createElement('a');
a.href = url;
a.download = '';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
const btn = player.controlBar?.getChild('ShareDownloadButton');
const setPreparingState = isPreparing => {
btn?.setPreparing?.(isPreparing);
};
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
const fetchDownload = async function () {
let attempt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
const response = await fetch(url, {
method: 'HEAD'
});
if (RETRY_STATUS_CODES.includes(response.status) && attempt < MAX_ATTEMPTS) {
await wait(INTERVAL_MS);
return fetchDownload(attempt + 1);
}
setPreparingState(false);
triggerDownload();
};
setPreparingState(true);
fetchDownload();
};
if (options.download) {
addDownloadButton();
}
player.share = {
download,
addDownloadButton,
removeDownloadButton
};
};
export { SharePlugin as default };