I was downloading matches from the FIFA+ Archive website using (N_m3u8DL-RE), and I was helped with that by (2nHxWW6GkN1l916N3ayz8HQoi).

During this process, he discovered that the FIFA website has two versions of each match,
a normal version with the FIFA logo,
and another hidden version without the logo

Image
[Attachment 90880 - Click to enlarge]


He created a script file for me to run using Python that allowed me to download the hidden files without the logo

Code:
import base64
import json
import os
import re
from os.path import join
from urllib.parse import quote

import isodate
import requests
import xmltodict
from pssh_box import _parse_boxes, widevine_pssh_data_pb2, _generate_widevine_data
from pywidevine import PSSH, Device, Cdm
from slugify import slugify

USE_MPD = True
INPUT_FILE = "input.txt"
WVD_FILE = "cdm.wvd"
INTRO_DURATION = 5
TEMP_MPD_FOLDER = "temp_mpd"

DEFAULT_LICENSE_URL = 'https://content-aeui1.uplynk.com/wv'
VIDEO_PLAYER_URL = 'https://cxm-api.fifa.com/fifaplusweb/api/videoPlayerData/{video_id}'
PREPLAY_URL = 'https://content.uplynk.com/preplay/{content_id}/multiple.json'


def get_keys(license_url, pssh):
    if license_url is None:
        license_url = DEFAULT_LICENSE_URL

    pssh = PSSH(pssh)
    device = Device.load(WVD_FILE)
    cdm = Cdm.from_device(device)
    session_id = cdm.open()
    challenge = cdm.get_license_challenge(session_id, pssh)

    response = requests.post(license_url, data=challenge)
    response.raise_for_status()

    cdm.parse_license(session_id, response.content)
    keys = []
    for key in cdm.get_keys(session_id):
        if "CONTENT" not in key.type:
            continue
        keys.append(f'{key.kid.hex}:{key.key.hex()}')
    cdm.close(session_id)

    return keys


def get_mpd_command(manifest, video_title):
    manifest = manifest.replace(".m3u8?", ".mpd?")
    response = requests.get(manifest).content.decode()
    response = xmltodict.parse(response)

    kids_psshs = []
    periods = response["MPD"].get("Period", [])
    if type(periods) is not list:
        periods = [periods]

    filtered_periods = []
    for period in periods:
        if period.get("@duration", None) is None:
            continue
        duration = isodate.parse_duration(period["@duration"])
        duration = duration.total_seconds()
        if duration < INTRO_DURATION:
            continue

        filtered_periods.append(period)
        adaptations = period.get("AdaptationSet", [])
        if type(adaptations) is not list:
            adaptations = [adaptations]

        for adaptation in adaptations:
            protections = adaptation.get("ContentProtection", [])
            if type(protections) is not list:
                protections = [protections]

            current_kid, current_pssh, license_url = None, None, None
            for protection in protections:
                if protection.get("@cenc:default_KID", None) is not None:
                    current_kid = protection["@cenc:default_KID"]
                if PSSH.SystemId.Widevine.__str__() in protection.get("@schemeIdUri", ""):
                    current_pssh = protection["cenc:pssh"]["#text"]
                    license_url = protection.get("ms:laurl", {}).get("@licenseUrl", None)

                if current_kid is not None and current_pssh is not None:
                    break

            kids_psshs.append((current_kid.replace("-", ""), current_pssh, license_url))

    content_id_dict = {}
    pssh_data_dict = {}
    for k, p, l in kids_psshs:
        pssh_box = _parse_boxes(base64.b64decode(p))[0]
        pssh_data = widevine_pssh_data_pb2.WidevinePsshData()
        pssh_data.ParseFromString(pssh_box.pssh_data)

        if not pssh_data.HasField('content_id'):
            continue
        content_id = str(base64.b16encode(pssh_data.content_id).decode())

        provider = None
        if pssh_data.HasField('provider'):
            provider = pssh_data.provider
        protection_scheme = None
        if pssh_data.HasField('protection_scheme'):
            protection_scheme = pssh_data.protection_scheme

        content_id_dict[content_id] = content_id_dict.get(content_id, []) + [(k, l)]
        if pssh_data_dict.get(content_id, None) is None:
            pssh_data_dict[content_id] = (provider, protection_scheme, pssh_data.content_id)

    merged_psshs = []
    for cid, kid_license in content_id_dict.items():
        kids = [kid.encode() for kid, _ in kid_license]
        provider, protection_scheme, raw_cid = pssh_data_dict[cid]

        pssh_data = _generate_widevine_data(
            kids,
            content_id=raw_cid,
            provider=provider,
            protection_scheme=protection_scheme
        )
        merged_pssh = PSSH.new(init_data=pssh_data, system_id=PSSH.SystemId.Widevine)
        merged_psshs.append((merged_pssh.__str__(), kid_license[0][1]))

    keys = []
    for pssh, license_url in merged_psshs:
        keys += get_keys(license_url, pssh)

    assert len(keys) > 0
    keys = ' '.join([f'--key {k}' for k in keys])

    response["MPD"]["Period"] = filtered_periods
    response = xmltodict.unparse(response, pretty=True)

    output_path = join(TEMP_MPD_FOLDER, f"{video_title}.mpd")
    with open(output_path, "w") as f:
        f.write(response)
    return (
        f'N_m3u8DL-RE "{output_path}" {keys} --save-dir "fifa_com" --save-name "{video_title}" -M format=mkv'
        f' & '
        f'del "{output_path}"'
    )


