vid2gifx


Namevid2gifx JSON
Version 0.1.1 PyPI version JSON
download
home_pageNone
SummaryFFmpeg-only video to GIF converter with palettegen/paletteuse and size targeting.
upload_time2025-10-10 14:26:42
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords ffmpeg gif video conversion palettegen paletteuse
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # vi2gifx — FFmpeg-only video → GIF converter

A clean, configurable Python CLI that converts and optimizes videos to GIFs using FFmpeg’s **palettegen → paletteuse** workflow.
Includes optional **size targeting** (stay under a byte budget), **frame-accurate seek**, and **VFR preservation**.

---

## Installation (from PyPI)

```bash
# 1) Have FFmpeg installed and on your PATH
#    macOS:  brew install ffmpeg
#    Ubuntu: sudo apt-get install ffmpeg
#    Windows: winget install ffmpeg  (or download from gyan.dev)
#    Verify:  ffmpeg -version

# 2) Install the CLI
pip install vi2gifx
```

> After install you’ll have a shell command named **`vi2gifx`**.

---

## Quick start

```bash
vi2gifx input.mp4 output.gif
```

Converts the whole video using a good default FPS and an adaptive palette for quality colors.

---

## Common recipes (copy-paste friendly)

> Each example includes what it does.

1. **Social-ready (smaller, crisp)**

```bash
vi2gifx in.mp4 out.gif --preset social
```

`fps=12`, `width=480` — great balance of size & clarity.

2. **Tiny footprint (docs, PRs, chats)**

```bash
vi2gifx in.mp4 out.gif --preset tiny
```

`fps=8`, `width=360`, `colors=64` — aggressively small.

3. **High-quality demo**

```bash
vi2gifx in.mp4 out.gif --preset hq
```

Higher FPS/width; larger files.

4. **Cap width (keep aspect)**

```bash
vi2gifx in.mp4 out.gif --width 480
```

5. **Fixed dimensions (may change aspect)**

```bash
vi2gifx in.mp4 out.gif --width 640 --height 360
```

6. **Lower FPS for size**

```bash
vi2gifx in.mp4 out.gif --fps 10
```

7. **Limit colors for size**

```bash
vi2gifx in.mp4 out.gif --colors 96
```

8. **Change dithering style**

```bash
vi2gifx in.mp4 out.gif --dither floyd_steinberg
```

9. **Trim a segment**

```bash
vi2gifx in.mp4 out.gif --start 3.2 --duration 6.5
```

10. **Frame-accurate trimming (avoid keyframe snap)**

```bash
vi2gifx in.mp4 out.gif --start 3.2 --duration 6.5 --seek-accurate
```

11. **Preserve original timing (VFR)**

```bash
vi2gifx in.mp4 out.gif --keep-vfr
```

Skips the `fps` filter; uses per-frame delays.

12. **Crop before scaling**

```bash
vi2gifx in.mp4 out.gif --crop 480:480:100:60 --width 480
```

13. **Deinterlace first**

```bash
vi2gifx in.mp4 out.gif --deinterlace
```

14. **Control loop count**

```bash
vi2gifx in.mp4 out.gif --loop 0   # infinite (default)
vi2gifx in.mp4 out.gif --loop 1   # play once
```

15. **Hard cap the final size (size targeting)**

```bash
vi2gifx in.mp4 out.gif --max-bytes 4_000_000
```

Iteratively shrinks **colors → fps → width** until ≤ 4 MB (respects floors).

16. **Size cap with quality floors**

```bash
vi2gifx in.mp4 out.gif --max-bytes 3_000_000 --min-colors 48 --min-fps 8 --min-width 320
```

17. **Motion-first preference**

```bash
vi2gifx in.mp4 out.gif --max-bytes 4_000_000 --min-fps 12
```

Keeps FPS higher; reduces colors/width instead.

---

## How size targeting works (brief)

When you pass `--max-bytes`, **vi2gifx** performs first-fit trials that reduce **colors → fps → width** along gentle ladders (e.g., colors 256→128→96→64, fps 12→…→6, width 720→…→min) and stops at the first result under your byte budget. If nothing fits, it writes a **best-effort** file using the floors and warns that it’s over budget. Steer trade-offs with `--min-colors`, `--min-fps`, `--min-width`.

