Skip to content

Commit

Permalink
Add isMSESupported check
Browse files Browse the repository at this point in the history
Add named exports for and expose statically: `isSupported`, `isMSESupported`, and `getMediaSource`
  • Loading branch information
robwalch committed Dec 1, 2023
1 parent eff1601 commit df759ae
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 30 deletions.
2 changes: 2 additions & 0 deletions api-extractor/report/hls.js.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,8 @@ class Hls implements HlsEventEmitter {
// Warning: (ae-setter-with-docs) The doc comment for the property "firstLevel" must appear on the getter, not the setter.
set firstLevel(newLevel: number);
get forceStartLoad(): boolean;
static getMediaSource(): typeof MediaSource | undefined;
static isMSESupported(): boolean;
static isSupported(): boolean;
get latency(): number;
// (undocumented)
Expand Down
15 changes: 13 additions & 2 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,17 +190,28 @@ First include `https://cdn.jsdelivr.net/npm/hls.js@1` (or `/hls.js` for unminifi
<script src="//cdn.jsdelivr.net/npm/hls.js@1"></script>
```

Invoke the following static method: `Hls.isSupported()` to check whether your browser is supporting [MediaSource Extensions](http://w3c.github.io/media-source/).
Invoke the following static method: `Hls.isSupported()` to check whether your browser supports [MediaSource Extensions](http://w3c.github.io/media-source/) with any baseline codecs.

```html
<script src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>
<script>
if (Hls.isSupported()) {
console.log('hello hls.js!');
console.log('Hello HLS.js!');
}
</script>
```

If you want to test for MSE support without testing for baseline codecs, use `isMSESupported`:

```js
if (
Hls.isMSESupported() &&
Hls.getMediaSource().isTypeSupported('video/mp4;codecs="av01.0.01M.08"')
) {
console.log('Hello AV1 playback! AVC who?');
}
```

### Second step: instantiate Hls object and bind it to `<video>` element

Let's
Expand Down
2 changes: 2 additions & 0 deletions src/exports-named.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,5 @@ export {
ErrorActionFlags,
} from './controller/error-controller';
export { AttrList } from './utils/attr-list';
export { isSupported, isMSESupported } from './is-supported';
export { getMediaSource } from './utils/mediasource-helper';
17 changes: 16 additions & 1 deletion src/hls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import LevelController from './controller/level-controller';
import { FragmentTracker } from './controller/fragment-tracker';
import KeyLoader from './loader/key-loader';
import StreamController from './controller/stream-controller';
import { isSupported } from './is-supported';
import { isMSESupported, isSupported } from './is-supported';
import { getMediaSource } from './utils/mediasource-helper';
import { logger, enableLogs } from './utils/logger';
import { enableStreamingMode, hlsDefaultConfig, mergeConfig } from './config';
import { EventEmitter } from 'eventemitter3';
Expand Down Expand Up @@ -87,10 +88,24 @@ export default class Hls implements HlsEventEmitter {
/**
* Check if the required MediaSource Extensions are available.
*/
static isMSESupported(): boolean {
return isMSESupported();
}

/**
* Check if MediaSource Extensions are available and isTypeSupported checks pass for any baseline codecs.
*/
static isSupported(): boolean {
return isSupported();
}

/**
* Get the MediaSource global used for MSE playback (ManagedMediaSource, MediaSource, or WebKitMediaSource).
*/
static getMediaSource(): typeof MediaSource | undefined {
return getMediaSource();
}

static get Events(): typeof Events {
return Events;
}
Expand Down
45 changes: 18 additions & 27 deletions src/is-supported.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,50 @@
import { getMediaSource } from './utils/mediasource-helper';
import { getCodecCompatibleName, mimeTypeForCodec } from './utils/codecs';
import { mimeTypeForCodec } from './utils/codecs';
import type { ExtendedSourceBuffer } from './types/buffer';

function getSourceBuffer(): typeof self.SourceBuffer {
return self.SourceBuffer || (self as any).WebKitSourceBuffer;
}

export function isSupported(): boolean {
export function isMSESupported(): boolean {
const mediaSource = getMediaSource();
if (!mediaSource) {
return false;
}
const sourceBuffer = getSourceBuffer();

// if SourceBuffer is exposed ensure its API is valid
// Older browsers do not expose SourceBuffer globally so checking SourceBuffer.prototype is impossible
const sourceBufferValidAPI =
const sourceBuffer = getSourceBuffer();
return (
!sourceBuffer ||
(sourceBuffer.prototype &&
typeof sourceBuffer.prototype.appendBuffer === 'function' &&
typeof sourceBuffer.prototype.remove === 'function');
if (!sourceBufferValidAPI) {
typeof sourceBuffer.prototype.remove === 'function')
);
}

export function isSupported(): boolean {
if (!isMSESupported()) {
return false;
}

const mediaSource = getMediaSource();
return (
!!mediaSource &&
typeof mediaSource.isTypeSupported === 'function' &&
([
'avc1.42E01E,mp4a.40.2',
'hvc1.1.6.L123.B0',
'av01.0.01M.08',
'vp09.00.50.08',
].some((codecsForVideoContainer) =>
isMimeTypeSupported(
mediaSource,
mimeTypeForCodec(codecsForVideoContainer, 'video'),
),
typeof mediaSource?.isTypeSupported === 'function' &&
(['avc1.42E01E,mp4a.40.2', 'av01.0.01M.08', 'vp09.00.50.08'].some(
(codecsForVideoContainer) =>
mediaSource.isTypeSupported(
mimeTypeForCodec(codecsForVideoContainer, 'video'),
),
) ||
['mp4a.40.2', 'fLaC'].some((codecForAudioContainer) =>
isMimeTypeSupported(
mediaSource,
mediaSource.isTypeSupported(
mimeTypeForCodec(codecForAudioContainer, 'audio'),
),
))
);
}

function isMimeTypeSupported(
mediaSource: typeof MediaSource,
mimeType: string,
): boolean {
return mediaSource.isTypeSupported(mimeType);
}

export function changeTypeSupported(): boolean {
const sourceBuffer = getSourceBuffer();
return (
Expand Down

0 comments on commit df759ae

Please sign in to comment.