Skip to content

Commit

Permalink
fix(player): include source type attr for html providers
Browse files Browse the repository at this point in the history
closes #1166
  • Loading branch information
mihar-22 committed Feb 17, 2024
1 parent 2376735 commit 9ab499e
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 25 deletions.
22 changes: 6 additions & 16 deletions packages/vidstack/src/providers/hls/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,27 +110,17 @@ export class HLSProvider extends VideoProvider implements MediaProviderAdapter {
}

override async loadSource(src: MediaSrc, preload?: HTMLMediaElement['preload']) {
if (!isString(src.src)) return;
if (!isString(src.src)) {
this._removeSource();
return;
}

this._media.preload = preload || '';
this._appendSource(src as MediaSrc<string>);
this._appendSource(src as MediaSrc<string>, 'application/x-mpegurl');
this._controller._loadSource(src);
this._currentSrc = src as MediaSrc<string>;
}

/**
* Append source so it works when requesting AirPlay since hls.js will remove it.
*/
private _appendSource(src: MediaSrc<string>) {
const prevSource = this.video.querySelector('source[data-vds]'),
source = prevSource ?? document.createElement('source');

setAttribute(source, 'src', src.src);
setAttribute(source, 'type', 'application/x-mpegurl');
setAttribute(source, 'data-vds', '');

if (!prevSource) this.video.append(source);
}

/**
* The given callback is invoked when a new `hls.js` instance is created and right before it's
* attached to media.
Expand Down
6 changes: 3 additions & 3 deletions packages/vidstack/src/providers/html/html–media-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { MediaErrorCode } from '../../core/api/types';
import { RAFLoop } from '../../foundation/observers/raf-loop';
import { isHLSSrc } from '../../utils/mime';
import { getNumberOfDecimalPlaces } from '../../utils/number';
import { IS_SAFARI } from '../../utils/support';
import { IS_IOS, IS_SAFARI } from '../../utils/support';
import type { HTMLMediaProvider } from './provider';

export class HTMLMediaEvents {
Expand Down Expand Up @@ -171,8 +171,8 @@ export class HTMLMediaEvents {

this._notify('loaded-metadata', undefined, event);

// Native HLS does not reliably fire `canplay` event.
if (IS_SAFARI && isHLSSrc(this._ctx.$state.source())) {
// iOS Safari and Native HLS do not reliably fire `canplay` event.
if (IS_IOS || (IS_SAFARI && isHLSSrc(this._ctx.$state.source()))) {
this._ctx.delegate._ready(this._getCanPlayDetail(), event);
}
}
Expand Down
41 changes: 35 additions & 6 deletions packages/vidstack/src/providers/html/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ export class HTMLMediaProvider implements MediaProviderAdapter {
if ('audioTracks' in this.media) new NativeAudioTracks(this, this._ctx);

onDispose(() => {
// Dispose of media.
this._media.setAttribute('src', '');
// We need to remove all media sources incase another provider uses the same media element.
this._media.srcObject = null;
this._media.removeAttribute('src');
for (const source of this._media.querySelectorAll('source')) source.remove();
this._media.load();
});
}
Expand Down Expand Up @@ -80,12 +82,21 @@ export class HTMLMediaProvider implements MediaProviderAdapter {
this._media.preload = preload || '';

if (isMediaStream(src)) {
this._removeSource();
this._media.srcObject = src;
} else {
this._media.srcObject = null;
this._media.src = isString(src)
? this._appendMediaFragment(src)
: window.URL.createObjectURL(src as MediaSource | Blob);
if (isString(src)) {
if (type !== '?') {
this._appendSource({ src, type });
} else {
this._removeSource();
this._media.src = this._appendMediaFragment(src);
}
} else {
this._removeSource();
this._media.src = window.URL.createObjectURL(src as MediaSource | Blob);
}
}

this._media.load();
Expand All @@ -96,7 +107,25 @@ export class HTMLMediaProvider implements MediaProviderAdapter {
};
}

private _appendMediaFragment(src: string) {
/**
* Append source so it works when requesting AirPlay since hls.js will remove it.
*/
protected _appendSource(src: MediaSrc<string>, defaultType?: string) {
const prevSource = this._media.querySelector('source[data-vds]'),
source = prevSource ?? document.createElement('source');

setAttribute(source, 'src', this._appendMediaFragment(src.src));
setAttribute(source, 'type', src.type !== '?' ? src.type : defaultType);
setAttribute(source, 'data-vds', '');

if (!prevSource) this._media.append(source);
}

protected _removeSource() {
this._media.querySelector('source[data-vds]')?.remove();
}

protected _appendMediaFragment(src: string) {
const { clipStartTime, clipEndTime } = this._ctx.$state,
startTime = clipStartTime(),
endTime = clipEndTime();
Expand Down

0 comments on commit 9ab499e

Please sign in to comment.