---

## CLI reference

```text
usage: vi2gifx INPUT OUTPUT [options]

positional arguments:
  INPUT                  Input video file
  OUTPUT                 Output GIF path (e.g., out.gif)

core quality/size:
  --fps INT              Frames per second (default 12 unless --keep-vfr)
  --width INT            Scale to this width (keeps aspect unless height also set)
  --height INT           Scale to this height (keeps aspect unless width also set)
  --colors INT           Palette colors (2–256). Fewer = smaller

advanced tuning:
  --dither {none,bayer,floyd_steinberg,sierra2,sierra2_4a}
                        Dither algorithm (default: sierra2_4a)
  --stats-mode {full,diff}
                        palettegen statistics mode (default: full)

trim/crop/deinterlace:
  --start FLOAT          Start time in seconds
  --duration FLOAT       Duration in seconds
  --crop W:H:X:Y         Crop region before scaling
  --deinterlace          Apply yadif for interlaced sources

timing/mux:
  --keep-vfr             Preserve source timing (omit fps filter; per-frame delays)
  --seek-accurate        Put -ss/-t after -i for frame-accurate trimming
  --loop INT             GIF loop count (0=infinite, 1=once, ...)

presets:
  --preset {social,tiny,hq}
                        Convenience starting points you can still override

size targeting:
  --max-bytes INT        Try to keep final GIF ≤ this many bytes
  --min-fps INT          Floor when shrinking FPS (default: 6)
  --min-width INT        Floor when shrinking width (default: 240)
  --min-colors INT       Floor when shrinking colors (default: 32)
```

---

## Quality tips

* Tiny yet readable: `--fps 10 --width 360 --colors 64`
* Keep text/UI sharp: prefer lowering **colors** before **width**
* Preserve pacing: `--keep-vfr` (if viewers act weird, go back to fixed `--fps`)
* Trim aggressively: `--start` / `--duration` save more bytes than any other knob

---

## Troubleshooting

* **“ffmpeg not found”** → Install FFmpeg and ensure it’s on your PATH (`ffmpeg -version`).
* **Starts a bit early** → Use `--seek-accurate` for frame-accurate trims.
* **Choppy playback** → Increase `--fps`, or relax size floors so FPS doesn’t drop too low.
* **Persistent banding with low colors** → Try a different `--dither` (e.g., `floyd_steinberg`).

---

## License

