PocketSync

I built PocketSync because putting a music video on a Nintendo 3DS was far more complicated than it had any right to be.

What began as a script for converting videos into one extremely particular format eventually became a macOS app for organizing, playing, and transferring my music video library. But the project really started with something less technical: I signed in to an old Apple account to look back at all the songs and music videos I had purchased when I was younger. But when I went to download them most of them were missing.

I had recently bought a Nintendo 3DS and wanted to use it like my old iPod nano, just a little device with music and videos I loved enough to purchase. And I thought that building that library myself seemed simple enough…

3DS Utility

It was 2025, and “Gnarly” by KATSEYE had just been released. Ironically, I didn’t even like the song at first, but it slowly grew on me. I bought the music video from iTunes and decided it would be fun to put it on my Nintendo 3DS, but… that turned out to be much harder than I expected.

The 3DS required a very specific kind of AVI file. The video had to be resized and encoded as Motion JPEG, while the audio needed its own particular format. Even after I got the video playing, it appeared in the wrong place because the 3DS Camera app used embedded date metadata rather than the file’s normal modification date.

I’m not really part of the modding scene, so the GBATemp post “Change the date of a 3DS video/picture” was the only guide I had to work from. And after a lot of experimenting with conversion and metadata, I finally got it working. So, I celebrated by making a silly little TikTok.

Automation

After converting a few videos by hand, I quickly realized I was repeating the same steps over and over. What started as a one-off script slowly turned into an automation tool that could handle video conversion, repair the date metadata, and transfer the finished files to the SD card.

Under the hood, PocketSync uses FFmpeg to turn each source into a 400×240 AVI containing Motion JPEG video at 20 frames per second and stereo, 32 kHz uncompressed audio.

The date fix ended up being the most unusual part. Changing the file’s creation or modification date wasn’t enough. PocketSync has to insert or update EXIF metadata inside the first JPEG frame stored in the AVI. Because that changes the size of the file, the app also repairs the AVI’s internal RIFF headers and index so that the finished video remains valid.

It wasn’t long before the command line became the bottleneck (aka I got too lazy to type the run command). I wanted something I could drag videos into, press a button, and let it take care of the rest.

Apple had also recently announced Liquid Glass, its new design language. It felt like a fun excuse to use SwiftUI again while building something I would actually use. The result was the first iteration of PocketSync’s interface.

Video Viewer

At this point, PocketSync was doing exactly what I had built it to do. It could import videos, convert them into the format the Nintendo 3DS expected, fix the metadata, and transfer everything to the SD card. It solved the original problem.

I only had a small collection of videos, but I found myself wanting have a little video player to run in the background. I had been relying on YouTube playlists, but YouTube's autoplay was never really random. It always seemed to fall back on the same handful of songs, even when they didn't fit the vibe. So instead of opening YouTube every day, I decided PocketSync should become its own music video player.

The conversion tools were moved into their own workspace, and I redesigned the main screen around playback. I wanted it to feel like an old iPod Nano, with a simple queue, shuffle mode, and a dedicated player that could stay open in the background while I worked. The player could sort videos by date, play them in order, or actually shuffle the entire library instead of relying on an unnecessary algorithm.

I even added a dedicated full-screen window for a second monitor. It sounds like a tiny detail, but I spent an embarrassing amount of time making sure pressing ESC actually closed the full-screen window.

Library Syncing

At this point, PocketSync was doing exactly what I had originally built it to do. It could import videos, convert them into the format expected by the Nintendo 3DS, patch their embedded dates, assign the numbered filenames used by the 3DS Camera app, and copy everything onto the SD card.

My collection was still fairly small, but I found myself wanting a little video player that I could leave running in the background. I had been relying on YouTube playlists, but its autoplay never felt genuinely random. It always seemed to return to the same handful of songs, even when they didn’t fit the vibe.

Instead of opening YouTube every day, I decided PocketSync should become its own music video player. I moved the conversion tools into a separate workspace and redesigned the main screen around playback. I wanted it to feel like an old iPod nano, with a simple queue, playback controls, and a player that could stay open while I worked.

The library normally appears with its most recently updated videos first. When shuffle is enabled, PocketSync creates a randomized version of the entire queue while keeping the current video at the front. From there, it plays through that shuffled queue instead of relying on an algorithm to fake a shuffle.

I also added a separate full-screen playback window. My original goal was to leave the video running on a second monitor while keeping PocketSync’s library and controls available in the main window. The full-screen window now works, although explicitly choosing which monitor it opens on is still on my list.

It sounds like a tiny detail, but I spent an embarrassing amount of time making sure full-screen playback could use the same player without restarting the video or losing its place.

What Comes Next

I’ve also started designing a plugin system for PocketSync. The idea is that extensions could eventually add new import sources, metadata providers, conversion formats, export destinations, playback options, or library actions without requiring all of that functionality to live inside the main app.

The protocol has already been mapped out: a plugin would declare what it can do and which permissions it needs, then communicate with PocketSync through structured requests and responses. The actual plugin loader and execution system aren’t finished yet, so this is still architecture rather than a feature people can use today.

I’m making PocketSync available on GitHub for anyone who wants to explore the code, fork the project, suggest improvements, or help build some of those ideas.

Next
Next

Character Design