Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat(hls): make a head request if hls subtitles have no extension (#4140
)

Closes #4135 
Closes #1959
  • Loading branch information
Álvaro Velad Galván committed Apr 20, 2022
1 parent 14355ee commit 19e12b5
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 3 deletions.
10 changes: 7 additions & 3 deletions lib/hls/hls_parser.js
Expand Up @@ -2252,11 +2252,10 @@ shaka.hls.HlsParser = class {

if (contentType == ContentType.TEXT) {
// The extension map didn't work.
if (!codecs || codecs == 'vtt' || codecs == 'wvtt') {
if (codecs == 'vtt' || codecs == 'wvtt') {
// If codecs is 'vtt', it's WebVTT.
// If there was no codecs string, assume HLS text streams are WebVTT.
return 'text/vtt';
} else {
} else if (codecs && codecs !== '') {
// Otherwise, assume MP4-embedded text, since text-based formats tend
// not to have a codecs string at all.
return 'application/mp4';
Expand All @@ -2281,6 +2280,11 @@ shaka.hls.HlsParser = class {
const contentMimeType = response.headers['content-type'];

if (!contentMimeType) {
if (contentType == ContentType.TEXT) {
// If there was no codecs string and no content-type, assume HLS text
// streams are WebVTT.
return 'text/vtt';
}
// If the HLS content is lacking in both MIME type metadata and
// segment file extensions, we fall back to assuming it's MP4.
const fallbackMimeType = map['mp4'];
Expand Down
63 changes: 63 additions & 0 deletions test/hls/hls_parser_unit.js
Expand Up @@ -1138,6 +1138,69 @@ describe('HlsParser', () => {
expect(actual).toEqual(manifest);
});

it('gets mime type of SUBTITLES from header request', async () => {
const master = [
'#EXTM3U\n',
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="eng",',
'URI="audio"\n',
'#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="sub1",LANGUAGE="eng",',
'URI="text"\n',
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1",SUBTITLES="sub1"\n',
'video\n',
].join('');

const media = [
'#EXTM3U\n',
'#EXT-X-PLAYLIST-TYPE:VOD\n',
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
'#EXTINF:5,\n',
'#EXT-X-BYTERANGE:121090@616\n',
'main.mp4',
].join('');

const textMedia = [
'#EXTM3U\n',
'#EXT-X-PLAYLIST-TYPE:VOD\n',
'#EXTINF:5,\n',
'#EXT-X-BYTERANGE:121090@616\n',
'main.subs',
].join('');

const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
manifest.anyTimeline();
manifest.addPartialVariant((variant) => {
variant.addPartialStream(ContentType.VIDEO, (stream) => {
stream.mime('video/mp4', 'avc1');
});
variant.addPartialStream(ContentType.AUDIO, (stream) => {
stream.mime('audio/mp4', 'mp4a');
});
});
manifest.addPartialTextStream((stream) => {
stream.language = 'en';
stream.kind = TextStreamKind.SUBTITLE;
stream.mime('application/mp4', '');
});
manifest.sequenceMode = true;
});

fakeNetEngine
.setResponseText('test:/master', master)
.setResponseText('test:/audio', media)
.setResponseText('test:/video', media)
.setResponseText('test:/text', textMedia)
.setResponseText('test:/main.subs', vttText)
.setHeaders('test:/main.subs', {
'content-type': 'application/mp4; foo=bar',
})
.setResponseValue('test:/init.mp4', initSegmentData)
.setResponseValue('test:/main.mp4', segmentData);

const actual = await parser.start('test:/master', playerInterface);
expect(actual).toEqual(manifest);
});

it('parses manifest with FORCED SUBTITLES', async () => {
const master = [
'#EXTM3U\n',
Expand Down

0 comments on commit 19e12b5

Please sign in to comment.