[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f3d3omv8ir3q5":3,"$fanuq43nlrv5g":49},{"slug":4,"title":5,"body":6,"summary":7,"tags":8,"author":13,"cover_url":14,"published_at":15,"seo_title":5,"seo_description":7,"reading_minutes":16,"related":17},"bullet-time-with-first-last-frame-video","Bullet time with first\u002Flast-frame video: orbiting a frozen moment from three stills","\u003Cp>A \"bullet time\" shot freezes a moment and moves the camera around it. The film version used a ring of still cameras. This one uses three generated stills and a video model that can be told where a clip must \u003Cem>end\u003C\u002Fem>, not just where it starts. It's a small extension of the \u003Ca href=\"\u002Fblog\u002Fan-ai-media-pipeline-that-shows-its-work\">media pipeline I wrote about before\u003C\u002Fa>, and every image and clip here came out of it — requested through this post's own media API, with the prompts and GPU times below.\u003C\u002Fp>\n\n\u003Cfigure data-post-media=\"6abac80f45201648bfd466c0\">\n  \u003Cvideo src=\"https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abac80f45201648bfd466c5-0-d5822d59.mp4\" autoplay muted loop playsinline preload=\"metadata\" width=\"848\" height=\"480\">\u003C\u002Fvideo>\n  \u003Cfigcaption>The result: 848×480, 192 frames at 16 fps — two first\u002Flast-frame clips joined, then ping-ponged into a loop.\u003C\u002Ffigcaption>\n\u003C\u002Ffigure>\n\n\u003Ch2>The idea: sample the orbit, let the video model interpolate\u003C\u002Fh2>\n\u003Cp>An orbit is a path of camera positions around a fixed scene. Generate a few points on that path as stills, then ask a video model for the motion between neighbouring points:\u003C\u002Fp>\n\u003Cul>\n  \u003Cli>\u003Cstrong>Points on the path:\u003C\u002Fstrong> the action still (front), plus the \u003Cem>angle\u003C\u002Fem> preset — Qwen-Image-Edit with a camera-move LoRA — at 45° right and 45° left.\u003C\u002Fli>\n  \u003Cli>\u003Cstrong>Segments:\u003C\u002Fstrong> the \u003Cem>video\u003C\u002Fem> preset is Wan 2.2 image-to-video with \u003Ccode>WanFirstLastFrameToVideo\u003C\u002Fcode>: the first frame and the last frame are both conditioning inputs, so the clip is pinned at both ends. Right → front, then front → left.\u003C\u002Fli>\n  \u003Cli>\u003Cstrong>Join:\u003C\u002Fstrong> segment 2 starts on the exact frame segment 1 ends on, so the join is continuous by construction.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Ch3>The still\u003C\u002Fh3>\n\u003Cfigure data-post-media=\"6aba9cedeb1db62ec33b02db\">\n  \u003Cimg src=\"https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6aba9cedeb1db62ec33b02e0-0-5a549ce7.png\" alt=\"A glass of water frozen mid-fall above a dark desk\" width=\"1344\" height=\"768\" loading=\"lazy\">\n  \u003Cfigcaption>1344×768, 30 s on the GPU. The prompt asked for a glass tipping over, frozen mid-fall. All three takes came back with the glass upright and the water leaping out of it — a frozen moment all the same, so the cleanest one stayed. \"Tipping over\" is a relationship between the glass and gravity; the fast model draws the objects and drops the verb.\u003C\u002Ffigcaption>\n\u003C\u002Ffigure>\n\u003Cp class=\"prompt\">\u003Cstrong>image · 16:9 · 30 s on the GPU\u003C\u002Fstrong>\u003Cbr>A glass of water tipping over on a dark slate desk, frozen mid-fall, the water suspended in the air in a clear arc with droplets hanging still, deep navy background, crisp high-speed photography, one single glass\u003C\u002Fp>\n\n\u003Ch3>Two more points on the orbit\u003C\u002Fh3>\n\u003Cfigure data-post-media=\"6abaac173e21d5cbd14d42a6\">\n  \u003Cimg src=\"https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abaac183e21d5cbd14d42ac-0-57d0b850.png\" alt=\"The frozen glass seen from 45 degrees to the right\" width=\"1360\" height=\"768\" loading=\"lazy\">\n  \u003Cfigcaption>rotate-right-45, 2 min 17 s on the GPU.\u003C\u002Ffigcaption>\n\u003C\u002Ffigure>\n\u003Cfigure data-post-media=\"6abaaeb33e21d5cbd14d4409\">\n  \u003Cimg src=\"https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abaaeb43e21d5cbd14d440f-0-c3d0c4be.png\" alt=\"The frozen glass seen from 45 degrees to the left\" width=\"1360\" height=\"768\" loading=\"lazy\">\n  \u003Cfigcaption>rotate-left-45, 2 min 17 s on the GPU.\u003C\u002Ffigcaption>\n\u003C\u002Ffigure>\n\n\u003Ch3>Two segments\u003C\u002Fh3>\n\u003Cp>Per-post media grew an end frame for this. The request for segment 1:\u003C\u002Fp>\n\u003Cpre>\u003Ccode>POST \u002Fadmin\u002Feditorial\u002Fposts\u002Fifcodes\u002F{slug}\u002Fmedia\n{\"purpose\": \"inline\", \"preset\": \"video\", \"aspect\": \"16:9\", \"frames\": 49,\n \"source_media_id\": \"&lt;right-45 still&gt;\", \"end_media_id\": \"&lt;front still&gt;\",\n \"prompt\": \"Frozen moment: … nothing moves except the camera.\"}\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Both ids resolve to bucket keys server-side; the flow hands them to \u003Ccode>mediagen\u002Fgenerate\u003C\u002Fcode> as \u003Ccode>source_key\u003C\u002Fcode> \u002F \u003Ccode>end_key\u003C\u002Fcode>, and the patcher traces the video node's \u003Ccode>start_image\u003C\u002Fcode> and \u003Ccode>end_image\u003C\u002Fcode> inputs back to their loaders — so it doesn't matter which \u003Ccode>LoadImage\u003C\u002Fcode> node is which in the graph.\u003C\u002Fp>\n\u003Cfigure data-post-media=\"6abab67d45201648bfd45db2\">\n  \u003Cvideo src=\"https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abab67e45201648bfd45db9-0-c3560467.mp4\" autoplay muted loop playsinline preload=\"metadata\" width=\"848\" height=\"480\">\u003C\u002Fvideo>\n  \u003Cfigcaption>Segment 1, right → front: 848×480, 49 frames, 4 min 19 s on the GPU.\u003C\u002Ffigcaption>\n\u003C\u002Ffigure>\n\u003Cfigure data-post-media=\"6ababe7345201648bfd4603a\">\n  \u003Cvideo src=\"https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6ababe7545201648bfd46041-0-bf847203.mp4\" autoplay muted loop playsinline preload=\"metadata\" width=\"848\" height=\"480\">\u003C\u002Fvideo>\n  \u003Cfigcaption>Segment 2, front → left: 848×480, 49 frames, 4 min 17 s on the GPU.\u003C\u002Ffigcaption>\n\u003C\u002Ffigure>\n\u003Cp class=\"prompt\">\u003Cstrong>video · 16:9 · 49 frames · first + last frame\u003C\u002Fstrong>\u003Cbr>Frozen moment: the tipping glass, the arc of water and every droplet hang perfectly still in the air while the camera glides smoothly around it. Time is stopped — nothing moves except the camera.\u003C\u002Fp>\n\n\u003Ch3>Stitching, on the same box\u003C\u002Fh3>\n\u003Cp>Joining is a preset too — \u003Ccode>stitch\u003C\u002Fcode> — so it runs on the GPU box like everything else, requested through the same post-media API with the two clips' media ids and \u003Ccode>pingpong: true\u003C\u002Fcode>. There is no stored graph: the node count depends on the clips, so the graph is built per request from core ComfyUI nodes only.\u003C\u002Fp>\n\u003Cul>\n  \u003Cli>Each clip: \u003Ccode>LoadVideo → GetVideoComponents\u003C\u002Fcode>. Every clip after the first goes through \u003Ccode>ImageFromBatch(batch_index=1)\u003C\u002Fcode> — its first frame is the previous clip's last, so the seam frame is dropped.\u003C\u002Fli>\n  \u003Cli>The parts are concatenated with \u003Ccode>ImageBatch\u003C\u002Fcode> nodes arranged as a balanced tree, not a chain.\u003C\u002Fli>\n  \u003Cli>Ping-pong needs the sequence reversed, and core ComfyUI has no batch-reverse node. So the reverse pass is one single-frame \u003Ccode>ImageFromBatch\u003C\u002Fcode> per frame, from \u003Ccode>total−2\u003C\u002Fcode> down to \u003Ccode>1\u003C\u002Fcode> — both turn-around frames are already in the forward pass, and the loop restarts on frame 0 — merged by the same balanced tree. For two 49-frame clips that's 95 slice nodes; nobody sees them, the Go builder writes them.\u003C\u002Fli>\n  \u003Cli>\u003Ccode>CreateVideo\u003C\u002Fcode> at 16 fps → \u003Ccode>SaveVideo\u003C\u002Fcode>. Frame counts come from the clips' own jobs, so the request doesn't need them.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Two 49-frame clips come out as 49 + 48 + 95 = 192 frames. A unit test plays the generated graph's node semantics over labelled frames and asserts that exact order — the kind of thing that is easy to get off by one and impossible to spot by eye at 16 fps.\u003C\u002Fp>\n\n\u003Ch2>Where it breaks\u003C\u002Fh2>\n\u003Cul>\n  \u003Cli>\u003Cstrong>The water is redrawn per angle.\u003C\u002Fstrong> The camera-move model repaints the scene from each viewpoint, and a splash has no fixed shape to preserve: the arcs and droplets differ between the three stills. First\u002Flast-frame pinning then has to morph one splash into another while the camera turns — watch the water reshape in both segments above. The glass and the desk edge carry the orbit; the water doesn't.\u003C\u002Fli>\n  \u003Cli>\u003Cstrong>The model doesn't know time is stopped.\u003C\u002Fstrong> \"Nothing moves except the camera\" is a request, not a constraint. Droplets can drift between the pinned first and last frames. There's no negative prompt to lean on either: the lightning-LoRA video preset samples at CFG 1, where negatives are a no-op.\u003C\u002Fli>\n  \u003Cli>\u003Cstrong>45° is a big step.\u003C\u002Fstrong> The further apart two stills are, the more the model has to invent in between. More, closer points (every 20–30°) would give a smoother orbit — at one angle render plus one clip per extra point.\u003C\u002Fli>\n\u003C\u002Ful>\n","A freeze-frame camera orbit built from generated stills: one action shot, two camera-move angles, two first\u002Flast-frame clips between them, stitched and ping-ponged. The pipeline, the seams, and where the model re-imagines the water.",[9,10,11,12],"ai","comfyui","video-generation","flowdsl","if.codes","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abae46c45201648bfd477a7-0-6f4d036e.png","2026-09-28T22:42:41Z",4,[18,28,39],{"slug":19,"title":20,"type":21,"summary":22,"tags":23,"author":13,"cover_url":25,"published_at":26,"updated_at":27},"an-ai-media-pipeline-that-shows-its-work","An AI media pipeline that shows its work: ComfyUI presets, FlowDSL routing and the misses","blog","How the images on my sites are generated: four ComfyUI presets behind one Go module, job rows as state, FlowDSL flows for routing, per-post media in the admin — and the bugs and model misses I hit shipping it. This post's own images were made the same way.",[9,12,10,24],"image-generation","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6aba8ba317ceba3543925be4-0-2f6b8a5c.png","2026-09-28T15:57:50Z","2026-09-28T15:57:50.784Z",{"slug":29,"title":30,"type":21,"summary":31,"tags":32,"author":13,"cover_url":36,"published_at":37,"updated_at":38},"openai-embeddings-python-mongodb","Transforming Text into Vectors: OpenAI Embeddings in Python","Learn how to generate text embeddings with the OpenAI API in Python to power semantic search, recommendations, and more. Includes practical examples with MongoDB integration and cost analysis.",[33,9,34,35],"openai","python","mongodb","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abad0fa45201648bfd46c2d-0-2e60b732.png","2024-11-23T00:00:00Z","2026-09-28T22:31:01.385Z",{"slug":40,"title":41,"type":21,"summary":42,"tags":43,"author":13,"cover_url":46,"published_at":47,"updated_at":48},"check-pricing-availability-ing-domains","Last Chance to Grab Short .ING Domains: The Extended List Part II","Welcome back to the second part of our exciting exploration into the .ING domain zone! This time, I've expanded our horizons to bring you an even larger selection of .ING domain names. List of over 24,000 domain names inside.",[44,45],"domains","business","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abad0fa45201648bfd46c38-0-c55f4c8d.png","2023-12-14T00:00:00Z","2026-09-28T22:31:01.453Z",[50,53,56,59,62,71,82],{"slug":4,"title":5,"type":21,"summary":7,"tags":51,"author":13,"cover_url":14,"published_at":15,"updated_at":52,"reading_minutes":16},[9,10,11,12],"2026-09-28T22:42:41.6Z",{"slug":19,"title":20,"type":21,"summary":22,"tags":54,"author":13,"cover_url":25,"published_at":26,"updated_at":27,"reading_minutes":55},[9,12,10,24],7,{"slug":29,"title":30,"type":21,"summary":31,"tags":57,"author":13,"cover_url":36,"published_at":37,"updated_at":38,"reading_minutes":58},[33,9,34,35],3,{"slug":40,"title":41,"type":21,"summary":42,"tags":60,"author":13,"cover_url":46,"published_at":47,"updated_at":48,"reading_minutes":61},[44,45],1,{"slug":63,"title":64,"type":21,"summary":65,"tags":66,"author":13,"cover_url":67,"published_at":68,"updated_at":69,"reading_minutes":70},"impressive-ing-domains","Unveiling the Impressive .ING Domains","Discover the vast potential of the new .ING domain zone in my latest blog post! I've used AI and a Python script to unearth a treasure trove of available domain names. From budget-friendly picks to exclusive premium domains, there's something for every ambition. Plus, a special list of unique, lesser-known domains awaits.",[44,45],"https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abad0fa45201648bfd46c43-0-03be24b7.png","2023-12-11T00:00:00Z","2026-09-28T22:31:01.527Z",2,{"slug":72,"title":73,"type":21,"summary":74,"tags":75,"author":13,"cover_url":79,"published_at":80,"updated_at":81,"reading_minutes":58},"secured-web-server-in-5-minutes","Fortify Web Server Security in 5 Minutes with Tailscale","Tailscale revolutionizes secure networking with its user-friendly approach, effortlessly connecting devices across diverse networks.",[76,77,78],"firewall","tailscale","webserver","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abad0fa45201648bfd46c4e-0-eae6f62d.png","2023-11-03T00:00:00Z","2026-09-28T22:31:01.597Z",{"slug":83,"title":84,"type":21,"summary":85,"tags":86,"author":13,"cover_url":89,"published_at":90,"updated_at":91,"reading_minutes":92},"lets-encrypt-free-ssl","How to Secure Your Website with Free SSL Certificates for a Lifetime","Let’s Encrypt certificates have revolutionized internet security by providing free, automated, and widely trusted SSL\u002FTLS certificates. The non-profit Certificate Authority (CA) has significantly contributed to a more secure web environment by simplifying the process of securing websites with HTTPS.",[87,88,78],"ssl","https","https:\u002F\u002Fmedia.stufio.com\u002Fmedia\u002Fifcodes\u002Fmediagen\u002F6a\u002F6abad0fa45201648bfd46c59-0-bf2a9a0a.png","2023-11-01T00:00:00Z","2026-09-28T22:39:13.555Z",6]