Skip to content
This repository has been archived by the owner on Jan 12, 2019. It is now read-only.

Commit

Permalink
Add support for description audio tracks in HLS (#1019)
Browse files Browse the repository at this point in the history
* Add support for description audio tracks (marked with CHARACTERISTICS of 'public.accessibility.describes-video')
* Update m3u8-parser to 2.1.0
* Add test for correctly setting alternative audio kinds
  • Loading branch information
OwenEdwards authored and mjneil committed Mar 9, 2017
1 parent ac257db commit bfa1fbf
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 5 deletions.
16 changes: 13 additions & 3 deletions docs/multiple-alternative-audio-tracks.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The mapping between `AudioTrack` and the parsed m3u8 file is fairly straight fo

As you can see m3u8's do not have a property for `AudioTrack.id`, which means that we let `video.js` randomly generate the id for `AudioTrack`s. This will have no real impact on any part of the system as we do not use the `id` anywhere.

The other property that does not have a mapping in the m3u8 is `AudioTrack.kind`. It was decided that we would set the `kind` to `main` when `default` is set to `true` and in all other cases we set it to `alternative`
The other property that does not have a mapping in the m3u8 is `AudioTrack.kind`. It was decided that we would set the `kind` to `main` when `default` is set to `true` and in other cases we set it to `alternative` unless the track has `characteristics` which include `public.accessibility.describes-video`, in which case we set it to `main-desc` (note that this `kind` indicates that the track is a mix of the main track and description, so it can be played *instead* of the main track; a track with kind `description` *only* has the description, not the main track).

Below is a basic example of a mapping
m3u8 layout
Expand All @@ -27,8 +27,13 @@ m3u8 layout
lang: 'eng'
},
'audio-track-2': {
default: true,
default: false,
lang: 'fr'
},
'audio-track-3': {
default: false,
lang: 'eng',
characteristics: 'public.accessibility.describes-video'
}
}]
}
Expand All @@ -48,6 +53,12 @@ Corresponding AudioTrackList when media-group-1 is used (before any tracks have
language: 'fr',
kind: 'alternative',
id: 'random'
}, {
label: 'audio-tracks-3',
enabled: false,
language: 'eng',
kind: 'main-desc',
id: 'random'
}]
```

Expand Down Expand Up @@ -83,4 +94,3 @@ Corresponding AudioTrackList when media-group-1 is used (before any tracks have
1. `MasterPlaylistController` maps the `label` to the `PlaylistLoader` containing the audio
1. `MasterPlaylistController` turns on that `PlaylistLoader` and the Corresponding `SegmentLoader` (master or audio only)
1. `MediaSource`/`mux.js` determine how to mux

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
"dependencies": {
"aes-decrypter": "1.0.3",
"global": "^4.3.0",
"m3u8-parser": "2.0.1",
"m3u8-parser": "2.1.0",
"mux.js": "4.1.1",
"url-toolkit": "1.0.9",
"video.js": "^5.17.0",
Expand Down
18 changes: 17 additions & 1 deletion src/master-playlist-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ export class MasterPlaylistController extends videojs.EventTarget {
let properties = mediaGroups.AUDIO[mediaGroup][label];
let track = new videojs.AudioTrack({
id: label,
kind: properties.default ? 'main' : 'alternative',
kind: this.audioTrackKind_(properties),
enabled: false,
language: properties.language,
label
Expand All @@ -574,6 +574,22 @@ export class MasterPlaylistController extends videojs.EventTarget {
})[0] || this.activeAudioGroup()[0]).enabled = true;
}

/**
* Convert the properties of an HLS track into an audioTrackKind.
*
* @private
*/
audioTrackKind_(properties) {
let kind = properties.default ? 'main' : 'alternative';

if (properties.characteristics &&
properties.characteristics.indexOf('public.accessibility.describes-video') >= 0) {
kind = 'main-desc';
}

return kind;
}

/**
* Call load on our SegmentLoaders
*/
Expand Down
34 changes: 34 additions & 0 deletions test/master-playlist-controller.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,40 @@ QUnit.test('sends decrypter messages to correct segment loader', function(assert
assert.deepEqual(mainHandleDecryptedCalls[0], { source: 'main' }, 'sent data');
});

QUnit.test('correctly sets alternate audio track kinds', function(assert) {
this.requests.length = 0;
this.player = createPlayer();
this.player.src({
src: 'manifest/alternate-audio-accessibility.m3u8',
type: 'application/vnd.apple.mpegurl'
});

// master
this.standardXHRResponse(this.requests.shift());
// media - required for loadedmetadata
this.standardXHRResponse(this.requests.shift());

const audioTracks = this.player.tech_.audioTracks();

assert.equal(audioTracks.length, 4, 'added 4 audio tracks');
assert.equal(audioTracks[0].id, 'English', 'contains english track');
assert.equal(audioTracks[0].kind, 'main', 'english track\'s kind is "main"');
assert.equal(audioTracks[1].id,
'English Descriptions',
'contains english descriptions track');
assert.equal(audioTracks[1].kind,
'main-desc',
'english descriptions track\'s kind is "main-desc"');
assert.equal(audioTracks[2].id, 'Français', 'contains french track');
assert.equal(audioTracks[2].kind,
'alternative',
'french track\'s kind is "alternative"');
assert.equal(audioTracks[3].id, 'Espanol', 'contains spanish track');
assert.equal(audioTracks[3].kind,
'alternative',
'spanish track\'s kind is "alternative"');
});

QUnit.module('Codec to MIME Type Conversion');

QUnit.test('recognizes muxed codec configurations', function(assert) {
Expand Down
10 changes: 10 additions & 0 deletions utils/manifest/alternate-audio-accessibility.m3u8
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#EXTM3U
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="eng",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="eng/prog_index.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="eng",NAME="English Descriptions",AUTOSELECT=YES,DEFAULT=NO,CHARACTERISTICS="public.accessibility.describes-video",URI="eng_desc/prog_index.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="fre",NAME="Français",AUTOSELECT=YES,DEFAULT=NO,URI="fre/prog_index.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",LANGUAGE="sp",NAME="Espanol",AUTOSELECT=YES,DEFAULT=NO,URI="sp/prog_index.m3u8"

#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=195023,CODECS="avc1.42e00a,mp4a.40.2",AUDIO="audio"
lo/prog_index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=591680,CODECS="avc1.42e01e,mp4a.40.2",AUDIO="audio"
hi/prog_index.m3u8

0 comments on commit bfa1fbf

Please sign in to comment.