Skip to content

Commit

Permalink
feat: add support for a frame-rate attribute (#159)
Browse files Browse the repository at this point in the history
* feat: add support for a frame-rate attribute

* docs: fix typo in comment
  • Loading branch information
gjanblaszczyk authored Aug 2, 2022
1 parent 269e406 commit cd75be1
Show file tree
Hide file tree
Showing 19 changed files with 129 additions and 68 deletions.
13 changes: 13 additions & 0 deletions src/parseAttributes.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { parseDivisionValue } from './utils/string';
import { from } from './utils/list';
import { parseDuration, parseDate } from './utils/time';

Expand Down Expand Up @@ -131,6 +132,18 @@ export const parsers = {
return parseInt(value, 10);
},

/**
* Specifies the frame rate of the representation
*
* @param {string} value
* value of attribute as a string
* @return {number}
* The parsed frame rate
*/
frameRate(value) {
return parseDivisionValue(value);
},

/**
* Specifies the number of the first Media Segment in this Representation in the Period
*
Expand Down
4 changes: 4 additions & 0 deletions src/toM3u8.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,10 @@ export const formatVideoPlaylist = ({
segments
};

if (attributes.frameRate) {
playlist.attributes['FRAME-RATE'] = attributes.frameRate;
}

if (attributes.contentProtection) {
playlist.contentProtection = attributes.contentProtection;
}
Expand Down
10 changes: 10 additions & 0 deletions src/utils/string.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Converts the provided string that may contain a division operation to a number.
*
* @param {string} value - the provided string value
*
* @return {number} the parsed string value
*/
export const parseDivisionValue = (value) => {
return parseFloat(value.split('/').reduce((prev, current) => prev / current));
};
1 change: 1 addition & 0 deletions test/manifests/608-captions.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 449000,
'CODECS': 'avc1.420015',
'FRAME-RATE': 23.976,
'NAME': '482',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down
1 change: 1 addition & 0 deletions test/manifests/708-captions.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 449000,
'CODECS': 'avc1.420015',
'FRAME-RATE': 23.976,
'NAME': '482',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down
1 change: 1 addition & 0 deletions test/manifests/location.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 449000,
'CODECS': 'avc1.420015',
'FRAME-RATE': 23.976,
'NAME': '482',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down
1 change: 1 addition & 0 deletions test/manifests/locations.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 449000,
'CODECS': 'avc1.420015',
'FRAME-RATE': 23.976,
'NAME': '482',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down
2 changes: 2 additions & 0 deletions test/manifests/maat_vtt_segmentTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ export const parsedManifest = {
'NAME': '482',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'FRAME-RATE': 23.976,
'RESOLUTION': {
width: 482,
height: 270
Expand Down Expand Up @@ -487,6 +488,7 @@ export const parsedManifest = {
'NAME': '720',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'FRAME-RATE': 23.976,
'RESOLUTION': {
width: 720,
height: 404
Expand Down
45 changes: 24 additions & 21 deletions test/manifests/multiperiod-dynamic.js
Original file line number Diff line number Diff line change
Expand Up @@ -613,16 +613,17 @@ export const parsedManifest = {
playlists: [
{
attributes: {
'NAME': 'default_video2000_0_1280x720',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'BANDWIDTH': 2008000,
'CODECS': 'avc1.4d001f',
'FRAME-RATE': 29.97,
'NAME': 'default_video2000_0_1280x720',
'PROGRAM-ID': 1,
'RESOLUTION': {
width: 1280,
height: 720
height: 720,
width: 1280
},
'CODECS': 'avc1.4d001f',
'BANDWIDTH': 2008000,
'PROGRAM-ID': 1
'SUBTITLES': 'subs'
},
uri: '',
endList: false,
Expand Down Expand Up @@ -905,16 +906,17 @@ export const parsedManifest = {
},
{
attributes: {
'NAME': 'default_video1200_1_960x540',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'BANDWIDTH': 1195000,
'CODECS': 'avc1.4d001f',
'FRAME-RATE': 29.97,
'NAME': 'default_video1200_1_960x540',
'PROGRAM-ID': 1,
'RESOLUTION': {
width: 960,
height: 540
height: 540,
width: 960
},
'CODECS': 'avc1.4d001f',
'BANDWIDTH': 1195000,
'PROGRAM-ID': 1
'SUBTITLES': 'subs'
},
uri: '',
endList: false,
Expand Down Expand Up @@ -1197,16 +1199,17 @@ export const parsedManifest = {
},
{
attributes: {
'NAME': 'default_video900_1_640x360',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'BANDWIDTH': 884000,
'CODECS': 'avc1.4d001e',
'FRAME-RATE': 29.97,
'NAME': 'default_video900_1_640x360',
'PROGRAM-ID': 1,
'RESOLUTION': {
width: 640,
height: 360
height: 360,
width: 640
},
'CODECS': 'avc1.4d001e',
'BANDWIDTH': 884000,
'PROGRAM-ID': 1
'SUBTITLES': 'subs'
},
uri: '',
endList: false,
Expand Down
1 change: 1 addition & 0 deletions test/manifests/multiperiod-segment-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 449000,
'CODECS': 'avc1.420015',
'FRAME-RATE': 23.976,
'NAME': '482',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down
15 changes: 8 additions & 7 deletions test/manifests/multiperiod-segment-template.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,17 @@ export const parsedManifest = {
playlists: [
{
attributes: {
'NAME': '1',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'BANDWIDTH': 100000,
'CODECS': 'avc1.4d001f',
'FRAME-RATE': 24,
'NAME': '1',
'PROGRAM-ID': 1,
'RESOLUTION': {
width: 480,
height: 200
height: 200,
width: 480
},
'CODECS': 'avc1.4d001f',
'BANDWIDTH': 100000,
'PROGRAM-ID': 1
'SUBTITLES': 'subs'
},
uri: '',
endList: true,
Expand Down
6 changes: 6 additions & 0 deletions test/manifests/multiperiod-startnumber-removed-periods.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 2942295,
'CODECS': 'avc1.4d001f',
'FRAME-RATE': 30,
'NAME': 'D',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down Expand Up @@ -155,6 +156,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 4267536,
'CODECS': 'avc1.640020',
'FRAME-RATE': 60,
'NAME': 'E',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down Expand Up @@ -219,6 +221,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 5256859,
'CODECS': 'avc1.640020',
'FRAME-RATE': 60,
'NAME': 'F',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down Expand Up @@ -283,6 +286,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 240781,
'CODECS': 'avc1.4d000d',
'FRAME-RATE': 30,
'NAME': 'A',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down Expand Up @@ -347,6 +351,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 494354,
'CODECS': 'avc1.4d001e',
'FRAME-RATE': 30,
'NAME': 'B',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down Expand Up @@ -411,6 +416,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 1277155,
'CODECS': 'avc1.4d001f',
'FRAME-RATE': 30,
'NAME': 'C',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down
6 changes: 6 additions & 0 deletions test/manifests/multiperiod-startnumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 2942295,
'CODECS': 'avc1.4d001f',
'FRAME-RATE': 30,
'NAME': 'D',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down Expand Up @@ -333,6 +334,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 4267536,
'CODECS': 'avc1.640020',
'FRAME-RATE': 60,
'NAME': 'E',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down Expand Up @@ -486,6 +488,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 5256859,
'CODECS': 'avc1.640020',
'FRAME-RATE': 60,
'NAME': 'F',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down Expand Up @@ -639,6 +642,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 240781,
'CODECS': 'avc1.4d000d',
'FRAME-RATE': 30,
'NAME': 'A',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down Expand Up @@ -792,6 +796,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 494354,
'CODECS': 'avc1.4d001e',
'FRAME-RATE': 30,
'NAME': 'B',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down Expand Up @@ -945,6 +950,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 1277155,
'CODECS': 'avc1.4d001e',
'FRAME-RATE': 30,
'NAME': 'C',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down
45 changes: 24 additions & 21 deletions test/manifests/multiperiod.js
Original file line number Diff line number Diff line change
Expand Up @@ -613,16 +613,17 @@ export const parsedManifest = {
playlists: [
{
attributes: {
'NAME': 'default_video2000_0_1280x720',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'BANDWIDTH': 2008000,
'CODECS': 'avc1.4d001f',
'FRAME-RATE': 29.97,
'NAME': 'default_video2000_0_1280x720',
'PROGRAM-ID': 1,
'RESOLUTION': {
width: 1280,
height: 720
height: 720,
width: 1280
},
'CODECS': 'avc1.4d001f',
'BANDWIDTH': 2008000,
'PROGRAM-ID': 1
'SUBTITLES': 'subs'
},
uri: '',
endList: true,
Expand Down Expand Up @@ -905,16 +906,17 @@ export const parsedManifest = {
},
{
attributes: {
'NAME': 'default_video1200_1_960x540',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'BANDWIDTH': 1195000,
'CODECS': 'avc1.4d001f',
'FRAME-RATE': 29.97,
'NAME': 'default_video1200_1_960x540',
'PROGRAM-ID': 1,
'RESOLUTION': {
width: 960,
height: 540
height: 540,
width: 960
},
'CODECS': 'avc1.4d001f',
'BANDWIDTH': 1195000,
'PROGRAM-ID': 1
'SUBTITLES': 'subs'
},
uri: '',
endList: true,
Expand Down Expand Up @@ -1197,16 +1199,17 @@ export const parsedManifest = {
},
{
attributes: {
'NAME': 'default_video900_1_640x360',
'AUDIO': 'audio',
'SUBTITLES': 'subs',
'BANDWIDTH': 884000,
'CODECS': 'avc1.4d001e',
'FRAME-RATE': 29.97,
'NAME': 'default_video900_1_640x360',
'PROGRAM-ID': 1,
'RESOLUTION': {
width: 640,
height: 360
height: 360,
width: 640
},
'CODECS': 'avc1.4d001e',
'BANDWIDTH': 884000,
'PROGRAM-ID': 1
'SUBTITLES': 'subs'
},
uri: '',
endList: true,
Expand Down
1 change: 1 addition & 0 deletions test/manifests/segmentBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 449000,
'CODECS': 'avc1.420015',
'FRAME-RATE': 23.976,
'NAME': '482',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down
2 changes: 2 additions & 0 deletions test/manifests/segmentList.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 449000,
'CODECS': 'avc1.420015',
'FRAME-RATE': 23.976,
'NAME': '482',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down Expand Up @@ -112,6 +113,7 @@ export const parsedManifest = {
'AUDIO': 'audio',
'BANDWIDTH': 3971000,
'CODECS': 'avc1.420015',
'FRAME-RATE': 23.976,
'NAME': '720',
'PROGRAM-ID': 1,
'RESOLUTION': {
Expand Down
Loading

0 comments on commit cd75be1

Please sign in to comment.