Interactive timeline-based datamoshing for clip-level I-frame and P-frame manipulation.
Current version: v1.1.5.
If this project helps your workflow, support ongoing development and experiments:
- Patreon: https://www.patreon.com/Seriousshit
- PayPal: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=dogme84%40gmail.com¤cy_code=USD
Screenshot:
Sample output video:
- Fix: Temp directories from normalization and I-frame injection are now cleaned up when a clip is removed, preventing
/tmpaccumulation over long sessions - Fix: Video info probing (fps, frame count, dimensions) moved off the Qt main thread — no more UI freeze after importing clips
- Fix: Timeline scroll wheel now pans;
Ctrl+wheelzooms (was inverted vs. shortcut docs) - Fix: Clip list view now highlights the correct row when a timeline clip is clicked
- Fix: Settings panel controls are now disabled when no clip is selected (prevented silent no-op slider interactions)
- Fix: "Cut At Playhead" context menu item disabled on empty timeline
- Fix:
UpdateWorkerexceptions no longer permanently block future update checks - Fix: OpenCV video capture handle always released via
finally(prevents file lock on Windows) - Fix:
RenderDialogstops its render worker when the dialog is closed mid-render - Fix: Drag-reorder MIME data parse is now validated; malformed drops return
Falsecleanly - Fix: Undo/redo stacks use
deque(maxlen=200)for O(1) eviction - Fix: Timeline hint text contrast raised to meet WCAG AA minimum
Datamosh GUI is a PySide6 desktop editor built for experimental compression-art workflows.
- Build a sequence from multiple clips on a timeline
- Drag clips from bin to timeline, reorder segments, and cut at playhead
- Control keyframe behavior per clip or per timeline segment
- Toggle "Drop first I-frame" on individual cuts/segments
- Duplicate P-frames to push motion-smear and prediction artifacts
- Preview timeline output before final render
- Undo/redo timeline and settings changes
The app keeps AVI bitstream manipulation in mosh.py and uses the GUI as an editor/orchestrator.
main.py: GUI entrypointgui/: active PySide6 applicationmosh.py: core AVI parser/rewriter + CLItests/: pytest suitelegacy/: old Tkinter-era code (reference only, not active)
- Python 3.10+
ffmpegandffprobeavailable onPATH
Install Python deps:
pip install -r requirements.txtpython3 main.pyOr use:
./launch.sh- Current release page:
https://github.com/willbearfruits/datamosh-gui/releases/tag/v1.1.5 - Download portal:
https://willbearfruits.github.io/datamosh-gui/ - Release pipeline:
.github/workflows/release.yml - Packaging details:
RELEASES.md
Local build output naming (Linux host):
local-release-artifacts/Datamosh-<version>-linux-portable.tar.gzlocal-release-artifacts/Datamosh-<version>-linux-installer.deblocal-release-artifacts/Datamosh-<version>-linux-<arch>.AppImagelocal-release-artifacts/SHA256SUMS-linux.txt
Cross-platform local attempt logs (Linux host):
local-release-artifacts/windows-build-attempt.loglocal-release-artifacts/macos-build-attempt.log
Use native OS runners for release-quality builds. Linux can package Linux artifacts locally; Windows and macOS should be built on their own platforms.
Linux:
pyinstaller --noconfirm --clean --windowed --name Datamosh \
--add-data "README.md:." \
--add-data "LICENSE:." \
--add-data "VERSION:." \
main.py
./packaging/linux/build_deb.sh "$(cat VERSION)" "dist/Datamosh" "local-release-artifacts"
./packaging/linux/build_appimage.sh "$(cat VERSION)" "dist/Datamosh" "local-release-artifacts"Windows (PowerShell, run on Windows):
pyinstaller --noconfirm --clean --windowed --name Datamosh `
--add-data "README.md;." `
--add-data "LICENSE;." `
--add-data "VERSION;." `
main.pymacOS (run on macOS):
pyinstaller --noconfirm --clean --windowed --name Datamosh \
--add-data "README.md:." \
--add-data "LICENSE:." \
--add-data "VERSION:." \
--osx-bundle-identifier com.datamosh.gui \
main.py- Open one or more source clips.
- Choose import mode/settings (normalize recommended, direct-AVI optional advanced).
- Wait for ingest/normalization to complete.
- Drag clips from bin to timeline and reorder as needed.
- Use playhead +
Cut(Ctrl+K) to split timeline segments. - Inject a one-frame I-frame clip from image/video (
Ctrl+Shift+I) when needed. - Toggle
Drop I(I) for selected segment when needed. - Adjust per-clip/segment settings:
- Keep extra keyframes after first
- Duplicate count
- Duplicate gap
- Keep/drop specific keyframe indices
- Preview timeline output.
- Render final AVI.
Ctrl+O: open clipsCtrl+Shift+O: add clipsCtrl+R: renderCtrl+Z: undoCtrl+Shift+Z/Ctrl+Y: redoSpace: play/pause previewLeft/Right: frame stepCtrl+K: cut selected timeline segment at playheadCtrl+Shift+I: inject single I-frame clip from mediaI: toggle drop-first I-frame for selected segmentDelete: remove selected timeline segmentF1: shortcut help
mosh.py is usable directly for scripted workflows:
python3 mosh.py input.avi output.avi --keep-first 1 --duplicate-count 2 --duplicate-gap 3Normalization example:
python3 mosh.py input.mp4 output.avi --normalize --normalize-preset balancedHeadless-safe full suite:
QT_QPA_PLATFORM=offscreen pytest -q- Current output target is AVI/Xvid.
- Non-AVI sources are normalized before processing.
legacy/exists for historical reference; active code path ismain.py+gui/.
