Recovering a lost Red vs. Blue PSA
First posted by @NocontextRvB on Twitter, they asked if anyone who used Halo Waypoint remembers seeing this Red vs. Blue PSA.
To anyone who has used Halo Waypoint before, does anyone remember seeing this Red vs Blue PSA? There’s one clear image of it but the PSA itself is lost to time pic.twitter.com/dIw1HlFC1j
— No Context Red vs Blue (@NocontextRvB) December 30, 2025
In the comments user @reqsihw replies with some information. When I saw that video streams were still up I was interesting in seeing if I can get them.
Apparently it's 1:41 in length but there's no playback. Maybe the video still exists? Not sure. Here's some screenshots along with links here: https://t.co/3gxgfeQBFahttps://t.co/NTRaxW9Rhnhttps://t.co/vKMjNEihCa pic.twitter.com/0tYgXuwvud
— whisper (formerly snipe.) (aka improv) (@reqsihw) January 8, 2026
So that is where we begin, with the two files initially referenced. http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism/manifest and http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ismv
I downloaded each file with curl.
curl "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ismv" --output "2060770-3.ismv"
curl "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism/manifest" --output "manifest"But I also noticed manifest is after a .ism file, so I grabbed that as well.
curl "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism" --output "2060770-3.ism"I also generated a sha256 hash of each file (for others to confirm they have the same file).
Get-FileHash -Algorithm SHA256 *
Algorithm Hash Path
--------- ---- ----
SHA256 D26C730B590BEFA9EC9A4B85FF855E4A3BC6D781AAC9675EF05AF72BFF28BAB4 2060770-3.ism
SHA256 118D1365B7CC90E8EC165AC826BE3918B0B4061386513FF5BC2445856746EFB4 2060770-3.ismv
SHA256 9045C71B59DB43444D8B0D2647E01199B1C471F261521D4D5EB744820A6778F7 manifestI also wanted to see the file size.
Get-ChildItem *
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 9/01/2026 12:06 PM 4768 2060770-3.ism
-a--- 9/01/2026 12:05 PM 148467964 2060770-3.ismv
-a--- 9/01/2026 12:05 PM 15034 manifestLooking inside 2060770-3.ism I can see it also references 2060770-3.ismc so I took a stab at where it would be located and downloaded it.
curl "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ismc" --output "2060770-3.ismc"
I then also run the commands as I did before so we can keep a refernece of them.
Algorithm Hash Path
--------- ---- ----
SHA256 9045C71B59DB43444D8B0D2647E01199B1C471F261521D4D5EB744820A6778F7 2060770-3.ismcMode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 9/01/2026 12:10 PM 15034 2060770-3.ismcThis means that attempting to download the .ismc/manifest file results in the exact same file as just the .ismc. So going forward we will ignore the one that says manifest and just refer to it as the .ismc file.
For reference these three files have been uploaded to a GitHub repository associated with this post.
Looking up online what these files even mean I found some documentation that says there may or may not be a .isma file which would contain audio streams. I had a look for 2060770-3.isma but that was a 404. This does not mean there is no audio, it just means it is bundled in another file.
Opening up the .ism and .ismc files I can see they are both xml files. .ism referneces the .ismc and .ismv files. They also both have information about what is contained in the .ismv file and both indicate there is video and audio.
Using MediaInfo we can also extract the metadata of the this .ismv file (see 2060770-3-ismv-metadata.txt). But if we look at just a summary of that,
Stream 1 - Audio
Format : AAC LC
Format/Info : Advanced Audio Codec
Codec ID : mp4a-40-2
Channel(s) : 2 channels
Channel layout : L R
Sampling rate : 44.1 kHz
Stream 2 - Video
Bit rate : 3768 kb/s
Width : 1280 pixels
Height : 720 pixels
Stream 3 - Video
Bit rate : 2 229 kb/s
Width : 960 pixels
Height : 540 pixels
Stream 4 - Video
Bit rate : 1 553 kb/s
Width : 796 pixels
Height : 448 pixels
Stream 5 - Video
Bit rate : 1 122 kb/s
Width : 716 pixels
Height : 404 pixels
Stream 6 - Video
Bit rate : 974 kb/s
Width : 640 pixels
Height : 360 pixels
Stream 7 - Video
Bit rate : 658 kb/s
Width : 512 pixels
Height : 288 pixels
Stream 8 - Video
Bit rate : 520 kb/s
Width : 512 pixels
Height : 288 pixels
Stream 9 - Video
Bit rate : 392 kb/s
Width : 512 pixels
Height : 288 pixels
Stream 10 - Video
Bit rate : 212 kb/s
Width : 320 pixels
Height : 180 pixels
Stream 11 - Video
Bit rate : 133 kb/s
Width : 240 pixels
Height : 136 pixelsSo this single file contains 10 video tracks and 1 audio track.
Attempting to play these files in VLC or Media Player Classic result in nothing. However you can right mouse click and look at audio track and video track information to see it matches above.
Converting the files with FFMpeg
Next I used FFMpeg to try convert the file to an mp4.
ffmpeg -i 2060770-3.ismv output.mp4Which produces a 0kb file and errors with this,
[vf#0:0 @ 000002d939415b80] Cannot determine format of input 0:1 after EOF
[vf#0:0 @ 000002d939415b80] Task finished with error code: -1094995529 (Invalid data found when processing input)
[vf#0:0 @ 000002d939415b80] Terminating thread with return code -1094995529 (Invalid data found when processing input)
[af#0:1 @ 000002d93b6b6d80] No filtered frames for output stream, trying to initialize anyway.
[vost#0:0/libx264 @ 000002d9393ff100] [enc:libx264 @ 000002d93b4b9900] Could not open encoder before EOF
[vost#0:0/libx264 @ 000002d9393ff100] Task finished with error code: -22 (Invalid argument)
[vost#0:0/libx264 @ 000002d9393ff100] Terminating thread with return code -22 (Invalid argument)
[out#0/mp4 @ 000002d939404540] Nothing was written into output file, because at least one of its streams received no packets.I tried many things to get any data out. This may be a skill issue. I tried to force the input a/v codecs.
ffmpeg -acodec aac -vcodec h264 -i "2060770-3.ismv" -c copy -an output.mp4I tried to ignore the audio and just get video
ffmpeg -i "2060770-3.ismv" -c:v copy -an output.mp4I tried to ignore the video and just get the audio.
ffmpeg -i "2060770-3.ismv" -vn -c:a copy output.m4aI tried to map the input a/v streams to pick a specific one.
ffmpeg -i "2060770-3.ismv" -map 0:v:1 -map 0:a:0 -c:v copy -c:a copy output.mp4Some of these errored with "track 1: codec frame size is not set" so I tried to set the frame size for aac input.
ffmpeg -c:a aac -frame_size 1024 -i "2060770-3.ismv" -vn -c:a copy output.m4aAlmost all of the above still errored with "Output file is empty, nothing was encoded". I even tried various combinations of the above and I got nada.
Tryin yt-dlp instead
Going back to the start urls I had a look at using yt-dlp instead. First up was to just list the streams it can see by using the -F argument.
yt-dlp -F "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism/manifest"
[generic] Extracting URL: http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism/manifest
[generic] manifest: Downloading webpage
WARNING: [generic] Falling back on generic information extractor
[generic] manifest: Extracting information
WARNING: [generic] None is not a supported codec
[info] Available formats for manifest:
ID EXT RESOLUTION │ TBR PROTO │ VCODEC VBR ACODEC MORE INFO
──────────────────────────────────────────────────────────────────────
150 ismv 240x136 │ 150k ism │ H264 150k video only [und]
240 ismv 320x180 │ 240k ism │ H264 240k video only [und]
440 ismv 512x288 │ 440k ism │ H264 440k video only [und]
640 ismv 512x288 │ 640k ism │ H264 640k video only [und]
840 ismv 512x288 │ 840k ism │ H264 840k video only [und]
1240 ismv 640x360 │ 1240k ism │ H264 1240k video only [und]
1440 ismv 716x404 │ 1440k ism │ H264 1440k video only [und]
2056 ismv 796x448 │ 2056k ism │ H264 2056k video only [und]
2962 ismv 960x540 │ 2962k ism │ H264 2962k video only [und]
5027 ismv 1280x720 │ 5027k ism │ H264 5027k video only [und]Oddly enough without /manifest we get a much different result.
yt-dlp -F "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism"
[generic] Extracting URL: http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism
[generic] 2060770-3: Downloading webpage
WARNING: [generic] Falling back on generic information extractor
[generic] 2060770-3: Extracting information
[info] Available formats for 2060770-3:
ID EXT RESOLUTION │ TBR PROTO │ VCODEC ACODEC
─────────────────────────────────────────────────────────
http-5027 ismv unknown │ 5027k http │ unknown unknownyt-dlp -F "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ismv"
[generic] Extracting URL: http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ismv
[generic] 2060770-3: Downloading webpage
[info] Available formats for 2060770-3:
ID EXT RESOLUTION │ PROTO │ VCODEC ACODEC
──────────────────────────────────────────────
fmp4 ismv unknown │ http │ unknown unknownyt-dlp -F "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ismc"
[generic] Extracting URL: http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ismc
[generic] 2060770-3: Downloading webpage
WARNING: [generic] Falling back on generic information extractor
[generic] 2060770-3: Extracting information
WARNING: [generic] None is not a supported codec
[info] Available formats for 2060770-3:
ID EXT RESOLUTION │ TBR PROTO │ VCODEC VBR ACODEC MORE INFO
──────────────────────────────────────────────────────────────────────
150 ismv 240x136 │ 150k ism │ H264 150k video only [und]
240 ismv 320x180 │ 240k ism │ H264 240k video only [und]
440 ismv 512x288 │ 440k ism │ H264 440k video only [und]
640 ismv 512x288 │ 640k ism │ H264 640k video only [und]
840 ismv 512x288 │ 840k ism │ H264 840k video only [und]
1240 ismv 640x360 │ 1240k ism │ H264 1240k video only [und]
1440 ismv 716x404 │ 1440k ism │ H264 1440k video only [und]
2056 ismv 796x448 │ 2056k ism │ H264 2056k video only [und]
2962 ismv 960x540 │ 2962k ism │ H264 2962k video only [und]
5027 ismv 1280x720 │ 5027k ism │ H264 5027k video only [und]So yt-dlp doesn't explicitly say that it has found audio in any of these streams. So I let it download each of the above with default settings (which is to fetch the highest quality of each stream it could find) and see what the result is.
This first result downloaded a 45MiB file.
yt-dlp "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism/manifest"
[generic] Extracting URL: http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism/manifest
[generic] manifest: Downloading webpage
WARNING: [generic] Falling back on generic information extractor
[generic] manifest: Extracting information
WARNING: [generic] None is not a supported codec
[info] manifest: Downloading 1 format(s): 5027
[ism] Total fragments: 51
[download] Destination: manifest [manifest].ismv
[download] 100% of 45.68MiB in 00:00:03 at 14.38MiB/sThe second without /manifest resulted in a 404.
yt-dlp "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism"
[generic] Extracting URL: http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism
[generic] 2060770-3: Downloading webpage
WARNING: [generic] Falling back on generic information extractor
[generic] 2060770-3: Extracting information
[info] 2060770-3: Downloading 1 format(s): http-5027
ERROR: unable to download video data: HTTP Error 404: Not FoundThird resulted in a 141MiB file.
yt-dlp "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ismv"
[generic] Extracting URL: http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ismv
[generic] 2060770-3: Downloading webpage
[info] 2060770-3: Downloading 1 format(s): fmp4
[download] Destination: 2060770-3 [2060770-3].ismv
[download] 100% of 141.59MiB in 00:00:03 at 35.94MiB/sTrying the fourth it kept saying it was getting 404s while trying to get all 51 fragments.
yt-dlp "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ismc"
[generic] Extracting URL: http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ismc
[generic] 2060770-3: Downloading webpage
WARNING: [generic] Falling back on generic information extractor
[generic] 2060770-3: Extracting information
WARNING: [generic] None is not a supported codec
[info] 2060770-3: Downloading 1 format(s): 5027
[ism] Total fragments: 51
[download] Destination: 2060770-3 [2060770-3].ismv
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 1 (1/10)...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 1 (2/10)...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 1 (3/10)...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 1 (4/10)...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 1 (5/10)...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 1 (6/10)...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 1 (7/10)...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 1 (8/10)...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 1 (9/10)...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 1 (10/10)...
[download] Skipping fragment 1 ...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 2 (1/10)...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 2 (2/10)...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 2 (3/10)...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 2 (4/10)...
[download] Got error: HTTP Error 404: Not Found. Retrying fragment 2 (5/10)...So after all of that I have 2 files. 2060770-3 [2060770-3].ismv (141.59MiB) and manifest [manifest].ismv (45.68MiB). This file CAN be converted to an mp4 with ffmpeg.
ffmpeg -i "manifest [manifest].ismv" -an -c:v libx264 "manifest [manifest].mp4"The 2060770-3 [2060770-3].ismv does not play and extracting all its data with MediaInfo seems to say it is the same data. Checking the file hashes we can actually just confirm it is an identical file to what we had previously.
Algorithm Hash Path
--------- ---- ----
SHA256 118D1365B7CC90E8EC165AC826BE3918B0B4061386513FF5BC2445856746EFB4 2060770-3 [2060770-3].ismv
SHA256 36CCC5665CED8AE6D854EBE02DC7D0163BB3C2D832ABE3357BCA43C28CD5FB7E manifest [manifest].ismvSo now that we know manifest [manifest].ismv it plays we can also confirm it is a 1:41 long video, but unfortunately it has no audio. Fun fact - if you go look at the streams in the manifest file you can also see that the first video stream was actually 45.6 MiB. So this IS the first video stream yoinked as its own file.
So then what did yt-dlp do differently that I did with FFMpeg, we lets have a look with the -vvv verbose argument.
yt-dlp -vvv "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism/manifest"
[debug] Command-line config: ['-vvv', 'http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism/manifest']
[debug] Encodings: locale cp1252, fs utf-8, pref cp1252, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2025.12.08 from yt-dlp/yt-dlp [7a52ff29d] (win_exe)
[debug] Python 3.10.11 (CPython AMD64 64bit) - Windows-10-10.0.26200-SP0 (OpenSSL 1.1.1t 7 Feb 2023)
[debug] exe versions: ffmpeg N-121938-g2456a39581-20251130 (setts), ffprobe N-121938-g2456a39581-20251130
[debug] Optional libraries: Cryptodome-3.23.0, brotli-1.2.0, certifi-2025.11.12, curl_cffi-0.13.0, mutagen-1.47.0, requests-2.32.5, sqlite3-3.40.1, urllib3-2.6.0, websockets-15.0.1, yt_dlp_ejs-0.3.2
[debug] JS runtimes: deno-2.6.4
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets, curl_cffi
[debug] Plugin directories: none
[debug] Loaded 1854 extractors
[generic] Extracting URL: http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism/manifest
[generic] manifest: Downloading webpage
WARNING: [generic] Falling back on generic information extractor
[generic] manifest: Extracting information
WARNING: [generic] None is not a supported codec
[debug] Identified a ISM manifest
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec, channels, acodec, size, br, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] manifest: Downloading 1 format(s): 5027
[debug] Invoking ism downloader on "http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism/manifest"
[ism] Total fragments: 51
[download] Destination: manifest [manifest].ismv
[debug] File locking is not supported. Proceeding without locking
[download] 100% of 45.68MiB in 00:00:02 at 19.54MiB/sHaving a look through this I think the important part is "[debug] Invoking ism downloader on". We can look at the source code for yt-dlp, and specifically the ism downloader, ism.py. Looking at it, it seems it is using fragments to download the file which would imply it is not using a large .ismv file.
But where are the fragments?
And what even are fragments? Video streaming services typically split a file into many small parts. Depending on the file thousands. This particilar 1:41 video has 51 fragments. This means that if you start streaming a video it will download the first few fragments so you can start playing. If you leave you won't waste bandwidth getting videos chunks you won't see. Additionally it allows you (or the player automatically) to change the quality you are seeing.
If your internet speed is slow it will get the fragments that are a lower resolution. If your internet speed is higher, then it can get the larger fragments that are a higher resolution. This is how YouTubes quality picker works.
If we look back at the .ismc file we can see that it has an attribute in the StreamIndex called URL, "QualityLevels({bitrate})/Fragments(video={start time})". Having a poke around I was able to confirm that this is contains some placeholder text which can be replaced b a video bitrate and current position to return a particula fragment. For example, http://videos.halowaypoint.com/videos1/db6723e6038f41a1819e8e71be7776a0/2060770-3.ism/QualityLevels(5027000)/Fragments(video=0) is the first video fragment of the PSA.
fragDownloader
To help download all of these video (and audio) fragments I created a tool called fragDownloader.
In its current state it can download all the fragments... and that is about where I am up to. It downloads about 45MB of video fragments and about 1MB of audio fragments. These fragments need to be joined together and then merged into a single file which contains the audio and video. It is the first half of that sentence which is the tricky bit.
I did try to join the files by creating video_appended and audio_appended files. It just slaps them together one after another. This does not work as I had hoped.
What is next?
I don't know when I'll get time to jump back in, so others are more than welcome to continue where I left off.
I believe what needs to happen is that ism.py from the yt-dlp repository contains the missing piece. It can handle the individual moov, traf, and whatever else happens inside the fragments and moves them, or removes them, or whatever it is doing to then concatinate the files into a single resource.
Because we have the correct amount of video and audio data I believe that it is all there and not corrupted.
What is exciting is that we may be able to not just recover this missing RvB PSA, we may be able to recover and archive A LOT more of these videos from halo.xbox.com that appear to still exist but are unreacahble from any front facing web player.