This repository has been archived by the owner on Oct 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathrun.js
149 lines (133 loc) · 4.68 KB
/
run.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
const fs = require("fs");
const puppeteer = require("puppeteer-core");
const normalNetworkPatterns = require("./normal-network-patterns.js");
const fastNetworkPatterns = require("./fast-network-patterns.js");
const stats = require("./stats");
const CHROME_PATH =
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
let patterns;
if (process.env.npm_package_config_ffmpeg_profile === 'PROFILE_FAST') {
patterns = fastNetworkPatterns;
} else {
patterns = normalNetworkPatterns
}
const configNetworkProfile = process.env.npm_package_config_network_profile;
const NETWORK_PROFILE = patterns[configNetworkProfile] || patterns.PROFILE_CASCADE;
console.log("Network profile:", NETWORK_PROFILE);
run()
.then((result) => {
console.log("Test finished. Press cmd+c to exit.");
if (!fs.existsSync('./results')){
fs.mkdirSync('./results');
}
fs.writeFileSync(`./results/run-${NETWORK_PROFILE}-${new Date().toISOString().split(' ').join('-')}.json`, JSON.stringify(result));
})
.catch(error => console.log(error));
async function run() {
const browser = await puppeteer.launch({
headless: false,
executablePath: CHROME_PATH,
defaultViewport: null,
devtools: true,
});
const page = await browser.newPage();
await page.goto("http://localhost:3000/samples/low-latency/index.html");
const cdpClient = await page.target().createCDPSession();
console.log("Waiting for player to setup.");
await page.evaluate(() => {
return new Promise(resolve => {
const hasLoaded = player.getBitrateInfoListFor("video").length !== 0;
if (hasLoaded) {
console.log('Stream loaded, setup complete.');
resolve();
} else {
console.log('Waiting for stream to load.');
player.on(dashjs.MediaPlayer.events.STREAM_INITIALIZED, (e) => {
console.log('Load complete.')
resolve();
});
}
});
});
console.log("Waiting for 10 seconds of uninterrupted max-quality playback before starting.");
const stabilized = await awaitStabilization(page);
if (!stabilized) {
console.error(
"Timed out after 30 seconds. The player must be stable at the max rendition before emulation begins. Make sure you're on a stable connection of at least 3mbps, and try again."
);
return;
}
console.log("Player is stable at the max quality, beginning network emulation");
page.evaluate(() => {
window.startRecording();
});
await runNetworkPattern(cdpClient, NETWORK_PROFILE);
const metrics = await page.evaluate(() => {
if (window.stopRecording) {
// Guard against closing the browser window early
window.stopRecording();
}
player.pause();
return window.abrHistory;
});
console.log("Run complete");
if (!metrics) {
console.log("No metrics were returned. Stats will not be logged.");
}
console.log(metrics);
({ switchHistory, ...result } = metrics);
result.averageBitrate = stats.computeAverageBitrate(switchHistory);
result.numSwitches = switchHistory.length;
console.log(result);
return result;
}
async function awaitStabilization (page) {
return await page.evaluate(() => {
console.log('Awaiting stabilization...')
return new Promise(resolve => {
const maxQuality = player.getBitrateInfoListFor("video").length - 1;
let timer = -1;
const failTimer = setTimeout(() => {
resolve(false);
}, 30000)
if (player.getQualityFor("video") === maxQuality) {
console.log('Starting stabilization timer...')
timer = setTimeout(() => {
clearTimeout(failTimer);
resolve(true);
}, 10000);
}
player.on(dashjs.MediaPlayer.events.QUALITY_CHANGE_RENDERED, e => {
console.warn("Quality changed requested", e);
if (e.newQuality !== maxQuality) {
console.log('Clearing stabilization timer...', e.newQuality, maxQuality)
clearTimeout(timer);
timer = -1;
} else if (timer === -1) {
console.log('Starting stabilization timer...')
timer = setTimeout(() => {
clearTimeout(failTimer);
resolve(true);
}, 10000);
}
});
});
});
}
async function runNetworkPattern(client, pattern) {
for await (const profile of pattern) {
console.log(
`Setting network speed to ${profile.speed}kbps for ${profile.duration} seconds`
);
setNetworkSpeedInMbps(client, profile.speed);
await new Promise(resolve => setTimeout(resolve, profile.duration * 1000));
}
}
function setNetworkSpeedInMbps(client, mbps) {
client.send("Network.emulateNetworkConditions", {
offline: false,
latency: 0,
uploadThroughput: (mbps * 1024) / 8,
downloadThroughput: (mbps * 1024) / 8
});
}