^ fish.webm (consistently breaks on Switch 2) 2026-08-31T19:42:46.252Z idk if i've written about it on this public blog before... here's a dumb little example of something i like to do sometimes the example is: the mp4 in this tweet https://x.com/zizprocreate/status/1787254338701742123 2026-08-31T19:44:35.156Z (i'm sure there's a .gif version of this on the internet somewhere, but for the sake of this example pretend that's not the case. also, i don't know of any way to use twitter's CDN API to get the original .gif version of this, only the pre-converted .mp4 version, so y'know.)
this is the mp4 2026-08-31T19:51:15.959Z you open it in LosslessCut ( https://github.com/mifi/lossless-cut ) and- oh, uh, i didn't think this was important enough to note, but actually yes it is, so... this is the still image screenshot version of this, which i've seen reposted several times over the past two years lol well, let's say i want a high(-ish) quality version of just this one frame of the video, for making my own dumb shitposts with 2026-08-31T19:55:46.631Z so, okay, as i was saying, then you grab the original tweet's mp4 via ytdl or similar (i recommend yt-dlp - https://github.com/yt-dlp/yt-dlp - unless you have a specific reason to use a different tool), then you open it in LosslessCut... 2026-08-31T20:05:50.339Z you navigate to the first frame that matches the pattern seen in the screenshot--note the heart covering the smiley face's right eye-- and you click the Screenshot button...
well, okay before that, go into File -> Settings, under "Snapshots and frame extraction" set "Snapshot capture format" to JPEG, and "Snapshot capture quality" to 100%.
i do it this way because it makes everything easier, with regard to colorspace conversion inaccuracies and yuv420 -> rgb inaccuracies. because that's gonna be a problem with PNG snapshot captures from LosslessCut otherwise. or like if you wanted to go open the video file in VLC and use that to take a snapshot on a specific frame, in PNG format, best case scenario you run into the same inaccurate color conversion problems. LosslessCut's JPEG snapshots have the least color-conversion inaccuracies, generally, in my experience. but if you know more about ICC color spaces or whatever and know what you're doing, there's probably a way to make PNG snapshots work better, but you still run into yuv420->rgb problems which *can* matter in some cases.
(no there is not a properly-documented, better, more proper way to do this. trust me, i've checked. but i'm open to suggestions if you have found better results doing something differently...)
it's just a shitshow, but y'know. anyways. 2026-08-31T20:07:28.041Z oh! and make sure the "Snapshot capture method" is set to "FFmpeg" 2026-08-31T20:09:28.073Z also also, losslesscut devs dont know what theyre doing, so if you want to get rid of the pop-up that takes up the whole fucking window and which you have to dismiss, maybe disable "Show informational in-app notifications" in the settings too. (this used to be an unobtrusive toast notification towards the top of the screen, what gives? whatever dude.) 2026-08-31T20:16:12.105Z so anyways, you do all that, then you go to the first frame that matches the screenshot, and click the Snapshot/Screenshot button, or press the hotkey, whatever.
ADDITIONAL NOTE: rounding error is a bitch, (losslesscut is largely javascript, so it figures,) so when you do this, if you go and look at the jpeg that was just written in the same folder as the mp4, sometimes it wont be the same frame as the one displayed in the losslesscut window, it'll be usually ±1 frame off. (tho in some cases, in longer videos, that error can accumulate and it may be multiple frames off.) the workaround is: try stepping forward or backward 1 frame, and click the Snapshot button, then check the jpeg. if the new resulting jpeg is the frame you actually WANTED, then congrats! if not, then try again, adjusting by a different number of frames relative to the target desired frame, until it gives you the one you want.
as i was saying, okay great! you have one of the JPEGs you wanted! "but wait," you may ask, "JPEGs *plural*?" yes! i'm so glad you asked! 2026-08-31T20:29:45.400Z in cases like this example, the hearts animation is a repeating pattern! it repeats in full a total of 11 times over the course of this video. and if you go and pause at the *next* frame that matches the frame in the screenshot, you'll notice it's not pixel-for-pixel identical to the *first* frame that you captured earlier! this is because of [Lossy Video Encoding](https://en.wikipedia.org/wiki/Lossy_compression)
in theory, with some lossy-compression video codecs, it could have been encoded such that those two frames *are* identical, but in practice this is like, almost never the case. Especially when it's a frame in a repeating pattern, with one or more different frames in between itself and the next matching frame. and ESPECIALLY when it's a video transcode (re-encode) automatically created by a social media website, like twitter or youtube, because those typically use a 'one size fits all' configuration for transcoding videos into other formats or resolutions or bitrates, and that configuration isn't optimized for repeating GIFs, or like, video versions of slideshows.
regarding the bit about video versions of slideshows, refer to my older work on restoring the unofficial AMV (or PV?) made by someone i forget the name of, for the song Kero9destiny (ケロ⑨destiny). i don't have a link to share, cuz i never compiled my working notes nor any of my visual results into a proper blog post. remind me to do that! but here's a link to the AMV anyways: https://www.youtube.com/watch?v=aalpzhIkmnA anyways, back to this example, 2026-08-31T20:31:56.443Z if you're following along, here are the resulting 11 JPEG screenshots from the video: https://chainswordcs.com/blog/2026/video-screenshot-cleanup/Me_liking_their_tweet_screenshots.7z so, okay! 2026-08-31T20:40:15.254Z now what i do is uhh, click the first one, open it in GIMP (https://www.gimp.org/downloads/)) then uh, in the GIMP window make sure you've zoomed out so the entire image from edge to edge is visible in the viewport...* then in the file explorer window you select the other 10 image files, then click and drag them over onto the GIMP window, to add them to the canvas. (each one gets its own new layer.)
*: you often have to do this, because when you click and drag an image file onto the GIMP window to add it to the current canvas/scene, usually(?) its position is placed in the center of the viewport, so if you're zoomed-in looking at like the bottom left corner, and you do that, the new image file added won't be centered. :D 2026-08-31T20:41:46.755Z like so 2026-08-31T20:49:30.019Z side note: if you want to be extra, and maybe want to do something else outside the scope of this guide, or if you're just curious, here's a PNG of the original meme repost screenshot, which i quickly scaled down and cropped to fit the canvas as its own layer, for reference. https://chainswordcs.com/site/blog/2026/video-screenshot-cleanup/attachments/IMG_20251202_122932_edit.png oops, wrong URL, here's the real one: https://chainswordcs.com/blog/2026/video-screenshot-cleanup/attachments/IMG_20251202_122932_edit.png 2026-08-31T20:53:19.241Z anyways, so, 2026-08-31T21:00:29.904Z what i typically do now is, starting from the bottom most layer set to 100% opacity, for each additional layer--the 𝑛th layer--change its opacity from 100% to 1/𝑛 (aka: `1/𝑛 * 100` percent).
for example: - Layer 2: opacity = 50% - Layer 3: opacity = 33.3% - Layer 4: opacity = 25% - Layer 5: opacity = 20% - Layer 6: opacity = 16.7% - Layer 7: opacity = 14.3% - Layer 8: opacity = 12.5% - Layer 9: opacity = 11.1% - Layer 10: opacity = 10% - Layer 11: opacity = 9.1% and so on... 2026-08-31T21:10:14.812Z this is to take the average of all layers, combined together, with the idea that the result will be something closer to that frame of the original-quality video encode (or the original image) than any single frame of the transcoded video on its own. maybe not *much* closer, in some cases, but slightly closer.
side note: with this example video, it has 1 keyframe, at timestamp 0:00.000, so taking literally all of these and averaging them together is basically the best way to go.* things get more complicated when dealing with a video which has several keyframes dotted at various points throughout. uh, y'know. i'm not gonna get into that right now, it's easiest to demonstrate that with visual examples, i'll write about that in another blog post.
*: assuming you're trying to avoid editorializing, like doing manual touchups with the paintbrush tool or whatever, as much as possible. which, in most cases, yeah. or if you *are* looking to start doing more manual touchups, i'll talk about that some other time, that's outside the scope of this (set of) blog post(s). 2026-08-31T21:14:03.079Z the result will look something like this: q=100 jpeg version: 2026-08-31T21:17:05.487Z before: after: just look at that shine 2026-08-31T21:22:47.859Z yeah, so uh, that's how it's done 2026-08-31T21:33:35.855Z extra: okay, looking at the meme repost screenshot, the frame of the video appears to match the 11th version of this frame of the animation (timestamp: 0:14.429), so if i want then i can just extract that frame on its own and be done, and just use that for my own shitposting needs. Me liking their tweet-00.00.14.429.jpeg : 2026-08-31T21:37:37.512Z and for reference, screenshot of this frame via VLC: 2026-08-31T21:40:41.236Z screenshot via VLC, but with [Preferences (Advanced/All) → Input / Codecs → Video codecs → FFmpeg → Skip the loop filter for H.264 decoding] set to "All" (instead of the default "None"): anyways, i'll leave it at that for right now. :)