ffmpeg-update 3.1.0__tar.gz → 3.1.2__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.
- {ffmpeg_update-3.1.0 → ffmpeg_update-3.1.2}/PKG-INFO +22 -42
- {ffmpeg_update-3.1.0 → ffmpeg_update-3.1.2}/README.md +20 -41
- {ffmpeg_update-3.1.0 → ffmpeg_update-3.1.2}/pyproject.toml +2 -1
- {ffmpeg_update-3.1.0 → ffmpeg_update-3.1.2}/src/ffmpeg_update/__init__.py +26 -27
- {ffmpeg_update-3.1.0 → ffmpeg_update-3.1.2}/src/ffmpeg_update/__main__.py +0 -0
- {ffmpeg_update-3.1.0 → ffmpeg_update-3.1.2}/src/ffmpeg_update/py.typed +0 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: ffmpeg-update
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.2
|
|
4
4
|
Summary: Package manager for FFmpeg, FFprobe, and FFplay static binaries
|
|
5
5
|
Keywords: updater,installer,downloader,program,executable,binary,command,line,cli,tool
|
|
6
6
|
Author: Asadullah Shaikh
|
|
7
7
|
Classifier: Development Status :: 5 - Production/Stable
|
|
8
8
|
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Framework :: AsyncIO
|
|
9
10
|
Classifier: Intended Audience :: Developers
|
|
10
11
|
Classifier: Intended Audience :: End Users/Desktop
|
|
11
12
|
Classifier: Intended Audience :: System Administrators
|
|
@@ -33,15 +34,12 @@ FFmpeg-update is a package manager for the FFmpeg suite, available as both a CLI
|
|
|
33
34
|
|
|
34
35
|
# Features
|
|
35
36
|
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
- Progress bar with ETA
|
|
43
|
-
- Smart permission handling
|
|
44
|
-
- Atomic file system operations
|
|
37
|
+
- Atomic installation
|
|
38
|
+
- Concurrent downloads
|
|
39
|
+
- Download progress bars
|
|
40
|
+
- Configurable installation directory
|
|
41
|
+
- Latest *release* and *snapshot* builds available
|
|
42
|
+
- Automatic sudo escalation for privileged installation directory
|
|
45
43
|
- Automatic operating system and machine architecture detection
|
|
46
44
|
|
|
47
45
|
# Installation
|
|
@@ -63,7 +61,7 @@ ffup <install|update [--dry-run]|check|uninstall> [OPTIONS] [ffmpeg] [ffprobe] [
|
|
|
63
61
|
Alternatively, can be invoked as a module with `python -m ffmpeg_update <COMMAND>`.
|
|
64
62
|
|
|
65
63
|
> [!TIP]
|
|
66
|
-
> Multiple names can be passed, e.g
|
|
64
|
+
> Multiple names can be passed, e.g., `ffup install ffmpeg ffprobe`
|
|
67
65
|
|
|
68
66
|
> [!NOTE]
|
|
69
67
|
> Default is `ffmpeg`, if no name is passed
|
|
@@ -71,39 +69,39 @@ Alternatively, can be invoked as a module with `python -m ffmpeg_update <COMMAND
|
|
|
71
69
|
## Parameters
|
|
72
70
|
|
|
73
71
|
- `--dir`: The path to the installation directory
|
|
74
|
-
- Environment variable: `$FFUP_DIR`/`$XDG_BIN_HOME`
|
|
75
72
|
- Default: `~/.local/bin`
|
|
76
|
-
-
|
|
73
|
+
- Environment variable: `$FFUP_DIR`, `$XDG_BIN_HOME`
|
|
74
|
+
- Commands: `check`, `install`, `uninstall`, `update`
|
|
77
75
|
|
|
78
76
|
- `--build`: The build type
|
|
77
|
+
- Default: `snapshot`
|
|
79
78
|
- Choices: `release`, `snapshot`
|
|
80
79
|
- Environment Variable: `$FFUP_BUILD`
|
|
81
|
-
-
|
|
82
|
-
- Functions: `check`, `install`, `update`
|
|
80
|
+
- Commands: `check`, `install`, `update`
|
|
83
81
|
|
|
84
82
|
- `--arch`: The machine architecture
|
|
83
|
+
- Default: Auto-detect using `platform.machine()`
|
|
85
84
|
- Choices: `amd64`, `arm64`
|
|
86
85
|
- Environment Variable: `$FFUP_ARCH`
|
|
87
|
-
-
|
|
88
|
-
- Functions: `check`, `install`, `update`
|
|
86
|
+
- Commands: `check`, `install`, `update`
|
|
89
87
|
|
|
90
88
|
- `--os`: The operating system
|
|
89
|
+
- Default: Auto-detect using `platform.system()`
|
|
91
90
|
- Choices: `linux`, `macos`
|
|
92
91
|
- Environment Variable: `$FFUP_OS`
|
|
93
|
-
-
|
|
94
|
-
- Functions: `check`, `install`, `update`
|
|
92
|
+
- Commands: `check`, `install`, `update`
|
|
95
93
|
|
|
96
94
|
- `--dry-run`: A flag to skip download/install, and only check for updates
|
|
97
|
-
- `ffup check` is an alias for `ffup update --dry-run`
|
|
98
95
|
- Default: `False`
|
|
99
|
-
-
|
|
96
|
+
- Commands: `update`
|
|
97
|
+
- Note: `ffup check` is an alias for `ffup update --dry-run`
|
|
100
98
|
|
|
101
99
|
# API Reference
|
|
102
100
|
|
|
103
101
|
## Functions
|
|
104
102
|
|
|
105
|
-
- `update(bins = {"ffmpeg"}, /, *, dry_run = False, dir, tempdir, progress, client) -> None`
|
|
106
|
-
- `install(bins = {"ffmpeg"}, /, *, dir, tempdir, progress, client) -> None`
|
|
103
|
+
- async `update(bins = {"ffmpeg"}, /, *, dry_run = False, dir, tempdir, progress, client) -> None`
|
|
104
|
+
- async `install(bins = {"ffmpeg"}, /, *, dir, tempdir, progress, client) -> None`
|
|
107
105
|
- `uninstall(bins = {"ffmpeg"}, /, *, dir) -> None`
|
|
108
106
|
- `get_arch() -> Literal["amd64", "arm64"]`
|
|
109
107
|
- `get_os() -> Literal["linux", "macos"]`
|
|
@@ -120,26 +118,8 @@ Alternatively, can be invoked as a module with `python -m ffmpeg_update <COMMAND
|
|
|
120
118
|
>
|
|
121
119
|
> - `progress`: A `rich.progress.Progress` used to show progress bars in the terminal
|
|
122
120
|
>
|
|
123
|
-
> - `client`: A `niquests.
|
|
121
|
+
> - `client`: A `niquests.AsyncSession` used to make HTTP requests
|
|
124
122
|
> - Must set parameter `base_url` to `f"https://ffmpeg.martin-riedl.de/redirect/latest/{os}/{arch}/{build}/"`
|
|
125
123
|
> - `build`: `"release"`, `"snapshot"`
|
|
126
124
|
> - `arch`: `"amd64"`, `"arm64"`
|
|
127
125
|
> - `os`: `"linux"`, `"macos"`
|
|
128
|
-
|
|
129
|
-
# Error Handling
|
|
130
|
-
|
|
131
|
-
## `FileNotFoundError`
|
|
132
|
-
|
|
133
|
-
- By design, all operations will fail if the path in question does not exist
|
|
134
|
-
- For new installations, ensure that the installation directory exists
|
|
135
|
-
- For other operations, ensure that the path points to the installed binary
|
|
136
|
-
|
|
137
|
-
## `HTTPError`
|
|
138
|
-
|
|
139
|
-
- `404 Client Error: Not Found for url: ...`
|
|
140
|
-
- Caused by invalid values for one or more of `build`, `arch`, and `os` parameters
|
|
141
|
-
|
|
142
|
-
## `PermissionError`
|
|
143
|
-
|
|
144
|
-
- Triggers automatic escalation via `sudo`
|
|
145
|
-
- The user is prompted for a password at `stdin`
|
|
@@ -5,15 +5,12 @@ FFmpeg-update is a package manager for the FFmpeg suite, available as both a CLI
|
|
|
5
5
|
|
|
6
6
|
# Features
|
|
7
7
|
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
- Progress bar with ETA
|
|
15
|
-
- Smart permission handling
|
|
16
|
-
- Atomic file system operations
|
|
8
|
+
- Atomic installation
|
|
9
|
+
- Concurrent downloads
|
|
10
|
+
- Download progress bars
|
|
11
|
+
- Configurable installation directory
|
|
12
|
+
- Latest *release* and *snapshot* builds available
|
|
13
|
+
- Automatic sudo escalation for privileged installation directory
|
|
17
14
|
- Automatic operating system and machine architecture detection
|
|
18
15
|
|
|
19
16
|
# Installation
|
|
@@ -35,7 +32,7 @@ ffup <install|update [--dry-run]|check|uninstall> [OPTIONS] [ffmpeg] [ffprobe] [
|
|
|
35
32
|
Alternatively, can be invoked as a module with `python -m ffmpeg_update <COMMAND>`.
|
|
36
33
|
|
|
37
34
|
> [!TIP]
|
|
38
|
-
> Multiple names can be passed, e.g
|
|
35
|
+
> Multiple names can be passed, e.g., `ffup install ffmpeg ffprobe`
|
|
39
36
|
|
|
40
37
|
> [!NOTE]
|
|
41
38
|
> Default is `ffmpeg`, if no name is passed
|
|
@@ -43,39 +40,39 @@ Alternatively, can be invoked as a module with `python -m ffmpeg_update <COMMAND
|
|
|
43
40
|
## Parameters
|
|
44
41
|
|
|
45
42
|
- `--dir`: The path to the installation directory
|
|
46
|
-
- Environment variable: `$FFUP_DIR`/`$XDG_BIN_HOME`
|
|
47
43
|
- Default: `~/.local/bin`
|
|
48
|
-
-
|
|
44
|
+
- Environment variable: `$FFUP_DIR`, `$XDG_BIN_HOME`
|
|
45
|
+
- Commands: `check`, `install`, `uninstall`, `update`
|
|
49
46
|
|
|
50
47
|
- `--build`: The build type
|
|
48
|
+
- Default: `snapshot`
|
|
51
49
|
- Choices: `release`, `snapshot`
|
|
52
50
|
- Environment Variable: `$FFUP_BUILD`
|
|
53
|
-
-
|
|
54
|
-
- Functions: `check`, `install`, `update`
|
|
51
|
+
- Commands: `check`, `install`, `update`
|
|
55
52
|
|
|
56
53
|
- `--arch`: The machine architecture
|
|
54
|
+
- Default: Auto-detect using `platform.machine()`
|
|
57
55
|
- Choices: `amd64`, `arm64`
|
|
58
56
|
- Environment Variable: `$FFUP_ARCH`
|
|
59
|
-
-
|
|
60
|
-
- Functions: `check`, `install`, `update`
|
|
57
|
+
- Commands: `check`, `install`, `update`
|
|
61
58
|
|
|
62
59
|
- `--os`: The operating system
|
|
60
|
+
- Default: Auto-detect using `platform.system()`
|
|
63
61
|
- Choices: `linux`, `macos`
|
|
64
62
|
- Environment Variable: `$FFUP_OS`
|
|
65
|
-
-
|
|
66
|
-
- Functions: `check`, `install`, `update`
|
|
63
|
+
- Commands: `check`, `install`, `update`
|
|
67
64
|
|
|
68
65
|
- `--dry-run`: A flag to skip download/install, and only check for updates
|
|
69
|
-
- `ffup check` is an alias for `ffup update --dry-run`
|
|
70
66
|
- Default: `False`
|
|
71
|
-
-
|
|
67
|
+
- Commands: `update`
|
|
68
|
+
- Note: `ffup check` is an alias for `ffup update --dry-run`
|
|
72
69
|
|
|
73
70
|
# API Reference
|
|
74
71
|
|
|
75
72
|
## Functions
|
|
76
73
|
|
|
77
|
-
- `update(bins = {"ffmpeg"}, /, *, dry_run = False, dir, tempdir, progress, client) -> None`
|
|
78
|
-
- `install(bins = {"ffmpeg"}, /, *, dir, tempdir, progress, client) -> None`
|
|
74
|
+
- async `update(bins = {"ffmpeg"}, /, *, dry_run = False, dir, tempdir, progress, client) -> None`
|
|
75
|
+
- async `install(bins = {"ffmpeg"}, /, *, dir, tempdir, progress, client) -> None`
|
|
79
76
|
- `uninstall(bins = {"ffmpeg"}, /, *, dir) -> None`
|
|
80
77
|
- `get_arch() -> Literal["amd64", "arm64"]`
|
|
81
78
|
- `get_os() -> Literal["linux", "macos"]`
|
|
@@ -92,26 +89,8 @@ Alternatively, can be invoked as a module with `python -m ffmpeg_update <COMMAND
|
|
|
92
89
|
>
|
|
93
90
|
> - `progress`: A `rich.progress.Progress` used to show progress bars in the terminal
|
|
94
91
|
>
|
|
95
|
-
> - `client`: A `niquests.
|
|
92
|
+
> - `client`: A `niquests.AsyncSession` used to make HTTP requests
|
|
96
93
|
> - Must set parameter `base_url` to `f"https://ffmpeg.martin-riedl.de/redirect/latest/{os}/{arch}/{build}/"`
|
|
97
94
|
> - `build`: `"release"`, `"snapshot"`
|
|
98
95
|
> - `arch`: `"amd64"`, `"arm64"`
|
|
99
96
|
> - `os`: `"linux"`, `"macos"`
|
|
100
|
-
|
|
101
|
-
# Error Handling
|
|
102
|
-
|
|
103
|
-
## `FileNotFoundError`
|
|
104
|
-
|
|
105
|
-
- By design, all operations will fail if the path in question does not exist
|
|
106
|
-
- For new installations, ensure that the installation directory exists
|
|
107
|
-
- For other operations, ensure that the path points to the installed binary
|
|
108
|
-
|
|
109
|
-
## `HTTPError`
|
|
110
|
-
|
|
111
|
-
- `404 Client Error: Not Found for url: ...`
|
|
112
|
-
- Caused by invalid values for one or more of `build`, `arch`, and `os` parameters
|
|
113
|
-
|
|
114
|
-
## `PermissionError`
|
|
115
|
-
|
|
116
|
-
- Triggers automatic escalation via `sudo`
|
|
117
|
-
- The user is prompted for a password at `stdin`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ffmpeg-update"
|
|
3
|
-
version = "3.1.
|
|
3
|
+
version = "3.1.2"
|
|
4
4
|
description = "Package manager for FFmpeg, FFprobe, and FFplay static binaries"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -11,6 +11,7 @@ keywords = ["updater", "installer", "downloader", "program", "executable", "bina
|
|
|
11
11
|
classifiers = [
|
|
12
12
|
"Development Status :: 5 - Production/Stable",
|
|
13
13
|
"Environment :: Console",
|
|
14
|
+
"Framework :: AsyncIO",
|
|
14
15
|
"Intended Audience :: Developers",
|
|
15
16
|
"Intended Audience :: End Users/Desktop",
|
|
16
17
|
"Intended Audience :: System Administrators",
|
|
@@ -73,21 +73,20 @@ async def update(
|
|
|
73
73
|
progress: Annotated[Progress, Parameter(parse=False)],
|
|
74
74
|
client: Annotated[AsyncSession, Parameter(parse=False)],
|
|
75
75
|
) -> None:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
)
|
|
76
|
+
bin_lst = list(bins)
|
|
77
|
+
latest, *current_lst = await asyncio.gather(
|
|
78
|
+
_latest("ffmpeg", client), *[_current(dir / bin) for bin in bin_lst]
|
|
79
|
+
)
|
|
80
|
+
print(f"Latest Version: {latest}")
|
|
81
|
+
for bin, current in zip(bin_lst, current_lst):
|
|
82
|
+
if current != latest:
|
|
83
|
+
print(f"{_fmt_FF(bin)}: update available")
|
|
84
|
+
else:
|
|
85
|
+
bins.remove(bin)
|
|
86
|
+
print(f"{_fmt_FF(bin)}: up to date")
|
|
87
|
+
|
|
88
|
+
if not dry_run and bins:
|
|
89
|
+
await install(bins, dir=dir, tempdir=tempdir, progress=progress, client=client)
|
|
91
90
|
|
|
92
91
|
|
|
93
92
|
@app.command
|
|
@@ -159,24 +158,24 @@ def get_os() -> OSType:
|
|
|
159
158
|
raise RuntimeError(f"unsupported operating system '{os}'")
|
|
160
159
|
|
|
161
160
|
|
|
162
|
-
def _current(path):
|
|
163
|
-
|
|
164
|
-
|
|
161
|
+
async def _current(path):
|
|
162
|
+
process = await asyncio.create_subprocess_exec(
|
|
163
|
+
path, "-version", stdout=asyncio.subprocess.PIPE
|
|
164
|
+
)
|
|
165
|
+
stdout, _ = await process.communicate()
|
|
166
|
+
match = re.search(r"version (N-\d+-\w+|\d\.\d(\.\d)?)", stdout.decode())
|
|
165
167
|
if match is None:
|
|
166
|
-
raise ValueError(f"failed to parse version from `{path} -version`
|
|
168
|
+
raise ValueError(f"failed to parse version from `{path} -version`")
|
|
167
169
|
return match.group(1)
|
|
168
170
|
|
|
169
171
|
|
|
170
172
|
async def _latest(bin, client):
|
|
171
|
-
response = await client.get(f"{bin}.zip", allow_redirects=False)
|
|
173
|
+
response = await client.get(f"{bin}.zip", allow_redirects=False, stream=True)
|
|
172
174
|
response.raise_for_status()
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return match.group(1)
|
|
178
|
-
else:
|
|
179
|
-
raise ValueError(f"unexpected {response}")
|
|
175
|
+
match = re.search(r"_(N-\d+-\w+|\d\.\d(\.\d)?)", response.headers["location"])
|
|
176
|
+
if match is None:
|
|
177
|
+
raise ValueError(f"failed to parse version from {response}")
|
|
178
|
+
return match.group(1)
|
|
180
179
|
|
|
181
180
|
|
|
182
181
|
async def _download(bin, tempdir, progress, client):
|
|
File without changes
|
|
File without changes
|