Skip to content
Open
Show file tree
Hide file tree
Changes from 11 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
51 changes: 50 additions & 1 deletion api-extractor/report/hls.js.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,23 @@ export type AudioSelectionOption = {
export class AudioStreamController extends BaseStreamController implements NetworkComponentAPI {
constructor(hls: Hls, fragmentTracker: FragmentTracker, keyLoader: KeyLoader);
// (undocumented)
protected checkFragmentChanged(type?: PlaylistLevelType): void;
// (undocumented)
doTick(): void;
// (undocumented)
protected getBufferOutput(): Bufferable | null;
// (undocumented)
protected getLoadPosition(): number;
// (undocumented)
protected _handleFragmentLoadComplete(fragLoadedData: FragLoadedData): void;
// (undocumented)
_handleFragmentLoadProgress(data: FragLoadedData): void;
// (undocumented)
protected loadFragment(frag: Fragment, track: Level, targetBufferTime: number): void;
get nextAudioTrack(): number;
// Warning: (ae-setter-with-docs) The doc comment for the property "nextAudioTrack" must appear on the getter, not the setter.
set nextAudioTrack(audioTrackId: number);
nextAudioTrackSwitch(): void;
// (undocumented)
protected onError(event: Events.ERROR, data: ErrorData): void;
// (undocumented)
Expand Down Expand Up @@ -235,6 +243,9 @@ export class AudioTrackController extends BasePlaylistController {
// (undocumented)
protected loadPlaylist(hlsUrlParameters?: HlsUrlParameters): void;
// (undocumented)
get nextAudioTrack(): number;
set nextAudioTrack(newId: number);
// (undocumented)
protected onAudioTrackLoaded(event: Events.AUDIO_TRACK_LOADED, data: AudioTrackLoadedData): void;
// (undocumented)
protected onError(event: Events.ERROR, data: ErrorData): void;
Expand Down Expand Up @@ -274,6 +285,8 @@ export interface AudioTrackSwitchedData extends MediaPlaylist {
//
// @public (undocumented)
export interface AudioTrackSwitchingData extends MediaPlaylist {
// (undocumented)
flushImmediate?: boolean;
}

// Warning: (ae-missing-release-tag) "AudioTrackUpdatedData" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
Expand Down Expand Up @@ -379,10 +392,14 @@ export class BaseSegment {
// @public (undocumented)
export class BaseStreamController extends TaskLoop implements NetworkComponentAPI {
constructor(hls: Hls, fragmentTracker: FragmentTracker, keyLoader: KeyLoader, logPrefix: string, playlistType: PlaylistLevelType);
protected abortCurrentFrag(): void;
// (undocumented)
protected afterBufferFlushed(media: Bufferable, bufferType: SourceBufferName, playlistType: PlaylistLevelType): void;
// (undocumented)
protected alignPlaylists(details: LevelDetails, previousDetails: LevelDetails | undefined, switchDetails: LevelDetails | undefined): number;
protected get backtrackFragment(): Fragment | null;
// Warning: (ae-setter-with-docs) The doc comment for the property "backtrackFragment" must appear on the getter, not the setter.
protected set backtrackFragment(_value: Fragment | null);
// (undocumented)
protected bitrateTest: boolean;
// (undocumented)
Expand All @@ -391,14 +408,24 @@ export class BaseStreamController extends TaskLoop implements NetworkComponentAP
protected buffering: boolean;
// (undocumented)
get bufferingEnabled(): boolean;
protected calculateOptimalSwitchPoint(nextLevel: Level, bufferInfo: BufferInfo, type: PlaylistLevelType): {
fetchdelay: number;
okToFlushForwardBuffer: boolean;
};
// (undocumented)
protected checkFragmentChanged(type?: PlaylistLevelType): void;
// (undocumented)
protected checkLiveUpdate(details: LevelDetails): void;
// (undocumented)
protected checkRetryDate(): void;
protected cleanupBackBuffer(type: PlaylistLevelType): void;
// (undocumented)
protected clearTrackerIfNeeded(frag: Fragment): void;
// (undocumented)
protected config: HlsConfig;
protected get couldBacktrack(): boolean;
// Warning: (ae-setter-with-docs) The doc comment for the property "couldBacktrack" must appear on the getter, not the setter.
protected set couldBacktrack(_value: boolean);
// (undocumented)
protected decrypter: Decrypter;
// (undocumented)
Expand All @@ -411,6 +438,7 @@ export class BaseStreamController extends TaskLoop implements NetworkComponentAP
protected flushBufferGap(frag: Fragment): void;
// (undocumented)
protected flushMainBuffer(startOffset: number, endOffset: number, type?: SourceBufferName | null): void;
protected followingBufferedFrag(frag: Fragment | null, type?: PlaylistLevelType): Fragment | null;
// (undocumented)
protected fragBufferedComplete(frag: Fragment, part: Part | null): void;
// (undocumented)
Expand All @@ -422,9 +450,14 @@ export class BaseStreamController extends TaskLoop implements NetworkComponentAP
// (undocumented)
protected fragmentTracker: FragmentTracker;
// (undocumented)
protected fragPlaying: Fragment | null;
// (undocumented)
protected fragPrevious: MediaFragment | null;
// (undocumented)
protected getAppendedFrag(position: number, playlistType?: PlaylistLevelType): Fragment | null;
protected getBufferedFrag(position: number, type?: PlaylistLevelType): Fragment | null;
// (undocumented)
protected getBufferOutput(): Bufferable | null;
// (undocumented)
protected getCurrentContext(chunkMeta: ChunkMetadata): {
frag: MediaFragment;
Expand Down Expand Up @@ -486,6 +519,8 @@ export class BaseStreamController extends TaskLoop implements NetworkComponentAP
// (undocumented)
protected mediaBuffer: Bufferable | null;
// (undocumented)
nextLevelSwitch(type: PlaylistLevelType): void;
// (undocumented)
protected nextLoadPosition: number;
// (undocumented)
protected onError(event: Events.ERROR, data: ErrorData): void;
Expand Down Expand Up @@ -539,6 +574,7 @@ export class BaseStreamController extends TaskLoop implements NetworkComponentAP
resumeBuffering(): void;
// (undocumented)
protected retryDate: number;
protected scheduleTrackSwitch(bufferInfo: BufferInfo, fetchdelay: number, okToFlushForwardBuffer: boolean, type: PlaylistLevelType): void;
// (undocumented)
protected setStartPosition(details: LevelDetails, sliding: number): void;
// (undocumented)
Expand Down Expand Up @@ -2116,6 +2152,9 @@ class Hls implements HlsEventEmitter {
// (undocumented)
static get MetadataSchema(): typeof MetadataSchema;
get minAutoLevel(): number;
get nextAudioTrack(): number;
// Warning: (ae-setter-with-docs) The doc comment for the property "nextAudioTrack" must appear on the getter, not the setter.
set nextAudioTrack(audioTrackId: number);
get nextAutoLevel(): number;
// Warning: (ae-setter-with-docs) The doc comment for the property "nextAutoLevel" must appear on the getter, not the setter.
set nextAutoLevel(nextLevel: number);
Expand Down Expand Up @@ -4539,6 +4578,14 @@ export interface SteeringManifestLoadedData {
export class StreamController extends BaseStreamController implements NetworkComponentAPI {
constructor(hls: Hls, fragmentTracker: FragmentTracker, keyLoader: KeyLoader);
// (undocumented)
protected abortCurrentFrag(): void;
protected get backtrackFragment(): Fragment | null;
// Warning: (ae-setter-with-docs) The doc comment for the property "backtrackFragment" must appear on the getter, not the setter.
protected set backtrackFragment(value: Fragment | null);
protected get couldBacktrack(): boolean;
// Warning: (ae-setter-with-docs) The doc comment for the property "couldBacktrack" must appear on the getter, not the setter.
protected set couldBacktrack(value: boolean);
// (undocumented)
get currentFrag(): Fragment | null;
// (undocumented)
get currentLevel(): number;
Expand All @@ -4550,6 +4597,7 @@ export class StreamController extends BaseStreamController implements NetworkCom
protected flushMainBuffer(startOffset: number, endOffset: number): void;
// (undocumented)
get forceStartLoad(): boolean;
protected getBufferOutput(): Bufferable | null;
// (undocumented)
getMainFwdBufferInfo(): BufferInfo | null;
// (undocumented)
Expand All @@ -4563,7 +4611,7 @@ export class StreamController extends BaseStreamController implements NetworkCom
// (undocumented)
get maxBufferLength(): number;
// (undocumented)
get nextBufferedFrag(): MediaFragment | null;
get nextBufferedFrag(): Fragment | null;
// (undocumented)
get nextLevel(): number;
nextLevelSwitch(): void;
Expand Down Expand Up @@ -4609,6 +4657,7 @@ export type StreamControllerConfig = {
testBandwidth: boolean;
liveSyncMode?: 'edge' | 'buffered';
startOnSegmentBoundary: boolean;
nextAudioTrackBufferFlushForwardOffset: number;
};

// Warning: (ae-missing-release-tag) "SubtitleFragProcessedData" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
Expand Down
6 changes: 6 additions & 0 deletions demo/index-light.html
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,12 @@ <h3>
<td>Current audio-track:</td>
<td><div id="audioTrackControl" style="display: inline"></div></td>
</tr>
<tr>
<td>Next audio-track:</td>
<td>
<div id="nextAudioTrackControl" style="display: inline"></div>
</td>
</tr>
<tr>
<td>Language / Name:</td>
<td>
Expand Down
6 changes: 6 additions & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,12 @@ <h3>
<td>Current audio-track:</td>
<td><div id="audioTrackControl" style="display: inline"></div></td>
</tr>
<tr>
<td>Next audio-track:</td>
<td>
<div id="nextAudioTrackControl" style="display: inline"></div>
</td>
</tr>
<tr>
<td>Language / Name:</td>
<td>
Expand Down
23 changes: 23 additions & 0 deletions demo/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -1393,9 +1393,12 @@ function updateAudioTrackInfo() {
const buttonEnabled = 'btn-primary" ';
const buttonDisabled = 'btn-success" ';
let html1 = '';
let html2 = '';
const audioTrackId = hls.audioTrack;
const nextAudioTrackId = hls.nextAudioTrack;
const len = hls.audioTracks.length;
const track = hls.audioTracks[audioTrackId];
const nextTrack = hls.audioTracks[nextAudioTrackId];

for (let i = 0; i < len; i++) {
html1 += buttonTemplate;
Expand All @@ -1413,10 +1416,30 @@ function updateAudioTrackInfo() {
'</button>';
}

for (let i = 0; i < len; i++) {
html2 += buttonTemplate;
if (nextAudioTrackId === i) {
html2 += buttonEnabled;
} else {
html2 += buttonDisabled;
}

html2 +=
'onclick="hls.nextAudioTrack=' +
i +
'">' +
hls.audioTracks[i].name +
'</button>';
}

$('#audioTrackLabel').text(
track ? track.lang || track.name : 'None selected'
);
$('#audioTrackControl').html(html1);
$('#audioTrackLabel').text(
nextTrack ? nextTrack.lang || nextTrack.name : 'None selected'
);
$('#nextAudioTrackControl').html(html2);
}

function codecs2label(levelCodecs) {
Expand Down
7 changes: 6 additions & 1 deletion docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ See [API Reference](https://hlsjs-dev.video-dev.org/api-docs/) for a complete li
- [`hls.allAudioTracks`](#hlsallaudiotracks)
- [`hls.audioTracks`](#hlsaudiotracks)
- [`hls.audioTrack`](#hlsaudiotrack)
- [`hls.nextAudioTrack`](#hlsnextaudiotrack)
- [Subtitle Tracks Control API](#subtitle-tracks-control-api)
- [`hls.setSubtitleOption(subtitleOption)`](#hlssetsubtitleoptionsubtitleoption)
- [`hls.allSubtitleTracks`](#hlsallsubtitletracks)
Expand Down Expand Up @@ -2046,6 +2047,10 @@ get : array of supported audio tracks in the active audio group ID

get/set : index of selected audio track in `hls.audioTracks`

### `hls.nextAudioTrack`

get/set : index of the next audio track that will be selected, allowing for seamless audio track switching

## Subtitle Tracks Control API

### `hls.setSubtitleOption(subtitleOption)`
Expand Down Expand Up @@ -2382,7 +2387,7 @@ Full list of Events is available below:
- `Hls.Events.AUDIO_TRACKS_UPDATED` - fired to notify that audio track lists has been updated
- data: { audioTracks : audioTracks }
- `Hls.Events.AUDIO_TRACK_SWITCHING` - fired when an audio track switching is requested
- data: { id : audio track id, type : playlist type ('AUDIO' | 'main'), url : audio track URL }
- data: { id : audio track id, type : playlist type ('AUDIO' | 'main'), url : audio track URL, flushImmediate: boolean indicating whether audio buffer should be flushed immediately when switching }
- `Hls.Events.AUDIO_TRACK_SWITCHED` - fired when an audio track switch actually occurs
- data: { id : audio track id }
- `Hls.Events.AUDIO_TRACK_LOADING` - fired when an audio track loading starts
Expand Down
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ export type StreamControllerConfig = {
testBandwidth: boolean;
liveSyncMode?: 'edge' | 'buffered';
startOnSegmentBoundary: boolean;
nextAudioTrackBufferFlushForwardOffset: number;
};

export type GapControllerConfig = {
Expand Down Expand Up @@ -376,6 +377,7 @@ export const hlsDefaultConfig: HlsConfig = {
backBufferLength: Infinity, // used by buffer-controller
frontBufferFlushThreshold: Infinity,
startOnSegmentBoundary: false, // used by stream-controller
nextAudioTrackBufferFlushForwardOffset: 0.25, // used by stream-controller
maxBufferSize: 60 * 1000 * 1000, // used by stream-controller
maxFragLookUpTolerance: 0.25, // used by stream-controller
maxBufferHole: 0.1, // used by stream-controller and gap-controller
Expand Down
Loading
Loading