def get_command(url):
    video_id = re.search(r"/watch/([^/?]*)", url).group(1)
    response = requests.get(
        VIDEO_PLAYER_URL.format(video_id=video_id),
        params={'locale': 'en'}
    )

    status_code = response.status_code
    if status_code == 404:
        raise Exception("Content not available")

    response = json.loads(response.content.decode())
    video_title = slugify(response.get('title', video_id))

    response = response["preplayParameters"]
    preplay_url = PREPLAY_URL.format(content_id=response["contentId"])
    if response.get("queryStr", None) is not None:
        preplay_url += "?" + response["queryStr"]
    if response.get("signature", None) is not None:
        if "?" not in preplay_url:
            preplay_url += "?"
        else:
            preplay_url += "&"
        preplay_url += "sig=" + quote(response["signature"])

    response = json.loads(requests.get(preplay_url).content.decode())["playURL"]

    if USE_MPD:
        return get_mpd_command(response, video_title)
    return f'N_m3u8DL-RE "{response}" --save-dir "fifa_com" --save-name "{video_title}"'


if __name__ == '__main__':
    if not os.path.exists(TEMP_MPD_FOLDER):
        os.makedirs(TEMP_MPD_FOLDER)

    with open(INPUT_FILE, 'r') as file:
        urls = file.readlines()
    urls = [u.strip() for u in urls]
    urls = list(dict.fromkeys([u for u in urls if len(u) > 0 and "plus.fifa.com" not in u]))

    index = 0
    nr = len(urls)
    for u in urls:
        index += 1
        print(f'[{index}/{nr}]')

        try:
            print(get_command(u))
        except Exception as e:
            print(f"Failed to get: {u}. Reason: {str(e)}. Try again later...")
However, after changing the file source from the FIFA website to the FIFA+ Archive website, the script for the hidden version no longer works as it used to.

This is the link to the match whose images are attached.

Code:
https://www.plus.fifa.com/en/content/spain-v-nigeria-group-d-1998-fifa-world-cup-france-full-match-replay/277d9e39-29c4-47ad-9511-4d9ceffa699e?gl=sa
and there are more details in these two topics

Code:
https://forum.videohelp.com/threads/415550-Any-Help-with-error-Download-first-segment-failed%21
Code:
https://forum.videohelp.com/threads/414899-Regarding-downloading-using-%28N_m3u8DL-RE%29
I hope someone can help me write another script that can download the hidden version of the files.