async parseBroadcast(url) {
        if (!url.endsWith("/"))
            url += "/";
        // Some packets are formatted slightly differently in
        // broadcast fragments compared to a normal demo file.
        this._isBroadcastFragment = true;
        const syncUrl = new url_1.URL("sync", url).toString();
        const syncResponse = await httpGet(syncUrl);
        const syncDto = JSON.parse(syncResponse.toString());
        if (syncDto.protocol !== 4) {
            throw new Error(`expected protocol version 4, got: ${syncDto.protocol}`);
        }
        if (syncDto.token_redirect != null) {
            url = new url_1.URL(syncDto.token_redirect, url).toString();
            if (!url.endsWith("/"))
                url += "/";
        }
        this.header = {
            magic: "HL2DEMO",
            protocol: syncDto.protocol,
            networkProtocol: 0,
            serverName: `GOTV Broadcast: ${url}`,
            clientName: "GOTV Demo",
            mapName: syncDto.map,
            gameDirectory: "csgo",
            playbackTime: 0,
            playbackTicks: 0,
            playbackFrames: 0,
            signonLength: 0
        };
        this.tickInterval = 1 / syncDto.tps;
        let cancelled = false;
        this.emit("start", {
            cancel() {
                cancelled = true;
            }
        });
        // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
        if (cancelled) {
            return;
        }
        const startUrl = new url_1.URL(`${syncDto.signup_fragment | 0}/start`, url).toString();
        const startResponse = await httpGet(startUrl);
        // Read the signon fragment
        this._bytebuf = ByteBuffer.wrap(startResponse, true);
        while (this._bytebuf.remaining() > 0) {
            this._readCommand();
        }
        // Keep reading fragments until we run out
        let fragment = syncDto.fragment | 0;
        let fragmentType = "full";
        while (!this._hasEnded) {
            const fragmentUrl = new url_1.URL(`${fragment}/${fragmentType}`, url).toString();
            let fragmentResponse;
            try {
                fragmentResponse = await httpGet(fragmentUrl);
            }
            catch {
                // HTTP 404 errors are expected - each fragment only lasts for a few seconds.
                // Wait for 1-2 secs before retrying to avoid spamming the relay.
                await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 1000));
                continue;
            }
            // We need to request {fragment}/full + {fragment}/delta
            if (fragmentType == "full") {
                fragmentType = "delta";
            }
            else {
                fragment += 1;
            }
            this._bytebuf = ByteBuffer.wrap(fragmentResponse, true);
            while (this._bytebuf.remaining() > 0) {
                this._readCommand();
            }
        }
    }
Start streaming a GOTV broadcast over HTTP.
Will keep streaming until the broadcast finishes.

@param url URL to the GOTV broadcast.
@returns Promise that resolves then the broadcast finishes.