119 lines
3.4 KiB
JavaScript
119 lines
3.4 KiB
JavaScript
// ==========================================================================
|
|
// Plyr support checks
|
|
// ==========================================================================
|
|
|
|
import { transitionEndEvent } from './utils/animation';
|
|
import browser from './utils/browser';
|
|
import { createElement } from './utils/elements';
|
|
import is from './utils/is';
|
|
|
|
// Default codecs for checking mimetype support
|
|
const defaultCodecs = {
|
|
'audio/ogg': 'vorbis',
|
|
'audio/wav': '1',
|
|
'video/webm': 'vp8, vorbis',
|
|
'video/mp4': 'avc1.42E01E, mp4a.40.2',
|
|
'video/ogg': 'theora',
|
|
};
|
|
|
|
// Check for feature support
|
|
const support = {
|
|
// Basic support
|
|
audio: 'canPlayType' in document.createElement('audio'),
|
|
video: 'canPlayType' in document.createElement('video'),
|
|
|
|
// Check for support
|
|
// Basic functionality vs full UI
|
|
check(type, provider, playsinline) {
|
|
const canPlayInline = browser.isIPhone && playsinline && support.playsinline;
|
|
const api = support[type] || provider !== 'html5';
|
|
const ui = api && support.rangeInput && (type !== 'video' || !browser.isIPhone || canPlayInline);
|
|
|
|
return {
|
|
api,
|
|
ui,
|
|
};
|
|
},
|
|
|
|
// Picture-in-picture support
|
|
// Safari & Chrome only currently
|
|
pip: (() => {
|
|
if (browser.isIPhone) {
|
|
return false;
|
|
}
|
|
|
|
// Safari
|
|
// https://developer.apple.com/documentation/webkitjs/adding_picture_in_picture_to_your_safari_media_controls
|
|
if (is.function(createElement('video').webkitSetPresentationMode)) {
|
|
return true;
|
|
}
|
|
|
|
// Chrome
|
|
// https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture
|
|
if (document.pictureInPictureEnabled && !createElement('video').disablePictureInPicture) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
})(),
|
|
|
|
// Airplay support
|
|
// Safari only currently
|
|
airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent),
|
|
|
|
// Inline playback support
|
|
// https://webkit.org/blog/6784/new-video-policies-for-ios/
|
|
playsinline: 'playsInline' in document.createElement('video'),
|
|
|
|
// Check for mime type support against a player instance
|
|
// Credits: http://diveintohtml5.info/everything.html
|
|
// Related: http://www.leanbackplayer.com/test/h5mt.html
|
|
mime(input) {
|
|
if (is.empty(input)) {
|
|
return false;
|
|
}
|
|
|
|
const [mediaType] = input.split('/');
|
|
let type = input;
|
|
|
|
// Verify we're using HTML5 and there's no media type mismatch
|
|
if (!this.isHTML5 || mediaType !== this.type) {
|
|
return false;
|
|
}
|
|
|
|
// Add codec if required
|
|
if (Object.keys(defaultCodecs).includes(type)) {
|
|
type += `; codecs="${defaultCodecs[input]}"`;
|
|
}
|
|
|
|
try {
|
|
return Boolean(type && this.media.canPlayType(type).replace(/no/, ''));
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
},
|
|
|
|
// Check for textTracks support
|
|
textTracks: 'textTracks' in document.createElement('video'),
|
|
|
|
// <input type="range"> Sliders
|
|
rangeInput: (() => {
|
|
const range = document.createElement('input');
|
|
range.type = 'range';
|
|
return range.type === 'range';
|
|
})(),
|
|
|
|
// Touch
|
|
// NOTE: Remember a device can be mouse + touch enabled so we check on first touch event
|
|
touch: 'ontouchstart' in document.documentElement,
|
|
|
|
// Detect transitions support
|
|
transitions: transitionEndEvent !== false,
|
|
|
|
// Reduced motion iOS & MacOS setting
|
|
// https://webkit.org/blog/7551/responsive-design-for-motion/
|
|
reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,
|
|
};
|
|
|
|
export default support;
|