MIT

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "vid2gifx",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "ffmpeg, gif, video, conversion, palettegen, paletteuse",
    "author": null,
    "author_email": "thecoderider <thecoderider42@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/7a/3c/80e8cfeeae60df8bb1c6e03d9f303ac7742093855b0e7f382b917eae7ecb/vid2gifx-0.1.1.tar.gz",
    "platform": null,
    "description": "# vi2gifx \u2014 FFmpeg-only video \u2192 GIF converter\r\n\r\nA clean, configurable Python CLI that converts and optimizes videos to GIFs using FFmpeg\u2019s **palettegen \u2192 paletteuse** workflow.\r\nIncludes optional **size targeting** (stay under a byte budget), **frame-accurate seek**, and **VFR preservation**.\r\n\r\n---\r\n\r\n## Installation (from PyPI)\r\n\r\n```bash\r\n# 1) Have FFmpeg installed and on your PATH\r\n#    macOS:  brew install ffmpeg\r\n#    Ubuntu: sudo apt-get install ffmpeg\r\n#    Windows: winget install ffmpeg  (or download from gyan.dev)\r\n#    Verify:  ffmpeg -version\r\n\r\n# 2) Install the CLI\r\npip install vi2gifx\r\n```\r\n\r\n> After install you\u2019ll have a shell command named **`vi2gifx`**.\r\n\r\n---\r\n\r\n## Quick start\r\n\r\n```bash\r\nvi2gifx input.mp4 output.gif\r\n```\r\n\r\nConverts the whole video using a good default FPS and an adaptive palette for quality colors.\r\n\r\n---\r\n\r\n## Common recipes (copy-paste friendly)\r\n\r\n> Each example includes what it does.\r\n\r\n1. **Social-ready (smaller, crisp)**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --preset social\r\n```\r\n\r\n`fps=12`, `width=480` \u2014 great balance of size & clarity.\r\n\r\n2. **Tiny footprint (docs, PRs, chats)**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --preset tiny\r\n```\r\n\r\n`fps=8`, `width=360`, `colors=64` \u2014 aggressively small.\r\n\r\n3. **High-quality demo**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --preset hq\r\n```\r\n\r\nHigher FPS/width; larger files.\r\n\r\n4. **Cap width (keep aspect)**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --width 480\r\n```\r\n\r\n5. **Fixed dimensions (may change aspect)**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --width 640 --height 360\r\n```\r\n\r\n6. **Lower FPS for size**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --fps 10\r\n```\r\n\r\n7. **Limit colors for size**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --colors 96\r\n```\r\n\r\n8. **Change dithering style**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --dither floyd_steinberg\r\n```\r\n\r\n9. **Trim a segment**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --start 3.2 --duration 6.5\r\n```\r\n\r\n10. **Frame-accurate trimming (avoid keyframe snap)**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --start 3.2 --duration 6.5 --seek-accurate\r\n```\r\n\r\n11. **Preserve original timing (VFR)**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --keep-vfr\r\n```\r\n\r\nSkips the `fps` filter; uses per-frame delays.\r\n\r\n12. **Crop before scaling**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --crop 480:480:100:60 --width 480\r\n```\r\n\r\n13. **Deinterlace first**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --deinterlace\r\n```\r\n\r\n14. **Control loop count**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --loop 0   # infinite (default)\r\nvi2gifx in.mp4 out.gif --loop 1   # play once\r\n```\r\n\r\n15. **Hard cap the final size (size targeting)**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --max-bytes 4_000_000\r\n```\r\n\r\nIteratively shrinks **colors \u2192 fps \u2192 width** until \u2264 4 MB (respects floors).\r\n\r\n16. **Size cap with quality floors**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --max-bytes 3_000_000 --min-colors 48 --min-fps 8 --min-width 320\r\n```\r\n\r\n17. **Motion-first preference**\r\n\r\n```bash\r\nvi2gifx in.mp4 out.gif --max-bytes 4_000_000 --min-fps 12\r\n```\r\n\r\nKeeps FPS higher; reduces colors/width instead.\r\n\r\n---\r\n\r\n## How size targeting works (brief)\r\n\r\nWhen you pass `--max-bytes`, **vi2gifx** performs first-fit trials that reduce **colors \u2192 fps \u2192 width** along gentle ladders (e.g., colors 256\u2192128\u219296\u219264, fps 12\u2192\u2026\u21926, width 720\u2192\u2026\u2192min) and stops at the first result under your byte budget. If nothing fits, it writes a **best-effort** file using the floors and warns that it\u2019s over budget. Steer trade-offs with `--min-colors`, `--min-fps`, `--min-width`.\r\n\r\n---\r\n\r\n## CLI reference\r\n\r\n```text\r\nusage: vi2gifx INPUT OUTPUT [options]\r\n\r\npositional arguments:\r\n  INPUT                  Input video file\r\n  OUTPUT                 Output GIF path (e.g., out.gif)\r\n\r\ncore quality/size:\r\n  --fps INT              Frames per second (default 12 unless --keep-vfr)\r\n  --width INT            Scale to this width (keeps aspect unless height also set)\r\n  --height INT           Scale to this height (keeps aspect unless width also set)\r\n  --colors INT           Palette colors (2\u2013256). Fewer = smaller\r\n\r\nadvanced tuning:\r\n  --dither {none,bayer,floyd_steinberg,sierra2,sierra2_4a}\r\n                        Dither algorithm (default: sierra2_4a)\r\n  --stats-mode {full,diff}\r\n                        palettegen statistics mode (default: full)\r\n\r\ntrim/crop/deinterlace:\r\n  --start FLOAT          Start time in seconds\r\n  --duration FLOAT       Duration in seconds\r\n  --crop W:H:X:Y         Crop region before scaling\r\n  --deinterlace          Apply yadif for interlaced sources\r\n\r\ntiming/mux:\r\n  --keep-vfr             Preserve source timing (omit fps filter; per-frame delays)\r\n  --seek-accurate        Put -ss/-t after -i for frame-accurate trimming\r\n  --loop INT             GIF loop count (0=infinite, 1=once, ...)\r\n\r\npresets:\r\n  --preset {social,tiny,hq}\r\n                        Convenience starting points you can still override\r\n\r\nsize targeting:\r\n  --max-bytes INT        Try to keep final GIF \u2264 this many bytes\r\n  --min-fps INT          Floor when shrinking FPS (default: 6)\r\n  --min-width INT        Floor when shrinking width (default: 240)\r\n  --min-colors INT       Floor when shrinking colors (default: 32)\r\n```\r\n\r\n---\r\n\r\n## Quality tips\r\n\r\n* Tiny yet readable: `--fps 10 --width 360 --colors 64`\r\n* Keep text/UI sharp: prefer lowering **colors** before **width**\r\n* Preserve pacing: `--keep-vfr` (if viewers act weird, go back to fixed `--fps`)\r\n* Trim aggressively: `--start` / `--duration` save more bytes than any other knob\r\n\r\n---\r\n\r\n## Troubleshooting\r\n\r\n* **\u201cffmpeg not found\u201d** \u2192 Install FFmpeg and ensure it\u2019s on your PATH (`ffmpeg -version`).\r\n* **Starts a bit early** \u2192 Use `--seek-accurate` for frame-accurate trims.\r\n* **Choppy playback** \u2192 Increase `--fps`, or relax size floors so FPS doesn\u2019t drop too low.\r\n* **Persistent banding with low colors** \u2192 Try a different `--dither` (e.g., `floyd_steinberg`).\r\n\r\n---\r\n\r\n## License\r\n\r\nMIT\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "FFmpeg-only video to GIF converter with palettegen/paletteuse and size targeting.",
    "version": "0.1.1",
    "project_urls": {
        "Homepage": "https://github.com/the-code-rider/vid2gif",
        "Issues": "https://github.com/the-code-rider/video2gif/issues"
    },
    "split_keywords": [
        "ffmpeg",
        " gif",
        " video",
        " conversion",
        " palettegen",
        " paletteuse"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "df94ec35a9e69cb2a4b91b2f22a19049587f66f8e596668184b553db579e1507",
                "md5": "e5c42b01a7cda19d4ff7889dce04a9cc",
                "sha256": "eb438e1f4f0ce3a27ab0abbce6e1db747328cc405c131b4121a787204032352d"
            },
            "downloads": -1,
            "filename": "vid2gifx-0.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e5c42b01a7cda19d4ff7889dce04a9cc",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 8625,
            "upload_time": "2025-10-10T14:26:41",
            "upload_time_iso_8601": "2025-10-10T14:26:41.119077Z",
            "url": "https://files.pythonhosted.org/packages/df/94/ec35a9e69cb2a4b91b2f22a19049587f66f8e596668184b553db579e1507/vid2gifx-0.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "7a3c80e8cfeeae60df8bb1c6e03d9f303ac7742093855b0e7f382b917eae7ecb",
                "md5": "dcd244c65a73d8d83ee3c9b6cfdee789",
                "sha256": "0a24b1ab2bc5c9aa9668fa30053d4465a702255859cbb93184f90b3975f39588"
            },
            "downloads": -1,
            "filename": "vid2gifx-0.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "dcd244c65a73d8d83ee3c9b6cfdee789",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 10610,
            "upload_time": "2025-10-10T14:26:42",
            "upload_time_iso_8601": "2025-10-10T14:26:42.032643Z",
            "url": "https://files.pythonhosted.org/packages/7a/3c/80e8cfeeae60df8bb1c6e03d9f303ac7742093855b0e7f382b917eae7ecb/vid2gifx-0.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-10 14:26:42",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "the-code-rider",
    "github_project": "vid2gif",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "vid2gifx"
}
        
Elapsed time: 2.07160s