Metadata-Version: 2.4
Name: pwb-wrapper-for-simpler-uploading-to-commons
Version: 1.8.0
Summary: CLI wrapper around Pywikibot for simpler Wikimedia Commons uploads
Author: Vitaly Zdanevich
License-Expression: MIT
Project-URL: Homepage, https://gitlab.com/vitaly-zdanevich/pwb_wrapper_for_simpler_uploading_to_commons
Project-URL: Repository, https://gitlab.com/vitaly-zdanevich/pwb_wrapper_for_simpler_uploading_to_commons
Project-URL: Documentation, https://gitlab.com/vitaly-zdanevich/pwb_wrapper_for_simpler_uploading_to_commons
Project-URL: Issues, https://gitlab.com/vitaly-zdanevich/pwb_wrapper_for_simpler_uploading_to_commons/-/issues
Keywords: wikimedia,commons,pywikibot,upload,cli
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pywikibot
Provides-Extra: autocomplete
Requires-Dist: argcomplete; extra == "autocomplete"
Dynamic: license-file

It is a wrapper around [pywikibot](https://github.com/wikimedia/pywikibot) to make uploading to [Wikimedia Commons](https://commons.wikimedia.org/wiki/Main_Page) from CLI simpler.

![screenshot](screenshot.webp)

## Install

From [PyPI](https://pypi.org/project/pwb-wrapper-for-simpler-uploading-to-commons/):

```bash
pip install pwb-wrapper-for-simpler-uploading-to-commons
```

With shell autocompletion support:

```bash
pip install 'pwb-wrapper-for-simpler-uploading-to-commons[autocomplete]'
```

## Usage

Installed CLI command:

```bash
pwb-upload --file my.jpg --source https://example.com --license 'PD-old' --category 'Sunsets in Batumi' --date '2025-12-27' --desc 'A beautiful sunset from the beach' --target myrenamed.jpg
```

For multiple categories, repeat `--category`:

```bash
pwb-upload --file my.jpg --category 'Sunsets in Batumi' --category 'Evening in Georgia' --date '2025-12-27'
```

Use folder name in category:

```bash
pwb-upload --category "Kaspiy ${PWD##*/}" --license 'PD-scan|PD-old-assumed-expired' --source https://dspace.nplg.gov.ge/handle/1234/387883 --dateParse
```

Category and prefix is the same:
```bash
S='xxx' pwb-upload --category "$S" --prefix "$S "
```

Default `source` is `{{own}}`.

Default `license` is `cc-by-4.0`.

`--author` for example [[User:Globustut|Globustut]]

`--date` in format `YYYY-MM-DD`.

`--dateParse` extracts year from a filename (`1xxx` or `2xxx`).

`--date` and `--dateParse` are mutually exclusive.

`--target` (file name on Commons) is optional.

`--prefix` (prefix for file name on Commons) is optional.

`--i` lets you start from a specific index.

`--recursive` includes files from subfolders when no file is specified.

You can upload with minimal arguments:

```bash
pwb-upload --file my.jpg --category 'Sunsets in Batumi' --date '2025-12-27'
```

Or pass the file as positional argument:

```bash
pwb-upload my.jpg --category 'Sunsets in Batumi' --date '2025-12-27'
```

Or upload without `category`, `date`, and `dateParse` (set them later on Commons):

```bash
pwb-upload my.jpg
```

If no file is specified, it uploads eligible files from the current folder (no subfolders by default):

```bash
pwb-upload --category 'My category' --author '[[User:Globustut|Globustut]]' --license 'self|CC-BY-4.0|author=Globustut' --date 2005
```

To include subfolders:

```bash
pwb-upload --recursive
```

For local development (without installation), you can still run:

```bash
./upload.py --file my.jpg
```

Author: for the current user use `me`.

### MP4 videos

MP4 inputs are automatically converted with [FFmpeg](https://ffmpeg.org/download.html) to WebM with AV1 video and Opus audio before uploading:

```bash
pwb-upload --category 'Bagrati Cathedral after restoration' Bagrati-Cathedral2026september-cross-ans-walking-man.mp4
```

This uploads `Bagrati-Cathedral2026september-cross-ans-walking-man.webm`. Conversion also applies to `--file`, folder uploads, and `--recursive`, including uppercase `.MP4` extensions. A custom `--target` gets a `.webm` extension, and `--prefix` works as usual.

Install an FFmpeg build with the [`libsvtav1`](https://ffmpeg.org/ffmpeg-codecs.html#libsvtav1) and [`libopus`](https://ffmpeg.org/ffmpeg-codecs.html#libopus-1) encoders and ensure `ffmpeg` is on `PATH`. Check availability with `ffmpeg -hide_banner -encoders`. Other file formats do not require FFmpeg.

Encoding uses AV1 CRF 28, preset 6, 10-bit YUV 4:2:0, and Opus at 160 kb/s and 48 kHz. The first video stream and optional first audio stream are selected; silent videos work too. Resolution and frame rate are not intentionally reduced. The terminal shows an updating encoding progress line, warnings, and errors; FFmpeg metadata and SVT-AV1 startup and memory reports are suppressed. These codecs are supported by [Commons video formats](https://commons.wikimedia.org/wiki/Commons:Video#Video_formats).

The original MP4 and any existing neighboring WebM remain untouched. The converted file is stored in the system temporary directory and removed when the upload finishes, fails, or is interrupted. Set `TMPDIR` to a directory with enough free space for large videos. Upload retries reuse the conversion; a new invocation encodes again. Conversion failures stop before uploading and exit with an error.

As a temporary workaround for an [SVT-AV1 3.1.2 encoder hang](https://gitlab.com/AOMediaCodec/SVT-AV1/-/issues/2318), FFmpeg is stopped if its frame count, media timestamp, and output byte count do not advance for 60 seconds. The script discards the partial output and retries conversion once with fewer encoder workers (`-svtav1-params lp=1`), retaining the codec and quality settings. This retry can encode more slowly. A second stall exits with an error instead of uploading incomplete media. Encoding can run longer than 60 seconds while progress continues. Remove this workaround once a fixed encoder version is required and verified.

## Autocompletion

Enable completion for the installed command:

```bash
eval "$(register-python-argcomplete pwb-upload)"
```

## Release to PyPI

Release scripts in this repository:

- `release_minor.sh` bumps `x.y.z` -> `x.(y+1).0`
- `release_patch.sh` bumps `x.y.z` -> `x.y.(z+1)`
- `release-added.sh` uses already staged files and already bumped version in `pyproject.toml` (no `git add .`)

Call them from git (one-time setup):

```bash
git config alias.release-minor '!f() { repo=$(git rev-parse --show-toplevel) && bash "$repo/release_minor.sh" "$@"; }; f'
git config alias.release-patch '!f() { repo=$(git rev-parse --show-toplevel) && bash "$repo/release_patch.sh" "$@"; }; f'
git config alias.release-added '!f() { repo=$(git rev-parse --show-toplevel) && bash "$repo/release-added.sh" "$@"; }; f'
```

Then run:

```bash
git release-minor 'Release message'
git release-patch 'Release message'
git release-added 'Release message'
```

Build distribution files:

```bash
python3 -m build
```

Upload to TestPyPI:

```bash
python3 -m twine upload --repository testpypi dist/*
```

Upload to PyPI:

```bash
python3 -m twine upload dist/*
```

Wikidata item about this tool https://www.wikidata.org/wiki/Q137601716

Commons category https://commons.wikimedia.org/wiki/Category:Uploaded_with_pwb_wrapper_script_by_Vitaly_Zdanevich

SonarCloud https://sonarcloud.io/project/overview?id=vitaly-zdanevich_pwb_wrapper_for_simpler_uploading_to_commons

## See also

My another Python script for [uploading to Commons from gThumb](https://gitlab.com/vitaly_zdanevich_wikimedia_commons/upload_to_commons_with_categories_from_iptc)

My [web extension for uploading to Commons](https://gitlab.com/vitaly-zdanevich-extensions/uploading-to-wikimedia-commons)

[All upload tools](https://commons.wikimedia.org/wiki/Commons:Upload_tools)

[CLI upload tools](https://commons.wikimedia.org/wiki/Commons:Command-line_upload)

This tool is mentioned at my blog post https://diff.wikimedia.org/2026/04/09/preserve-old-public-domain-newspapers-and-books-from-archive-websites/
