forked from video-dev/hls.js
-
Notifications
You must be signed in to change notification settings - Fork 7
/
audio-track-controller.js
157 lines (140 loc) · 4.5 KB
/
audio-track-controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
* audio track controller
*/
import Event from '../events';
import EventHandler from '../event-handler';
import { logger } from '../utils/logger';
import { ErrorTypes } from '../errors';
class AudioTrackController extends EventHandler {
constructor (hls) {
super(hls, Event.MANIFEST_LOADING,
Event.MANIFEST_PARSED,
Event.AUDIO_TRACK_LOADED,
Event.ERROR);
this.ticks = 0;
this.ontick = this.tick.bind(this);
}
destroy () {
this.cleanTimer();
EventHandler.prototype.destroy.call(this);
}
cleanTimer () {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
}
tick () {
this.ticks++;
if (this.ticks === 1) {
this.doTick();
if (this.ticks > 1) {
setTimeout(this.tick, 1);
}
this.ticks = 0;
}
}
doTick () {
this.updateTrack(this.trackId);
}
onError (data) {
if (data.fatal && data.type === ErrorTypes.NETWORK_ERROR) {
this.cleanTimer();
}
}
onManifestLoading () {
// reset audio tracks on manifest loading
this.tracks = [];
this.trackId = -1;
}
onManifestParsed (data) {
let tracks = data.audioTracks || [];
let defaultFound = false;
this.tracks = tracks;
this.hls.trigger(Event.AUDIO_TRACKS_UPDATED, { audioTracks: tracks });
// loop through available audio tracks and autoselect default if needed
let id = 0;
tracks.forEach(track => {
if (track.default && !defaultFound) {
this.audioTrack = id;
defaultFound = true;
return;
}
id++;
});
if (defaultFound === false && tracks.length) {
logger.log('no default audio track defined, use first audio track as default');
this.audioTrack = 0;
}
}
onAudioTrackLoaded (data) {
if (data.id < this.tracks.length) {
logger.log(`audioTrack ${data.id} loaded`);
this.tracks[data.id].details = data.details;
// check if current playlist is a live playlist
if (data.details.live && !this.timer) {
// if live playlist we will have to reload it periodically
// set reload period to playlist target duration
this.timer = setInterval(this.ontick, 1000 * data.details.targetduration);
}
if (!data.details.live && this.timer) {
// playlist is not live and timer is armed : stopping it
this.cleanTimer();
}
}
}
/** get alternate audio tracks list from playlist **/
get audioTracks () {
return this.tracks;
}
/** get index of the selected audio track (index in audio track lists) **/
get audioTrack () {
return this.trackId;
}
/** select an audio track, based on its index in audio track lists**/
set audioTrack (audioTrackId) {
if (this.trackId !== audioTrackId || this.tracks[audioTrackId].details === undefined) {
this.setAudioTrackInternal(audioTrackId);
}
}
setAudioTrackInternal (newId) {
// check if level idx is valid
if (newId >= 0 && newId < this.tracks.length) {
// stopping live reloading timer if any
this.cleanTimer();
this.trackId = newId;
logger.log(`switching to audioTrack ${newId}`);
let audioTrack = this.tracks[newId],
hls = this.hls,
type = audioTrack.type,
url = audioTrack.url,
eventObj = { id: newId, type: type, url: url };
hls.trigger(Event.AUDIO_TRACK_SWITCHING, eventObj);
// check if we need to load playlist for this audio Track
let details = audioTrack.details;
if (url && (details === undefined || details.live === true)) {
// track not retrieved yet, or live playlist we need to (re)load it
logger.log(`(re)loading playlist for audioTrack ${newId}`);
hls.trigger(Event.AUDIO_TRACK_LOADING, { url: url, id: newId });
}
}
}
updateTrack (newId) {
// check if level idx is valid
if (newId >= 0 && newId < this.tracks.length) {
// stopping live reloading timer if any
this.cleanTimer();
this.trackId = newId;
logger.log(`updating audioTrack ${newId}`);
let audioTrack = this.tracks[newId], url = audioTrack.url;
// check if we need to load playlist for this audio Track
let details = audioTrack.details;
if (url && (details === undefined || details.live === true)) {
// track not retrieved yet, or live playlist we need to (re)load it
logger.log(`(re)loading playlist for audioTrack ${newId}`);
this.hls.trigger(Event.AUDIO_TRACK_LOADING, { url: url, id: newId });
}
}
}
}
export default AudioTrackController;