diff --git a/yt_dlp/downloader/mhtml.py b/yt_dlp/downloader/mhtml.py
index 1477f65a6..bc86fd1bf 100644
--- a/yt_dlp/downloader/mhtml.py
+++ b/yt_dlp/downloader/mhtml.py
@@ -166,7 +166,11 @@ body > figure > img {
if (i + 1) <= ctx['fragment_index']:
continue
- fragment_url = urljoin(fragment_base_url, fragment['path'])
+ fragment_url = fragment.get('url')
+ if not fragment_url:
+ assert fragment_base_url
+ fragment_url = urljoin(fragment_base_url, fragment['path'])
+
success, frag_content = self._download_fragment(ctx, fragment_url, info_dict)
if not success:
continue
diff --git a/yt_dlp/extractor/francetv.py b/yt_dlp/extractor/francetv.py
index 877c5c055..347a766d8 100644
--- a/yt_dlp/extractor/francetv.py
+++ b/yt_dlp/extractor/francetv.py
@@ -187,7 +187,7 @@ class FranceTVIE(InfoExtractor):
'protocol': 'mhtml',
'url': 'about:invalid',
'fragments': [{
- 'path': sheet,
+ 'url': sheet,
# XXX: not entirely accurate; each spritesheet seems to be
# a 10×10 grid of thumbnails corresponding to approximately
# 2 seconds of the video; the last spritesheet may be shorter
diff --git a/yt_dlp/extractor/youtube.py b/yt_dlp/extractor/youtube.py
index 7e3f142c7..4fe9cec5b 100644
--- a/yt_dlp/extractor/youtube.py
+++ b/yt_dlp/extractor/youtube.py
@@ -3208,7 +3208,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
'width': width,
'height': height,
'fragments': [{
- 'path': url.replace('$M', str(j)),
+ 'url': url.replace('$M', str(j)),
'duration': min(fragment_duration, duration - (j * fragment_duration)),
} for j in range(math.ceil(fragment_count))],
}