A homebrew video player for the Nintendo 3DS. MIVF uses a custom page-based video container, software codecs tuned for the ARM11, a native C player, and a PC-side encoder that converts ordinary video files into .mivf.
Status: Tested on real hardware (New 3DS / Old 3DS) and the Azahar emulator. Primary target: 400×240, 30 fps. Old 3DS may need the --profile 3ds-fast encoder preset for smooth playback.
- Custom codecs: M2Y1 (raw-token YUV420) and M2Y2 (entropy-coded with a division-free binary range coder — smaller files, similar quality). Also supports RAWV, M2Y0, and PC16/IA4M audio.
- File browser: thumbnail previews,
.coverposters,.nfosynopsis, favorites, and recents with debounced preview loading for smooth scrolling. - MoFlex playback:
.moflex(MobiClip 3D video) files are recognized in the browser and play via the built-in MoFlex backend. See docs/MOFLEX_STATUS.md for details. - Auto-resume bookmarks: pick up where you left off.
- Auto-advance: automatically play the next file in the folder.
- Aspect ratio modes: FIT (letterbox), STRETCH (fill), NATIVE (1:1).
- A/B scene looper: mark two points and loop the section.
- Playback speed: 0.5× to 2.0× with pitch-corrected audio.
- Sleep timer + lid-close pause: pauses cleanly and resumes on wake.
- Subtitles:
.srtsupport with multiple tracks, adjustable delay and position. - Chapters:
.chapterssidecar with named markers, previous/next navigation. - Customization: themes, adjustable brightness, auto-dim, font scale, persistent settings saved on close.
- Touch transport: drag the timeline to scrub.
- Seek index: sidecar
.idxand embedded footer for fast seeking. Large uncached files skip expensive synchronous scanning at open time.
See docs/CONTROLS.md for the full control map.
| Context | Button | Action |
|---|---|---|
| Browser | D-Pad ↑/↓ | Move selection |
| Browser | A | Open file |
| Browser | Y | Toggle favorite |
| Browser | B / START | Exit |
| Playback | A | Play / pause |
| Playback | ←/→ | Seek ±5 s |
| Playback | Touch + drag | Scrub timeline |
| Playback | X | Cycle playback speed |
| Playback | B | A/B loop marker |
| Playback | Y | Cycle subtitle track |
| Playback | L + D-Pad | Audio volume |
| Playback | R + ↑/↓ | Screen brightness |
| Playback | R + ←/→ | Previous / next chapter |
| Playback | SELECT | Open settings |
| Playback | START | Stop and return to browser |
D-Pad ↑/↓ to move, A/←/→ to change, B or SELECT to close and save.
See docs/INSTALLING.md for detailed instructions.
- Download
mivf_player_3ds.cia(HOME menu) ormivf_player_3ds.3dsx(Homebrew Launcher) from the Releases page. - Install
.ciawith FBI, or place.3dsxinsdmc:/3ds/. - Put
.mivffiles insdmc:/mivf/. The player also scanssdmc:/3ds/mivf_player_3ds/and the SD root. - Settings and app data live under
sdmc:/3ds/mivf_player_3ds/appdata/. Legacy root-level settings are still read for migration.
See docs/ENCODING.md for full encoder documentation and tuning guidance.
Quick examples:
# Recommended: M2Y2 (smaller files, same quality)
python encode_mivf.py input.mp4 output.mivf --m2y2
# Old 3DS: smaller packets for smoother playback
python encode_mivf.py input.mp4 output.mivf --m2y2 --profile 3ds-fast
# Batch encode a folder
python encode_mivf.py ./videos/ ./output/Requirements: Python 3 and ffmpeg on your system PATH.
| Flag | Purpose |
|---|---|
--m2y2 |
Use M2Y2 codec (smaller files, ~20% savings) |
--profile 3ds-fast |
Tune for Old 3DS playback smoothness |
--report-packet-sizes |
Print per-video-packet size histogram after encoding |
--no-seek-index |
Skip .idx sidecar generation |
--no-embedded-index |
Skip embedded seek footer in .mivf |
--qp |
Quality parameter (higher QP = smaller file, lower quality) |
--keep {4,8,16} |
Transform coefficients per quadrant (16 = max detail, 4 = smallest) |
--fps |
Override output frame rate |
--jobs |
Parallel encoder workers (default 8) |
--audio-codec {ia4m,pc16} |
Audio format: ia4m (ADPCM mono, small) or pc16 (PCM stereo, larger) |
See python encode_mivf.py --help for the complete flag list.
Place these next to yourvideo.mivf:
| File | Purpose |
|---|---|
yourvideo.srt, yourvideo.1.srt |
Subtitle tracks (cycle with Y) |
yourvideo.chapters |
Chapter markers with optional labels |
yourvideo.cover |
Poster image (raw RGB565, browser-preview size) |
yourvideo.nfo |
Synopsis text shown in the browser preview |
yourvideo.idx |
Seek index sidecar (auto-generated by encoder) |
See docs/FILES_AND_SIDECARS.md for details.
- New 3DS: M2Y2 at 400×240, 30 fps runs well with default encoder settings.
- Old 3DS: Use
--profile 3ds-fastwhen encoding. Consider--keep 4or--keep 8for demanding content. See docs/PERFORMANCE_TUNING.md. - Seek index: Encoder generates both sidecar (
.idx) and embedded index by default. Large uncached files skip expensive synchronous scanning at open time for faster load.
- Installing
- Encoding Videos
- Controls Reference
- Files & Sidecars
- Seek Index
- MoFlex Status
- Performance Tuning
- Developer Build
- Troubleshooting
- Architecture
- Release Checklist
See docs/DEVELOPING.md for full instructions.
Quickstart:
# Requires devkitPro (3ds-dev group: devkitARM + libctru)
make # builds mivf_player_3ds.3dsx
make cia # builds mivf_player_3ds.cia (requires makerom + bannertool)source/— Native 3DS player (C).main.cis the app;mivf_*.c/.hare modules.tools/— Native encoder, M2Y2 transcoder, and helper binaries.meta/— Icon, banner, banner audio, makerom RSF.Makefile— Builds.3dsxandmake ciafor installable title.encode_mivf.py— Python front-end for ffmpeg →.mivfencoding.
Built with devkitPro / devkitARM and libctru. CIA packaging uses makerom and bannertool. MoFlex demuxer and decoder are adapted from FFmpeg (LGPL).
Released under the MIT License. Bundled FFmpeg-derived components retain their original LGPL licensing.