Skip to content

Commit cd75be1

Browse files
feat: add support for a frame-rate attribute (#159)
* feat: add support for a frame-rate attribute * docs: fix typo in comment
1 parent 269e406 commit cd75be1

19 files changed

+129
-68
lines changed

src/parseAttributes.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { parseDivisionValue } from './utils/string';
12
import { from } from './utils/list';
23
import { parseDuration, parseDate } from './utils/time';
34

@@ -131,6 +132,18 @@ export const parsers = {
131132
return parseInt(value, 10);
132133
},
133134

135+
/**
136+
* Specifies the frame rate of the representation
137+
*
138+
* @param {string} value
139+
* value of attribute as a string
140+
* @return {number}
141+
* The parsed frame rate
142+
*/
143+
frameRate(value) {
144+
return parseDivisionValue(value);
145+
},
146+
134147
/**
135148
* Specifies the number of the first Media Segment in this Representation in the Period
136149
*

src/toM3u8.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,10 @@ export const formatVideoPlaylist = ({
296296
segments
297297
};
298298

299+
if (attributes.frameRate) {
300+
playlist.attributes['FRAME-RATE'] = attributes.frameRate;
301+
}
302+
299303
if (attributes.contentProtection) {
300304
playlist.contentProtection = attributes.contentProtection;
301305
}

src/utils/string.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Converts the provided string that may contain a division operation to a number.
3+
*
4+
* @param {string} value - the provided string value
5+
*
6+
* @return {number} the parsed string value
7+
*/
8+
export const parseDivisionValue = (value) => {
9+
return parseFloat(value.split('/').reduce((prev, current) => prev / current));
10+
};

test/manifests/608-captions.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export const parsedManifest = {
3636
'AUDIO': 'audio',
3737
'BANDWIDTH': 449000,
3838
'CODECS': 'avc1.420015',
39+
'FRAME-RATE': 23.976,
3940
'NAME': '482',
4041
'PROGRAM-ID': 1,
4142
'RESOLUTION': {

test/manifests/708-captions.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const parsedManifest = {
3737
'AUDIO': 'audio',
3838
'BANDWIDTH': 449000,
3939
'CODECS': 'avc1.420015',
40+
'FRAME-RATE': 23.976,
4041
'NAME': '482',
4142
'PROGRAM-ID': 1,
4243
'RESOLUTION': {

test/manifests/location.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export const parsedManifest = {
2222
'AUDIO': 'audio',
2323
'BANDWIDTH': 449000,
2424
'CODECS': 'avc1.420015',
25+
'FRAME-RATE': 23.976,
2526
'NAME': '482',
2627
'PROGRAM-ID': 1,
2728
'RESOLUTION': {

test/manifests/locations.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export const parsedManifest = {
2323
'AUDIO': 'audio',
2424
'BANDWIDTH': 449000,
2525
'CODECS': 'avc1.420015',
26+
'FRAME-RATE': 23.976,
2627
'NAME': '482',
2728
'PROGRAM-ID': 1,
2829
'RESOLUTION': {

test/manifests/maat_vtt_segmentTemplate.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ export const parsedManifest = {
406406
'NAME': '482',
407407
'AUDIO': 'audio',
408408
'SUBTITLES': 'subs',
409+
'FRAME-RATE': 23.976,
409410
'RESOLUTION': {
410411
width: 482,
411412
height: 270
@@ -487,6 +488,7 @@ export const parsedManifest = {
487488
'NAME': '720',
488489
'AUDIO': 'audio',
489490
'SUBTITLES': 'subs',
491+
'FRAME-RATE': 23.976,
490492
'RESOLUTION': {
491493
width: 720,
492494
height: 404

test/manifests/multiperiod-dynamic.js

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -613,16 +613,17 @@ export const parsedManifest = {
613613
playlists: [
614614
{
615615
attributes: {
616-
'NAME': 'default_video2000_0_1280x720',
617616
'AUDIO': 'audio',
618-
'SUBTITLES': 'subs',
617+
'BANDWIDTH': 2008000,
618+
'CODECS': 'avc1.4d001f',
619+
'FRAME-RATE': 29.97,
620+
'NAME': 'default_video2000_0_1280x720',
621+
'PROGRAM-ID': 1,
619622
'RESOLUTION': {
620-
width: 1280,
621-
height: 720
623+
height: 720,
624+
width: 1280
622625
},
623-
'CODECS': 'avc1.4d001f',
624-
'BANDWIDTH': 2008000,
625-
'PROGRAM-ID': 1
626+
'SUBTITLES': 'subs'
626627
},
627628
uri: '',
628629
endList: false,
@@ -905,16 +906,17 @@ export const parsedManifest = {
905906
},
906907
{
907908
attributes: {
908-
'NAME': 'default_video1200_1_960x540',
909909
'AUDIO': 'audio',
910-
'SUBTITLES': 'subs',
910+
'BANDWIDTH': 1195000,
911+
'CODECS': 'avc1.4d001f',
912+
'FRAME-RATE': 29.97,
913+
'NAME': 'default_video1200_1_960x540',
914+
'PROGRAM-ID': 1,
911915
'RESOLUTION': {
912-
width: 960,
913-
height: 540
916+
height: 540,
917+
width: 960
914918
},
915-
'CODECS': 'avc1.4d001f',
916-
'BANDWIDTH': 1195000,
917-
'PROGRAM-ID': 1
919+
'SUBTITLES': 'subs'
918920
},
919921
uri: '',
920922
endList: false,
@@ -1197,16 +1199,17 @@ export const parsedManifest = {
11971199
},
11981200
{
11991201
attributes: {
1200-
'NAME': 'default_video900_1_640x360',
12011202
'AUDIO': 'audio',
1202-
'SUBTITLES': 'subs',
1203+
'BANDWIDTH': 884000,
1204+
'CODECS': 'avc1.4d001e',
1205+
'FRAME-RATE': 29.97,
1206+
'NAME': 'default_video900_1_640x360',
1207+
'PROGRAM-ID': 1,
12031208
'RESOLUTION': {
1204-
width: 640,
1205-
height: 360
1209+
height: 360,
1210+
width: 640
12061211
},
1207-
'CODECS': 'avc1.4d001e',
1208-
'BANDWIDTH': 884000,
1209-
'PROGRAM-ID': 1
1212+
'SUBTITLES': 'subs'
12101213
},
12111214
uri: '',
12121215
endList: false,

test/manifests/multiperiod-segment-list.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const parsedManifest = {
1515
'AUDIO': 'audio',
1616
'BANDWIDTH': 449000,
1717
'CODECS': 'avc1.420015',
18+
'FRAME-RATE': 23.976,
1819
'NAME': '482',
1920
'PROGRAM-ID': 1,
2021
'RESOLUTION': {

test/manifests/multiperiod-segment-template.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,16 +130,17 @@ export const parsedManifest = {
130130
playlists: [
131131
{
132132
attributes: {
133-
'NAME': '1',
134133
'AUDIO': 'audio',
135-
'SUBTITLES': 'subs',
134+
'BANDWIDTH': 100000,
135+
'CODECS': 'avc1.4d001f',
136+
'FRAME-RATE': 24,
137+
'NAME': '1',
138+
'PROGRAM-ID': 1,
136139
'RESOLUTION': {
137-
width: 480,
138-
height: 200
140+
height: 200,
141+
width: 480
139142
},
140-
'CODECS': 'avc1.4d001f',
141-
'BANDWIDTH': 100000,
142-
'PROGRAM-ID': 1
143+
'SUBTITLES': 'subs'
143144
},
144145
uri: '',
145146
endList: true,

test/manifests/multiperiod-startnumber-removed-periods.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export const parsedManifest = {
9191
'AUDIO': 'audio',
9292
'BANDWIDTH': 2942295,
9393
'CODECS': 'avc1.4d001f',
94+
'FRAME-RATE': 30,
9495
'NAME': 'D',
9596
'PROGRAM-ID': 1,
9697
'RESOLUTION': {
@@ -155,6 +156,7 @@ export const parsedManifest = {
155156
'AUDIO': 'audio',
156157
'BANDWIDTH': 4267536,
157158
'CODECS': 'avc1.640020',
159+
'FRAME-RATE': 60,
158160
'NAME': 'E',
159161
'PROGRAM-ID': 1,
160162
'RESOLUTION': {
@@ -219,6 +221,7 @@ export const parsedManifest = {
219221
'AUDIO': 'audio',
220222
'BANDWIDTH': 5256859,
221223
'CODECS': 'avc1.640020',
224+
'FRAME-RATE': 60,
222225
'NAME': 'F',
223226
'PROGRAM-ID': 1,
224227
'RESOLUTION': {
@@ -283,6 +286,7 @@ export const parsedManifest = {
283286
'AUDIO': 'audio',
284287
'BANDWIDTH': 240781,
285288
'CODECS': 'avc1.4d000d',
289+
'FRAME-RATE': 30,
286290
'NAME': 'A',
287291
'PROGRAM-ID': 1,
288292
'RESOLUTION': {
@@ -347,6 +351,7 @@ export const parsedManifest = {
347351
'AUDIO': 'audio',
348352
'BANDWIDTH': 494354,
349353
'CODECS': 'avc1.4d001e',
354+
'FRAME-RATE': 30,
350355
'NAME': 'B',
351356
'PROGRAM-ID': 1,
352357
'RESOLUTION': {
@@ -411,6 +416,7 @@ export const parsedManifest = {
411416
'AUDIO': 'audio',
412417
'BANDWIDTH': 1277155,
413418
'CODECS': 'avc1.4d001f',
419+
'FRAME-RATE': 30,
414420
'NAME': 'C',
415421
'PROGRAM-ID': 1,
416422
'RESOLUTION': {

test/manifests/multiperiod-startnumber.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ export const parsedManifest = {
180180
'AUDIO': 'audio',
181181
'BANDWIDTH': 2942295,
182182
'CODECS': 'avc1.4d001f',
183+
'FRAME-RATE': 30,
183184
'NAME': 'D',
184185
'PROGRAM-ID': 1,
185186
'RESOLUTION': {
@@ -333,6 +334,7 @@ export const parsedManifest = {
333334
'AUDIO': 'audio',
334335
'BANDWIDTH': 4267536,
335336
'CODECS': 'avc1.640020',
337+
'FRAME-RATE': 60,
336338
'NAME': 'E',
337339
'PROGRAM-ID': 1,
338340
'RESOLUTION': {
@@ -486,6 +488,7 @@ export const parsedManifest = {
486488
'AUDIO': 'audio',
487489
'BANDWIDTH': 5256859,
488490
'CODECS': 'avc1.640020',
491+
'FRAME-RATE': 60,
489492
'NAME': 'F',
490493
'PROGRAM-ID': 1,
491494
'RESOLUTION': {
@@ -639,6 +642,7 @@ export const parsedManifest = {
639642
'AUDIO': 'audio',
640643
'BANDWIDTH': 240781,
641644
'CODECS': 'avc1.4d000d',
645+
'FRAME-RATE': 30,
642646
'NAME': 'A',
643647
'PROGRAM-ID': 1,
644648
'RESOLUTION': {
@@ -792,6 +796,7 @@ export const parsedManifest = {
792796
'AUDIO': 'audio',
793797
'BANDWIDTH': 494354,
794798
'CODECS': 'avc1.4d001e',
799+
'FRAME-RATE': 30,
795800
'NAME': 'B',
796801
'PROGRAM-ID': 1,
797802
'RESOLUTION': {
@@ -945,6 +950,7 @@ export const parsedManifest = {
945950
'AUDIO': 'audio',
946951
'BANDWIDTH': 1277155,
947952
'CODECS': 'avc1.4d001e',
953+
'FRAME-RATE': 30,
948954
'NAME': 'C',
949955
'PROGRAM-ID': 1,
950956
'RESOLUTION': {

test/manifests/multiperiod.js

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -613,16 +613,17 @@ export const parsedManifest = {
613613
playlists: [
614614
{
615615
attributes: {
616-
'NAME': 'default_video2000_0_1280x720',
617616
'AUDIO': 'audio',
618-
'SUBTITLES': 'subs',
617+
'BANDWIDTH': 2008000,
618+
'CODECS': 'avc1.4d001f',
619+
'FRAME-RATE': 29.97,
620+
'NAME': 'default_video2000_0_1280x720',
621+
'PROGRAM-ID': 1,
619622
'RESOLUTION': {
620-
width: 1280,
621-
height: 720
623+
height: 720,
624+
width: 1280
622625
},
623-
'CODECS': 'avc1.4d001f',
624-
'BANDWIDTH': 2008000,
625-
'PROGRAM-ID': 1
626+
'SUBTITLES': 'subs'
626627
},
627628
uri: '',
628629
endList: true,
@@ -905,16 +906,17 @@ export const parsedManifest = {
905906
},
906907
{
907908
attributes: {
908-
'NAME': 'default_video1200_1_960x540',
909909
'AUDIO': 'audio',
910-
'SUBTITLES': 'subs',
910+
'BANDWIDTH': 1195000,
911+
'CODECS': 'avc1.4d001f',
912+
'FRAME-RATE': 29.97,
913+
'NAME': 'default_video1200_1_960x540',
914+
'PROGRAM-ID': 1,
911915
'RESOLUTION': {
912-
width: 960,
913-
height: 540
916+
height: 540,
917+
width: 960
914918
},
915-
'CODECS': 'avc1.4d001f',
916-
'BANDWIDTH': 1195000,
917-
'PROGRAM-ID': 1
919+
'SUBTITLES': 'subs'
918920
},
919921
uri: '',
920922
endList: true,
@@ -1197,16 +1199,17 @@ export const parsedManifest = {
11971199
},
11981200
{
11991201
attributes: {
1200-
'NAME': 'default_video900_1_640x360',
12011202
'AUDIO': 'audio',
1202-
'SUBTITLES': 'subs',
1203+
'BANDWIDTH': 884000,
1204+
'CODECS': 'avc1.4d001e',
1205+
'FRAME-RATE': 29.97,
1206+
'NAME': 'default_video900_1_640x360',
1207+
'PROGRAM-ID': 1,
12031208
'RESOLUTION': {
1204-
width: 640,
1205-
height: 360
1209+
height: 360,
1210+
width: 640
12061211
},
1207-
'CODECS': 'avc1.4d001e',
1208-
'BANDWIDTH': 884000,
1209-
'PROGRAM-ID': 1
1212+
'SUBTITLES': 'subs'
12101213
},
12111214
uri: '',
12121215
endList: true,

test/manifests/segmentBase.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const parsedManifest = {
1515
'AUDIO': 'audio',
1616
'BANDWIDTH': 449000,
1717
'CODECS': 'avc1.420015',
18+
'FRAME-RATE': 23.976,
1819
'NAME': '482',
1920
'PROGRAM-ID': 1,
2021
'RESOLUTION': {

test/manifests/segmentList.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const parsedManifest = {
1515
'AUDIO': 'audio',
1616
'BANDWIDTH': 449000,
1717
'CODECS': 'avc1.420015',
18+
'FRAME-RATE': 23.976,
1819
'NAME': '482',
1920
'PROGRAM-ID': 1,
2021
'RESOLUTION': {
@@ -112,6 +113,7 @@ export const parsedManifest = {
112113
'AUDIO': 'audio',
113114
'BANDWIDTH': 3971000,
114115
'CODECS': 'avc1.420015',
116+
'FRAME-RATE': 23.976,
115117
'NAME': '720',
116118
'PROGRAM-ID': 1,
117119
'RESOLUTION': {

0 commit comments

Comments
 (0)