Skip to content

Commit d7e78f2

Browse files
authored
Merge pull request #1 from Eyevinn/feat/add-more-playlist-info
Feat/add more playlist info
2 parents 7e386e4 + 0b35e4d commit d7e78f2

File tree

8 files changed

+3326
-1885
lines changed

8 files changed

+3326
-1885
lines changed

.eslintrc.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ extends:
99

1010
plugins:
1111
- prettier
12-
- '@typescript-eslint'
12+
- "@typescript-eslint"
1313

1414
globals:
1515
Promise: true
@@ -19,10 +19,10 @@ rules:
1919
- error
2020
arrow-body-style: off
2121
no-console: off
22-
'@typescript-eslint/no-unused-vars': "error"
23-
'@typescript-eslint/explicit-module-boundary-types': off
22+
"@typescript-eslint/no-unused-vars": "error"
23+
"@typescript-eslint/explicit-module-boundary-types": off
2424

25-
parser: '@typescript-eslint/parser'
25+
parser: "@typescript-eslint/parser"
2626

2727
parserOptions:
2828
sourceType: module

demo/demo.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ document.addEventListener("DOMContentLoaded", () => {
77
};
88
const src =
99
"https://f53accc45b7aded64ed8085068f31881.egress.mediapackage-vod.eu-north-1.amazonaws.com/out/v1/1c63bf88e2664639a6c293b4d055e6bb/ade303f83e8444d69b7658f988abb054/2a647c0cf9b7409598770b9f11799178/manifest.m3u8";
10+
11+
// demuxed
12+
// const src =
13+
// "https://playertest.longtailvideo.com/adaptive/elephants_dream_v4/index.m3u8";
14+
1015
new SafariBitrateMonitor({
1116
videoElement,
1217
hlsManifestUrl: src,

demo/index.html

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
<!DOCTYPE html>
22
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Safari Bitrate Monitor</title>
7+
<script type="module" src="demo.js"></script>
8+
</head>
39

4-
<head>
5-
<meta charset="UTF-8">
6-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7-
<title>Safari Bitrate Monitor</title>
8-
<script type="module" src="demo.js"></script>
9-
</head>
10-
11-
<body>
12-
<div id="wrapper">
13-
<video src="https://f53accc45b7aded64ed8085068f31881.egress.mediapackage-vod.eu-north-1.amazonaws.com/out/v1/1c63bf88e2664639a6c293b4d055e6bb/ade303f83e8444d69b7658f988abb054/2a647c0cf9b7409598770b9f11799178/manifest.m3u8" controls>
14-
</video>
15-
</div>
16-
<style>
17-
#wrapper {
18-
width: 100%;
19-
max-width: 800px;
20-
margin: 0 auto;
21-
}
22-
23-
video {
24-
max-width: 100%;
25-
}
26-
</style>
27-
</body>
10+
<body>
11+
<div id="wrapper">
12+
<video
13+
src="https://f53accc45b7aded64ed8085068f31881.egress.mediapackage-vod.eu-north-1.amazonaws.com/out/v1/1c63bf88e2664639a6c293b4d055e6bb/ade303f83e8444d69b7658f988abb054/2a647c0cf9b7409598770b9f11799178/manifest.m3u8"
14+
controls
15+
></video>
16+
</div>
17+
<style>
18+
#wrapper {
19+
width: 100%;
20+
max-width: 800px;
21+
margin: 0 auto;
22+
}
2823

24+
video {
25+
max-width: 100%;
26+
}
27+
</style>
28+
</body>
2929
</html>

index.ts

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,70 @@ export interface IQualityLevel {
22
bitrate: number;
33
width: number;
44
height: number;
5+
fps: number;
6+
audioCodec: string;
7+
videoCodec: string;
58
}
69

7-
export interface IHLSPlaylist {
10+
export interface IHLSPlaylist extends IQualityLevel {
811
url: string;
9-
width: number;
10-
height: number;
11-
bitrate: number;
1212
}
1313

1414
const HLS_ATTRIBUTE_REGEXP = new RegExp(
1515
'(?:,?)([A-Z0-9-]+?)[=](".*?"|[^",]+)(?=,|s*$)',
1616
"g"
1717
);
1818

19+
const guessCodec = (
20+
codecs: string[]
21+
): { audio?: string; video: string } | undefined => {
22+
if (codecs.length === 1) {
23+
return {
24+
audio: undefined,
25+
video: codecs[0],
26+
};
27+
}
28+
29+
if (codecs.length >= 2) {
30+
// Guess based on some of the most common codecs. There is no
31+
// way to be 100% certain which codec belongs to which track
32+
// in the HLS standard.
33+
const firstIsProbablyVideo = codecs[0].includes("avc");
34+
const secondIsProbablyVideo = codecs[1].includes("avc");
35+
36+
const firstIsProbablyAudio = codecs[0].includes("mp4a");
37+
const secondIsProbablyAudio = codecs[1].includes("mp4a");
38+
39+
if (firstIsProbablyVideo) {
40+
return {
41+
video: codecs[0],
42+
audio: codecs[1],
43+
};
44+
}
45+
46+
if (secondIsProbablyVideo) {
47+
return {
48+
video: codecs[1],
49+
audio: codecs[0],
50+
};
51+
}
52+
53+
if (firstIsProbablyAudio) {
54+
return {
55+
video: codecs[1],
56+
audio: codecs[0],
57+
};
58+
}
59+
60+
if (secondIsProbablyAudio) {
61+
return {
62+
video: codecs[0],
63+
audio: codecs[1],
64+
};
65+
}
66+
}
67+
};
68+
1969
const BITRATE_POLL_INTERVAL = 5 * 1000;
2070

2171
export class SafariBitrateMonitor {
@@ -75,6 +125,9 @@ export class SafariBitrateMonitor {
75125
width: 0,
76126
height: 0,
77127
bitrate: 0,
128+
fps: 0,
129+
audioCodec: "",
130+
videoCodec: "",
78131
};
79132
if (line.includes("#EXT-X-STREAM-INF")) {
80133
let valid = false;
@@ -93,6 +146,23 @@ export class SafariBitrateMonitor {
93146
playlist.height = Number(height);
94147
break;
95148
}
149+
case "CODECS": {
150+
const codecs = value.replace(/"/g, "").split(",");
151+
152+
const avCodecs = guessCodec(codecs);
153+
154+
playlist.videoCodec = avCodecs.video;
155+
playlist.audioCodec = avCodecs.audio;
156+
157+
break;
158+
}
159+
case "FRAME-RATE":
160+
if (value) {
161+
playlist.fps = Number(value);
162+
}
163+
break;
164+
default:
165+
break;
96166
}
97167
}
98168
if (valid) {
@@ -118,6 +188,9 @@ export class SafariBitrateMonitor {
118188
bitrate: playlist.bitrate,
119189
width: playlist.width,
120190
height: playlist.height,
191+
videoCodec: playlist.videoCodec,
192+
audioCodec: playlist.audioCodec,
193+
fps: playlist.fps,
121194
});
122195
}
123196
}, this.bitratePollInterval);

0 commit comments

Comments
 (0)