vidio-cli 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vidio_cli-0.1.0/.gitattributes +1 -0
- vidio_cli-0.1.0/.github/workflows/ci.yml +65 -0
- vidio_cli-0.1.0/.github/workflows/publish.yml +72 -0
- vidio_cli-0.1.0/.gitignore +55 -0
- vidio_cli-0.1.0/AGENTS.md +143 -0
- vidio_cli-0.1.0/CHANGELOG.md +20 -0
- vidio_cli-0.1.0/LICENSE +21 -0
- vidio_cli-0.1.0/PKG-INFO +238 -0
- vidio_cli-0.1.0/README.md +210 -0
- vidio_cli-0.1.0/pyproject.toml +53 -0
- vidio_cli-0.1.0/src/vidio_cli/__init__.py +3 -0
- vidio_cli-0.1.0/src/vidio_cli/cli.py +62 -0
- vidio_cli-0.1.0/src/vidio_cli/commands/__init__.py +36 -0
- vidio_cli-0.1.0/src/vidio_cli/commands/concat.py +103 -0
- vidio_cli-0.1.0/src/vidio_cli/commands/crop.py +391 -0
- vidio_cli-0.1.0/src/vidio_cli/commands/grid.py +258 -0
- vidio_cli-0.1.0/src/vidio_cli/commands/info.py +244 -0
- vidio_cli-0.1.0/src/vidio_cli/commands/list.py +316 -0
- vidio_cli-0.1.0/src/vidio_cli/commands/resize.py +220 -0
- vidio_cli-0.1.0/src/vidio_cli/commands/to_gif.py +351 -0
- vidio_cli-0.1.0/src/vidio_cli/commands/trim.py +133 -0
- vidio_cli-0.1.0/src/vidio_cli/config.py +25 -0
- vidio_cli-0.1.0/src/vidio_cli/ffmpeg_utils.py +197 -0
- vidio_cli-0.1.0/tests/assets/sample.mp4 +3 -0
- vidio_cli-0.1.0/tests/conftest.py +18 -0
- vidio_cli-0.1.0/tests/test_cli.py +31 -0
- vidio_cli-0.1.0/tests/test_concat.py +65 -0
- vidio_cli-0.1.0/tests/test_crop.py +664 -0
- vidio_cli-0.1.0/tests/test_grid.py +108 -0
- vidio_cli-0.1.0/tests/test_info.py +56 -0
- vidio_cli-0.1.0/tests/test_list.py +112 -0
- vidio_cli-0.1.0/tests/test_resize.py +146 -0
- vidio_cli-0.1.0/tests/test_to_gif.py +192 -0
- vidio_cli-0.1.0/tests/test_trim.py +110 -0
- vidio_cli-0.1.0/uv.lock +378 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
fast-tests:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- name: Checkout
|
|
16
|
+
uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Setup Python
|
|
19
|
+
uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: ${{ matrix.python-version }}
|
|
22
|
+
|
|
23
|
+
- name: Install uv
|
|
24
|
+
uses: astral-sh/setup-uv@v5
|
|
25
|
+
with:
|
|
26
|
+
enable-cache: true
|
|
27
|
+
|
|
28
|
+
- name: Sync dependencies
|
|
29
|
+
run: uv sync --group dev
|
|
30
|
+
|
|
31
|
+
- name: Lint
|
|
32
|
+
run: uv run ruff check .
|
|
33
|
+
|
|
34
|
+
- name: Fast tests (non-integration)
|
|
35
|
+
run: uv run pytest -q -m "not integration"
|
|
36
|
+
|
|
37
|
+
integration-tests:
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
|
|
40
|
+
steps:
|
|
41
|
+
- name: Checkout
|
|
42
|
+
uses: actions/checkout@v4
|
|
43
|
+
with:
|
|
44
|
+
lfs: true
|
|
45
|
+
|
|
46
|
+
- name: Setup Python
|
|
47
|
+
uses: actions/setup-python@v5
|
|
48
|
+
with:
|
|
49
|
+
python-version: "3.11"
|
|
50
|
+
|
|
51
|
+
- name: Install uv
|
|
52
|
+
uses: astral-sh/setup-uv@v5
|
|
53
|
+
with:
|
|
54
|
+
enable-cache: true
|
|
55
|
+
|
|
56
|
+
- name: Install ffmpeg
|
|
57
|
+
run: |
|
|
58
|
+
sudo apt-get update
|
|
59
|
+
sudo apt-get install -y ffmpeg
|
|
60
|
+
|
|
61
|
+
- name: Sync dependencies
|
|
62
|
+
run: uv sync --group dev
|
|
63
|
+
|
|
64
|
+
- name: Integration tests
|
|
65
|
+
run: uv run pytest -q -m "integration"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
repository:
|
|
9
|
+
description: "Package repository target"
|
|
10
|
+
required: true
|
|
11
|
+
default: testpypi
|
|
12
|
+
type: choice
|
|
13
|
+
options:
|
|
14
|
+
- testpypi
|
|
15
|
+
- pypi
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- name: Checkout
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Setup Python
|
|
25
|
+
uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.12"
|
|
28
|
+
|
|
29
|
+
- name: Install uv
|
|
30
|
+
uses: astral-sh/setup-uv@v5
|
|
31
|
+
with:
|
|
32
|
+
enable-cache: true
|
|
33
|
+
|
|
34
|
+
- name: Build distributions
|
|
35
|
+
run: uv build
|
|
36
|
+
|
|
37
|
+
- name: Validate distributions
|
|
38
|
+
run: |
|
|
39
|
+
python -m pip install --upgrade pip twine
|
|
40
|
+
python -m twine check dist/*
|
|
41
|
+
|
|
42
|
+
- name: Upload dist artifacts
|
|
43
|
+
uses: actions/upload-artifact@v4
|
|
44
|
+
with:
|
|
45
|
+
name: dist
|
|
46
|
+
path: dist/
|
|
47
|
+
|
|
48
|
+
publish:
|
|
49
|
+
needs: build
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
permissions:
|
|
52
|
+
id-token: write
|
|
53
|
+
environment:
|
|
54
|
+
name: pypi
|
|
55
|
+
env:
|
|
56
|
+
TARGET_REPOSITORY: ${{ github.event_name == 'release' && 'pypi' || github.event.inputs.repository }}
|
|
57
|
+
steps:
|
|
58
|
+
- name: Download dist artifacts
|
|
59
|
+
uses: actions/download-artifact@v4
|
|
60
|
+
with:
|
|
61
|
+
name: dist
|
|
62
|
+
path: dist/
|
|
63
|
+
|
|
64
|
+
- name: Publish to TestPyPI
|
|
65
|
+
if: env.TARGET_REPOSITORY == 'testpypi'
|
|
66
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
67
|
+
with:
|
|
68
|
+
repository-url: https://test.pypi.org/legacy/
|
|
69
|
+
|
|
70
|
+
- name: Publish to PyPI
|
|
71
|
+
if: env.TARGET_REPOSITORY == 'pypi'
|
|
72
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
.python-version
|
|
23
|
+
|
|
24
|
+
# IDE - PyCharm
|
|
25
|
+
.idea/
|
|
26
|
+
*.iws
|
|
27
|
+
*.iml
|
|
28
|
+
*.ipr
|
|
29
|
+
|
|
30
|
+
# IDE - VSCode
|
|
31
|
+
.vscode/
|
|
32
|
+
*.code-workspace
|
|
33
|
+
|
|
34
|
+
# Virtual environments
|
|
35
|
+
venv/
|
|
36
|
+
env/
|
|
37
|
+
ENV/
|
|
38
|
+
.venv/
|
|
39
|
+
.env/
|
|
40
|
+
|
|
41
|
+
# Testing
|
|
42
|
+
.coverage
|
|
43
|
+
htmlcov/
|
|
44
|
+
.pytest_cache/
|
|
45
|
+
.tox/
|
|
46
|
+
.nox/
|
|
47
|
+
|
|
48
|
+
# OS specific
|
|
49
|
+
.DS_Store
|
|
50
|
+
Thumbs.db
|
|
51
|
+
|
|
52
|
+
# Temporary files
|
|
53
|
+
tmp/
|
|
54
|
+
|
|
55
|
+
tasks.md
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
`vidio-cli` is a Python-based CLI tool that provides a simple, user-friendly wrapper around ffmpeg for common video operations. It uses Typer for CLI framework and Rich for terminal output formatting.
|
|
8
|
+
|
|
9
|
+
## Development Setup
|
|
10
|
+
|
|
11
|
+
This project uses `uv` for package management:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Install dependencies
|
|
15
|
+
uv sync
|
|
16
|
+
|
|
17
|
+
# Install with dev dependencies
|
|
18
|
+
uv sync --group dev
|
|
19
|
+
|
|
20
|
+
# Install in development mode (editable install)
|
|
21
|
+
uv pip install -e .
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Running Commands
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Run the CLI during development
|
|
28
|
+
uv run vidio <command>
|
|
29
|
+
|
|
30
|
+
# Or after installing in dev mode
|
|
31
|
+
vidio <command>
|
|
32
|
+
|
|
33
|
+
# Run tests
|
|
34
|
+
uv run pytest
|
|
35
|
+
|
|
36
|
+
# Run tests with verbose output
|
|
37
|
+
uv run pytest -v
|
|
38
|
+
|
|
39
|
+
# Run specific test file
|
|
40
|
+
uv run pytest tests/test_concat.py
|
|
41
|
+
|
|
42
|
+
# Lint with ruff
|
|
43
|
+
uv run ruff check .
|
|
44
|
+
|
|
45
|
+
# Format with ruff
|
|
46
|
+
uv run ruff format .
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Architecture
|
|
50
|
+
|
|
51
|
+
### Command Registration System
|
|
52
|
+
|
|
53
|
+
Commands are **dynamically discovered and registered** at startup via `src/vidio_cli/commands/__init__.py`:
|
|
54
|
+
|
|
55
|
+
1. The `get_commands()` function scans the `commands/` directory for Python modules
|
|
56
|
+
2. Each module with a `register()` function is treated as a command
|
|
57
|
+
3. Module names (with underscores) become command names (with hyphens), e.g., `to_gif.py` → `to-gif`
|
|
58
|
+
4. Commands are registered with the main Typer app in `src/vidio_cli/cli.py`
|
|
59
|
+
|
|
60
|
+
### Command Module Pattern
|
|
61
|
+
|
|
62
|
+
Each command module follows this structure:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
def register(app: typer.Typer) -> None:
|
|
66
|
+
"""Register the command with the Typer app."""
|
|
67
|
+
app.command(no_args_is_help=True)(command_function)
|
|
68
|
+
|
|
69
|
+
def command_function(
|
|
70
|
+
ctx: typer.Context,
|
|
71
|
+
# ... command arguments and options
|
|
72
|
+
) -> None:
|
|
73
|
+
"""Command implementation."""
|
|
74
|
+
verbose = ctx.obj.get("VERBOSE", False) if ctx.obj else False
|
|
75
|
+
# ... command logic using ffmpeg_utils
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Shared Utilities
|
|
79
|
+
|
|
80
|
+
- **`ffmpeg_utils.py`**: Core utilities for running ffmpeg/ffprobe commands
|
|
81
|
+
- `ensure_ffmpeg()`: Verifies ffmpeg is installed
|
|
82
|
+
- `run_ffmpeg()`: Executes ffmpeg commands with error handling
|
|
83
|
+
- `get_video_info()`: Retrieves video metadata using ffprobe
|
|
84
|
+
- `check_output_file()`: Handles output file overwrite checks
|
|
85
|
+
|
|
86
|
+
- **`config.py`**: Default settings for video encoding (codec, quality, preset)
|
|
87
|
+
|
|
88
|
+
### Global Context
|
|
89
|
+
|
|
90
|
+
The verbose flag (`--verbose` / `-v`) is stored in the Typer context object and accessed by commands via `ctx.obj.get("VERBOSE", False)`.
|
|
91
|
+
|
|
92
|
+
## Adding a New Command
|
|
93
|
+
|
|
94
|
+
1. Create `src/vidio_cli/commands/<command_name>.py`
|
|
95
|
+
2. Implement the `register(app: typer.Typer)` function
|
|
96
|
+
3. Implement the command function with appropriate arguments/options
|
|
97
|
+
4. Use `ffmpeg_utils` functions for running ffmpeg operations
|
|
98
|
+
5. Access verbose flag from context: `verbose = ctx.obj.get("VERBOSE", False)`
|
|
99
|
+
6. Create corresponding test file: `tests/test_<command_name>.py`
|
|
100
|
+
7. The command will be automatically discovered and registered (no manual registration needed)
|
|
101
|
+
|
|
102
|
+
## Testing
|
|
103
|
+
|
|
104
|
+
Tests use pytest and should cover:
|
|
105
|
+
- Command registration
|
|
106
|
+
- Argument/option validation
|
|
107
|
+
- ffmpeg command generation (can mock `run_ffmpeg`)
|
|
108
|
+
- Error handling
|
|
109
|
+
|
|
110
|
+
Test videos can be placed in `tests/assets/` if needed.
|
|
111
|
+
|
|
112
|
+
## Dependencies
|
|
113
|
+
|
|
114
|
+
- **typer**: CLI framework with type annotations
|
|
115
|
+
- **rich**: Terminal formatting and colors
|
|
116
|
+
- **ffmpeg**: External dependency (must be in PATH)
|
|
117
|
+
|
|
118
|
+
## PyPI Release Workflow
|
|
119
|
+
|
|
120
|
+
Use this release flow for `vidio-cli`:
|
|
121
|
+
|
|
122
|
+
1. Update version in `pyproject.toml`.
|
|
123
|
+
2. Update `CHANGELOG.md` with the release date and notable changes.
|
|
124
|
+
3. Run quality checks locally:
|
|
125
|
+
- `uv run ruff check .`
|
|
126
|
+
- `uv run pytest -q`
|
|
127
|
+
4. Build and validate the distribution:
|
|
128
|
+
- `uv build`
|
|
129
|
+
- `python -m twine check dist/*`
|
|
130
|
+
5. Commit and tag:
|
|
131
|
+
- `git tag v<version>`
|
|
132
|
+
- `git push origin main --tags`
|
|
133
|
+
6. Publish:
|
|
134
|
+
- Preferred: create a GitHub Release from the version tag; this triggers `.github/workflows/publish.yml` and publishes to PyPI.
|
|
135
|
+
- Optional: run the publish workflow manually with `workflow_dispatch` to publish to TestPyPI first.
|
|
136
|
+
|
|
137
|
+
### Trusted Publishing Setup
|
|
138
|
+
|
|
139
|
+
The project should use PyPI Trusted Publishing with GitHub Actions:
|
|
140
|
+
|
|
141
|
+
- In PyPI/TestPyPI project settings, add a trusted publisher for this repository.
|
|
142
|
+
- Point it to workflow file `.github/workflows/publish.yml`.
|
|
143
|
+
- Restrict to the `main` branch and/or release tags as needed.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## 0.1.0 - 2026-02-06
|
|
6
|
+
|
|
7
|
+
First public release of `vidio-cli`.
|
|
8
|
+
|
|
9
|
+
- Added core commands for everyday video workflows:
|
|
10
|
+
- `list` / `ls`
|
|
11
|
+
- `info`
|
|
12
|
+
- `trim`
|
|
13
|
+
- `resize`
|
|
14
|
+
- `crop`
|
|
15
|
+
- `concat`
|
|
16
|
+
- `grid`
|
|
17
|
+
- `to-gif`
|
|
18
|
+
- Added dynamic command discovery and registration.
|
|
19
|
+
- Added test coverage for command behavior and output handling.
|
|
20
|
+
- Added distribution build support for wheel and source tarball.
|
vidio_cli-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Matan Ben-Yosef
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
vidio_cli-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vidio-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A simple and easy-to-use ffmpeg wrapper for common video operations
|
|
5
|
+
Project-URL: Homepage, https://github.com/matanb/vidio-cli
|
|
6
|
+
Project-URL: Repository, https://github.com/matanb/vidio-cli
|
|
7
|
+
Project-URL: Issues, https://github.com/matanb/vidio-cli/issues
|
|
8
|
+
Author-email: Matan Ben-Yosef <matan.ben.yosef@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: cli,ffmpeg,gif,media,video
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Multimedia :: Video
|
|
23
|
+
Classifier: Topic :: Utilities
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: rich>=13.5.0
|
|
26
|
+
Requires-Dist: typer>=0.9.0
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# vidio-cli
|
|
30
|
+
|
|
31
|
+
A simple and easy-to-use ffmpeg wrapper for common video operations.
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- **Stupidly Easy:** Simple CLI commands for common video operations.
|
|
36
|
+
- **Powerful Defaults:** Sensible defaults make it work great out of the box.
|
|
37
|
+
- **Focused v1 Scope:** Core commands people use repeatedly, without feature bloat.
|
|
38
|
+
|
|
39
|
+
## Requirements
|
|
40
|
+
|
|
41
|
+
- Python 3.10+
|
|
42
|
+
- ffmpeg (must be installed and in your PATH)
|
|
43
|
+
|
|
44
|
+
## v1 Command Scope
|
|
45
|
+
|
|
46
|
+
`vidio-cli` 0.1.0 intentionally focuses on practical, high-frequency tasks:
|
|
47
|
+
|
|
48
|
+
- `list` / `ls`: find video files quickly
|
|
49
|
+
- `info`: inspect metadata and streams
|
|
50
|
+
- `trim`: cut clips by time range
|
|
51
|
+
- `resize`: scale for delivery targets
|
|
52
|
+
- `crop`: convert to target aspect ratios
|
|
53
|
+
- `concat`: place videos side-by-side or stacked
|
|
54
|
+
- `grid`: build multi-video collages
|
|
55
|
+
- `to-gif`: convert clips to GIF with good defaults
|
|
56
|
+
|
|
57
|
+
Commands that are less consistently useful (for example, niche one-off transforms) are deferred to later releases.
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Using pip
|
|
63
|
+
pip install vidio-cli
|
|
64
|
+
|
|
65
|
+
# Using uv
|
|
66
|
+
uv pip install vidio-cli
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Usage
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Get help
|
|
73
|
+
vidio --help
|
|
74
|
+
|
|
75
|
+
# Get help for a specific command
|
|
76
|
+
vidio concat --help
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Concatenate Videos
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Concatenate videos horizontally
|
|
83
|
+
vidio concat video1.mp4 video2.mp4 output.mp4
|
|
84
|
+
|
|
85
|
+
# Concatenate videos vertically
|
|
86
|
+
vidio concat video1.mp4 video2.mp4 output.mp4 --vertical
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### List Video Files
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# List videos in current directory (ls-style output)
|
|
93
|
+
vidio list
|
|
94
|
+
# or use the shorter alias
|
|
95
|
+
vidio ls
|
|
96
|
+
|
|
97
|
+
# List with detailed information (duration, resolution, codec)
|
|
98
|
+
vidio ls --list
|
|
99
|
+
|
|
100
|
+
# Search recursively in subdirectories
|
|
101
|
+
vidio ls --recursive
|
|
102
|
+
|
|
103
|
+
# Use table format instead of ls-style
|
|
104
|
+
vidio ls --table
|
|
105
|
+
|
|
106
|
+
# Get JSON output for scripting
|
|
107
|
+
vidio ls --json
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Video Information
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Display detailed metadata about a video file
|
|
114
|
+
vidio info video.mp4
|
|
115
|
+
|
|
116
|
+
# Get machine-readable JSON output
|
|
117
|
+
vidio info video.mp4 --json
|
|
118
|
+
|
|
119
|
+
# Calculate exact frame count (slower but accurate)
|
|
120
|
+
vidio info video.mp4 --exact-frames
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Create Video Grids
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Arrange videos in a 2x2 grid (auto-calculated)
|
|
127
|
+
vidio grid video1.mp4 video2.mp4 video3.mp4 video4.mp4 output.mp4
|
|
128
|
+
|
|
129
|
+
# Specify grid dimensions
|
|
130
|
+
vidio grid video1.mp4 video2.mp4 video3.mp4 video4.mp4 output.mp4 --rows 2 --cols 2
|
|
131
|
+
|
|
132
|
+
# Control cell size and add padding
|
|
133
|
+
vidio grid video1.mp4 video2.mp4 video3.mp4 video4.mp4 output.mp4 --width 640 --height 360 --padding 10
|
|
134
|
+
|
|
135
|
+
# Change background color
|
|
136
|
+
vidio grid video1.mp4 video2.mp4 video3.mp4 video4.mp4 output.mp4 --background white
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Trim Videos
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Trim from 30 seconds to 90 seconds
|
|
143
|
+
vidio trim input.mp4 output.mp4 --start 30 --end 90
|
|
144
|
+
|
|
145
|
+
# Trim from 1:30 for 45 seconds duration
|
|
146
|
+
vidio trim input.mp4 output.mp4 --start 1:30 --duration 45
|
|
147
|
+
|
|
148
|
+
# Trim from beginning to 2:15
|
|
149
|
+
vidio trim input.mp4 output.mp4 --end 2:15
|
|
150
|
+
|
|
151
|
+
# Trim using different time formats
|
|
152
|
+
vidio trim input.mp4 output.mp4 --start 0:01:30 --end 0:02:45
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Resize Videos
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Resize to specific dimensions (maintains aspect ratio)
|
|
159
|
+
vidio resize input.mp4 output.mp4 --width 1920 --height 1080
|
|
160
|
+
|
|
161
|
+
# Scale by percentage
|
|
162
|
+
vidio resize input.mp4 output.mp4 --scale 0.5 # 50% of original size
|
|
163
|
+
|
|
164
|
+
# Resize width only (height auto-calculated)
|
|
165
|
+
vidio resize input.mp4 output.mp4 --width 1280
|
|
166
|
+
|
|
167
|
+
# Resize height only (width auto-calculated)
|
|
168
|
+
vidio resize input.mp4 output.mp4 --height 720
|
|
169
|
+
|
|
170
|
+
# Force exact dimensions (may distort)
|
|
171
|
+
vidio resize input.mp4 output.mp4 -w 1920 -h 1080 --force-aspect
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Convert to GIF
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
# Basic conversion with optimized palette
|
|
178
|
+
vidio to-gif video.mp4 output.gif
|
|
179
|
+
|
|
180
|
+
# High quality with custom frame rate
|
|
181
|
+
vidio to-gif video.mp4 output.gif --fps 15 --quality high
|
|
182
|
+
|
|
183
|
+
# Small file size for web
|
|
184
|
+
vidio to-gif video.mp4 output.gif --scale 0.3 --fps 8 --quality low
|
|
185
|
+
|
|
186
|
+
# Convert specific time range
|
|
187
|
+
vidio to-gif video.mp4 output.gif --start 10 --duration 5
|
|
188
|
+
|
|
189
|
+
# Custom width with different dithering
|
|
190
|
+
vidio to-gif video.mp4 output.gif --width 800 --dither bayer
|
|
191
|
+
|
|
192
|
+
# Fast conversion (skip optimization)
|
|
193
|
+
vidio to-gif video.mp4 output.gif --no-optimize
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Crop Videos
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
# Crop to center square (perfect for Instagram)
|
|
200
|
+
vidio crop input.mp4 output.mp4 --preset center-square
|
|
201
|
+
|
|
202
|
+
# Crop to 16:9 aspect ratio
|
|
203
|
+
vidio crop input.mp4 output.mp4 --preset 16:9
|
|
204
|
+
|
|
205
|
+
# Crop to 9:16 aspect ratio (vertical/portrait)
|
|
206
|
+
vidio crop input.mp4 output.mp4 --preset 9:16
|
|
207
|
+
|
|
208
|
+
# Crop to 4:3 aspect ratio
|
|
209
|
+
vidio crop input.mp4 output.mp4 --preset 4:3
|
|
210
|
+
|
|
211
|
+
# Custom crop region (centered)
|
|
212
|
+
vidio crop input.mp4 output.mp4 --width 1280 --height 720
|
|
213
|
+
|
|
214
|
+
# Custom crop with specific position
|
|
215
|
+
vidio crop input.mp4 output.mp4 -w 1280 -h 720 --x 100 --y 50
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
## Development
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
# Clone the repo
|
|
223
|
+
git clone https://github.com/matanb/vidio-cli.git
|
|
224
|
+
cd vidio-cli
|
|
225
|
+
|
|
226
|
+
# Install dependencies
|
|
227
|
+
uv sync --group dev
|
|
228
|
+
|
|
229
|
+
# Run tests
|
|
230
|
+
uv run pytest -q
|
|
231
|
+
|
|
232
|
+
# Run lint
|
|
233
|
+
uv run ruff check .
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## License
|
|
237
|
+
|
|
238
|
+
MIT
|