Skip to content

Commit

Permalink
Rewrite bitrate test
Browse files Browse the repository at this point in the history
Use XMLHttpRequest to measure the actual loading stage and get
the actual number of bytes loaded.
  • Loading branch information
dmitrylyzo committed Oct 26, 2022
1 parent fa4e5b6 commit 56dc003
Showing 1 changed file with 59 additions and 13 deletions.
72 changes: 59 additions & 13 deletions src/apiClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const reportRateLimits = {

/** Approximate LAN bitrate */
const LAN_BITRATE = 140000000;
/** Bitrate test timeout in milliseconds */
const BITRATETEST_TIMEOUT = 5000;

function redetectBitrate(instance) {
stopBitrateDetection(instance);
Expand Down Expand Up @@ -746,22 +748,66 @@ class ApiClient {
}

getDownloadSpeed(byteSize) {
const url = this.getUrl('Playback/BitrateTest', {
Size: byteSize
});
return new Promise((resolve, reject) => {
const url = this.getUrl('Playback/BitrateTest', {
Size: byteSize
});

const now = new Date().getTime();
console.log(`Requesting ${url}`);

return this.ajax({
type: 'GET',
url,
timeout: 5000
}).then(() => {
const responseTimeSeconds = (new Date().getTime() - now) / 1000;
const bytesPerSecond = byteSize / responseTimeSeconds;
const bitrate = Math.round(bytesPerSecond * 8);
const xhr = new XMLHttpRequest;

xhr.open('GET', url, true);

const headers = {
'Cache-Control': 'no-cache'
};

this.setRequestHeaders(headers);

for (const key in headers) {
xhr.setRequestHeader(key, headers[key]);
}

const timeout = setTimeout(() => {
xhr.abort();
reject('BitrateTest timeout');
}, BITRATETEST_TIMEOUT);

let startTime;

xhr.onreadystatechange = () => {
if (xhr.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
startTime = performance.now();
}
};

xhr.onload = (e) => {
clearTimeout(timeout);

if (xhr.status < 400) {
const responseTimeSeconds = (performance.now() - startTime) * 1e-3;

// Some older web engines (WebKit in webOS 1.2) may not have `ProgressEvent.loaded` field.
const loaded = e.loaded || byteSize;

const bytesPerSecond = loaded / responseTimeSeconds;
const bitrate = Math.round(bytesPerSecond * 8);

console.debug(`BitrateTest ${loaded} bytes loaded (${byteSize} requested) in ${responseTimeSeconds} seconds -> ${bitrate} bps`);

resolve(bitrate);
} else {
reject(`BitrateTest failed with ${xhr.status} status`);
}
};

xhr.onerror = () => {
clearTimeout(timeout);
reject('BitrateTest error');
};

return bitrate;
xhr.send(null);
});
}

Expand Down

0 comments on commit 56dc003

Please sign in to comment.