aio-ffmpeg 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.
- aio_ffmpeg-0.1.0/.gitea/workflows/ci.yml +55 -0
- aio_ffmpeg-0.1.0/.gitea/workflows/release.yml +52 -0
- aio_ffmpeg-0.1.0/.gitignore +74 -0
- aio_ffmpeg-0.1.0/CHANGELOG.md +23 -0
- aio_ffmpeg-0.1.0/CONTRIBUTING.md +77 -0
- aio_ffmpeg-0.1.0/LICENSE +21 -0
- aio_ffmpeg-0.1.0/PKG-INFO +280 -0
- aio_ffmpeg-0.1.0/README.md +243 -0
- aio_ffmpeg-0.1.0/docs/FFPROBE_JSON_REPORT.md +859 -0
- aio_ffmpeg-0.1.0/docs/api-design.md +551 -0
- aio_ffmpeg-0.1.0/docs/architecture.md +541 -0
- aio_ffmpeg-0.1.0/docs/builder.md +107 -0
- aio_ffmpeg-0.1.0/docs/client.md +74 -0
- aio_ffmpeg-0.1.0/docs/examples/probe_media.py +55 -0
- aio_ffmpeg-0.1.0/docs/examples/progress_cli.py +48 -0
- aio_ffmpeg-0.1.0/docs/examples/transcode.py +44 -0
- aio_ffmpeg-0.1.0/docs/examples/watermark.py +37 -0
- aio_ffmpeg-0.1.0/docs/filters.md +84 -0
- aio_ffmpeg-0.1.0/docs/hardware.md +70 -0
- aio_ffmpeg-0.1.0/docs/integration.md +87 -0
- aio_ffmpeg-0.1.0/docs/pipeline.md +91 -0
- aio_ffmpeg-0.1.0/docs/progress.md +98 -0
- aio_ffmpeg-0.1.0/docs/quickstart.md +160 -0
- aio_ffmpeg-0.1.0/docs/reference/ffmpeg_Documentation.html +4087 -0
- aio_ffmpeg-0.1.0/docs/research.md +658 -0
- aio_ffmpeg-0.1.0/examples/extract_audio.py +98 -0
- aio_ffmpeg-0.1.0/examples/hardware_acceleration.py +64 -0
- aio_ffmpeg-0.1.0/examples/simple_transcode.py +118 -0
- aio_ffmpeg-0.1.0/examples/stream_concat.py +85 -0
- aio_ffmpeg-0.1.0/examples/video_thumbnails.py +81 -0
- aio_ffmpeg-0.1.0/examples/watermark_and_filters.py +106 -0
- aio_ffmpeg-0.1.0/examples/ytdlp_pipeline.py +75 -0
- aio_ffmpeg-0.1.0/pyproject.toml +115 -0
- aio_ffmpeg-0.1.0/src/aio_ffmpeg/__init__.py +10 -0
- aio_ffmpeg-0.1.0/src/aio_ffmpeg/py.typed +1 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/__init__.py +227 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/_compat.py +160 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/_constants.py +31 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/_discovery.py +298 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/_logging.py +22 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/_types.py +139 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/client.py +1040 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/command.py +531 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/enums.py +71 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/exceptions.py +196 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/filters.py +736 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/hardware.py +549 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/integration/__init__.py +19 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/integration/ytdlp.py +204 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/models.py +255 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/pipeline.py +921 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/probe.py +529 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/process.py +322 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/progress.py +246 -0
- aio_ffmpeg-0.1.0/src/async_ffmpeg/py.typed +1 -0
- aio_ffmpeg-0.1.0/tests/conftest.py +9 -0
- aio_ffmpeg-0.1.0/tests/integration/test_pipeline_e2e.py +115 -0
- aio_ffmpeg-0.1.0/tests/performance/test_concurrent.py +78 -0
- aio_ffmpeg-0.1.0/tests/unit/test_advanced.py +146 -0
- aio_ffmpeg-0.1.0/tests/unit/test_client.py +283 -0
- aio_ffmpeg-0.1.0/tests/unit/test_command.py +144 -0
- aio_ffmpeg-0.1.0/tests/unit/test_compat.py +63 -0
- aio_ffmpeg-0.1.0/tests/unit/test_constants.py +19 -0
- aio_ffmpeg-0.1.0/tests/unit/test_discovery.py +100 -0
- aio_ffmpeg-0.1.0/tests/unit/test_exceptions.py +98 -0
- aio_ffmpeg-0.1.0/tests/unit/test_filters.py +230 -0
- aio_ffmpeg-0.1.0/tests/unit/test_hardware.py +207 -0
- aio_ffmpeg-0.1.0/tests/unit/test_init.py +22 -0
- aio_ffmpeg-0.1.0/tests/unit/test_integration.py +122 -0
- aio_ffmpeg-0.1.0/tests/unit/test_logging.py +68 -0
- aio_ffmpeg-0.1.0/tests/unit/test_models.py +123 -0
- aio_ffmpeg-0.1.0/tests/unit/test_params_validation.py +176 -0
- aio_ffmpeg-0.1.0/tests/unit/test_pipeline.py +346 -0
- aio_ffmpeg-0.1.0/tests/unit/test_probe.py +192 -0
- aio_ffmpeg-0.1.0/tests/unit/test_process.py +147 -0
- aio_ffmpeg-0.1.0/tests/unit/test_progress.py +175 -0
- aio_ffmpeg-0.1.0/tests/unit/test_types.py +50 -0
- aio_ffmpeg-0.1.0/uv.lock +556 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
name: CI Pipeline
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, develop]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, develop]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint-and-test:
|
|
11
|
+
name: Lint, Type Check and Tests
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout repository
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Set up Python 3.14
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.14"
|
|
21
|
+
|
|
22
|
+
- name: Install FFmpeg
|
|
23
|
+
run: |
|
|
24
|
+
sudo apt-get update
|
|
25
|
+
sudo apt-get install -y ffmpeg
|
|
26
|
+
|
|
27
|
+
- name: Install uv
|
|
28
|
+
uses: astral-sh/setup-uv@v3
|
|
29
|
+
with:
|
|
30
|
+
enable-cache: true
|
|
31
|
+
|
|
32
|
+
- name: Install dependencies
|
|
33
|
+
run: |
|
|
34
|
+
uv sync --extra dev
|
|
35
|
+
|
|
36
|
+
- name: Check code formatting (Ruff)
|
|
37
|
+
run: |
|
|
38
|
+
uv run ruff format --check src/ tests/ docs/
|
|
39
|
+
|
|
40
|
+
- name: Lint codebase (Ruff)
|
|
41
|
+
run: |
|
|
42
|
+
uv run ruff check src/ tests/ docs/
|
|
43
|
+
|
|
44
|
+
- name: Type check (Mypy)
|
|
45
|
+
run: |
|
|
46
|
+
uv run mypy src/
|
|
47
|
+
|
|
48
|
+
- name: Run unit & integration tests with coverage
|
|
49
|
+
run: |
|
|
50
|
+
uv run coverage run -m pytest tests/ -v
|
|
51
|
+
uv run coverage report -m
|
|
52
|
+
|
|
53
|
+
- name: Build distribution packages (Wheel & Sdist)
|
|
54
|
+
run: |
|
|
55
|
+
uv build
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Release Pipeline
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build-and-release:
|
|
10
|
+
name: Build and Verify Release Artifacts
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- name: Checkout repository
|
|
14
|
+
uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Set up Python 3.14
|
|
17
|
+
uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.14"
|
|
20
|
+
|
|
21
|
+
- name: Install FFmpeg
|
|
22
|
+
run: |
|
|
23
|
+
sudo apt-get update
|
|
24
|
+
sudo apt-get install -y ffmpeg
|
|
25
|
+
|
|
26
|
+
- name: Install uv
|
|
27
|
+
uses: astral-sh/setup-uv@v3
|
|
28
|
+
with:
|
|
29
|
+
enable-cache: true
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: |
|
|
33
|
+
uv sync --extra dev
|
|
34
|
+
|
|
35
|
+
- name: Lint and Typecheck
|
|
36
|
+
run: |
|
|
37
|
+
uv run ruff check src/ tests/ examples/
|
|
38
|
+
uv run mypy src/
|
|
39
|
+
|
|
40
|
+
- name: Run test suite
|
|
41
|
+
run: |
|
|
42
|
+
uv run pytest tests/ -v
|
|
43
|
+
|
|
44
|
+
- name: Build distribution packages (Wheel & Sdist)
|
|
45
|
+
run: |
|
|
46
|
+
uv build
|
|
47
|
+
|
|
48
|
+
- name: Upload distribution packages as artifacts
|
|
49
|
+
uses: actions/upload-artifact@v4
|
|
50
|
+
with:
|
|
51
|
+
name: dist-packages
|
|
52
|
+
path: dist/*
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
.Python
|
|
8
|
+
build/
|
|
9
|
+
develop-eggs/
|
|
10
|
+
dist/
|
|
11
|
+
downloads/
|
|
12
|
+
eggs/
|
|
13
|
+
.eggs/
|
|
14
|
+
lib/
|
|
15
|
+
lib64/
|
|
16
|
+
parts/
|
|
17
|
+
sdist/
|
|
18
|
+
var/
|
|
19
|
+
wheels/
|
|
20
|
+
share/python-wheels/
|
|
21
|
+
*.egg-info/
|
|
22
|
+
.installed.cfg
|
|
23
|
+
*.egg
|
|
24
|
+
MANIFEST
|
|
25
|
+
|
|
26
|
+
# Virtual environments
|
|
27
|
+
.venv/
|
|
28
|
+
env/
|
|
29
|
+
venv/
|
|
30
|
+
ENV/
|
|
31
|
+
env.bak/
|
|
32
|
+
venv.bak/
|
|
33
|
+
|
|
34
|
+
# Testing & Linting
|
|
35
|
+
.pytest_cache/
|
|
36
|
+
.ruff_cache/
|
|
37
|
+
.mypy_cache/
|
|
38
|
+
.coverage
|
|
39
|
+
.coverage.*
|
|
40
|
+
coverage.xml
|
|
41
|
+
htmlcov/
|
|
42
|
+
|
|
43
|
+
# Graphify output directory
|
|
44
|
+
graphify-out/
|
|
45
|
+
|
|
46
|
+
# Media temporary files and test artifacts
|
|
47
|
+
*.mp4
|
|
48
|
+
*.mkv
|
|
49
|
+
*.avi
|
|
50
|
+
*.mp3
|
|
51
|
+
*.aac
|
|
52
|
+
*.wav
|
|
53
|
+
*.flac
|
|
54
|
+
*.m4a
|
|
55
|
+
*.webm
|
|
56
|
+
*.ogg
|
|
57
|
+
*.ts
|
|
58
|
+
*.srt
|
|
59
|
+
*.vtt
|
|
60
|
+
*.log
|
|
61
|
+
*.txt
|
|
62
|
+
!requirements*.txt
|
|
63
|
+
!docs/**/*.txt
|
|
64
|
+
output_examples/
|
|
65
|
+
|
|
66
|
+
# IDE / Editor
|
|
67
|
+
.idea/
|
|
68
|
+
.vscode/
|
|
69
|
+
*.swp
|
|
70
|
+
*.swo
|
|
71
|
+
|
|
72
|
+
# OS generated
|
|
73
|
+
.DS_Store
|
|
74
|
+
Thumbs.db
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Все заметные изменения в проекте `async-ffmpeg` документируются в этом файле.
|
|
4
|
+
|
|
5
|
+
Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.0.0/),
|
|
6
|
+
и проект придерживается [Семантического версионирования](https://semver.org/lang/ru/).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-09-19
|
|
11
|
+
|
|
12
|
+
### Добавлено
|
|
13
|
+
- **Высокоуровневый клиент (`FFmpegClient`)**: единый фасад с методами `transcode`, `extract_audio`, `trim`, `concat`, `screenshot`, `thumbnails`, `convert`, `normalize_audio`, `scale`, `two_pass_transcode`, `create_contact_sheet`, `detect_silence` и `probe`.
|
|
14
|
+
- **Конструктор команд (`FFmpegCommand`)**: строго упорядоченный fluent-builder аргументов FFmpeg CLI (глобальные опции -> входные параметры -> фильтры -> выходные параметры) с автоматической валидацией конфликтующих флагов.
|
|
15
|
+
- **Декларативный конвейер медиа (`MediaPipeline`)**: пошаговое построение цепочек обработки (trim, scale, watermark, audio normalization) с компиляцией в единый процесс FFmpeg и валидацией на этапе сборки.
|
|
16
|
+
- **Клиент инспекции (`FFprobe`) и строгие модели данных**: асинхронный запуск `ffprobe` с разбором JSON-вывода в типизированные frozen dataclass-модели (`MediaInfo`, `VideoStream`, `AudioStream`, `SubtitleStream`, `Chapter`, `StreamDisposition`).
|
|
17
|
+
- **Модуль аппаратного ускорения (`HardwareAccel`)**: автоматическое обнаружение доступных GPU-ускорителей (CUDA/NVENC, AMD AMF, Intel QSV, D3D11VA, Apple VideoToolbox) и подбор оптимальных кодеков.
|
|
18
|
+
- **Диспетчер процессов (`ProcessRunner`)**: асинхронное управление жизненным циклом подпроцессов через `asyncio.create_subprocess_exec()`, ограничение параллельности через `asyncio.Semaphore`, поддержка таймаутов и graceful shutdown (`q\n` -> SIGINT -> SIGKILL).
|
|
19
|
+
- **Машиночитаемый парсер прогресса (`ProgressParser`)**: разбор протокола `-progress pipe:1` в реальном времени с вычислением процента выполнения, времени, FPS, битрейта и скорости кодирования.
|
|
20
|
+
- **Объектно-ориентированный граф фильтров (`Filter`, `FilterChain`, `FilterGraph`, `ComplexFilterGraph`)**: фабричные функции для видео- и аудиофильтров (`scale`, `fps`, `crop`, `pad`, `rotate`, `overlay`, `drawtext`, `loudnorm`, `volume`, `amix`, `concat` и др.).
|
|
21
|
+
- **Модуль интеграции с `async-yt-dlp` (`async_ffmpeg.integration`)**: функции `process_download_result`, `transcode_download`, `extract_download_audio` и класс `DownloadPostProcessor` на базе слабосвязанного протокола `DownloadResultProtocol`.
|
|
22
|
+
- **Комплекс интерактивных примеров (`examples/`)**: 7 готовых сценариев (`simple_transcode`, `extract_audio`, `video_thumbnails`, `watermark_and_filters`, `stream_concat`, `hardware_acceleration`, `ytdlp_pipeline`).
|
|
23
|
+
- **Инфраструктура и качество**: 118 автоматических тестов с 100% прохождением, поддержка Python 3.14+, строгая статическая типизация `mypy --strict` без единого `Any`, zero runtime dependencies (только стандартная библиотека Python).
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Руководство по внесению вклада (Contributing)
|
|
2
|
+
|
|
3
|
+
Приветствуются любые улучшения, исправления ошибок и предложения новых функциональных возможностей в `async-ffmpeg`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Стратегия ветвления (Branching Strategy)
|
|
8
|
+
|
|
9
|
+
В репозитории используется модель Git Flow с двумя долгоживущими ветками:
|
|
10
|
+
|
|
11
|
+
- **`main`**: стабильная (production) ветка. Содержит исключительно готовые к релизу версии кода. Прямые коммиты запрещены. Слияния осуществляются только из `develop` перед выпуском новой версии с созданием аннотированного тега (`vX.Y.Z`).
|
|
12
|
+
- **`develop`**: ветка активной разработки. В неё интегрируются новые возможности и исправления через Pull Requests.
|
|
13
|
+
- **Вспомогательные ветки**:
|
|
14
|
+
- `feature/<название>`: разработка новой функциональности (создаются от `develop`, сливаются в `develop`).
|
|
15
|
+
- `fix/<описание>` или `bugfix/<описание>`: устранение ошибок (создаются от `develop`, сливаются в `develop`).
|
|
16
|
+
- `hotfix/<описание>`: неотложные исправления для продакшна (создаются от `main`, сливаются в `main` и `develop`).
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 2. Процесс разработки
|
|
21
|
+
|
|
22
|
+
1. Склонировать репозиторий:
|
|
23
|
+
```bash
|
|
24
|
+
git clone ssh://git@localhost:2222/6aton/AsyncFFmpeg.git
|
|
25
|
+
cd AsyncFFmpeg
|
|
26
|
+
```
|
|
27
|
+
2. Создать рабочую ветку от актуального состояния `develop`:
|
|
28
|
+
```bash
|
|
29
|
+
git checkout develop
|
|
30
|
+
git pull origin develop
|
|
31
|
+
git checkout -b feature/my-feature
|
|
32
|
+
```
|
|
33
|
+
3. Установить зависимости для разработки через менеджер `uv`:
|
|
34
|
+
```bash
|
|
35
|
+
uv sync --extra dev
|
|
36
|
+
```
|
|
37
|
+
4. Внести изменения, соблюдая архитектурные принципы проекта.
|
|
38
|
+
5. Написать модульные или интеграционные тесты в каталоге `tests/`.
|
|
39
|
+
6. Убедиться в успешном прохождении всех локальных проверок качества.
|
|
40
|
+
7. Зафиксировать изменения с понятными сообщениями коммитов и отправить ветку в удалённый репозиторий.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 3. Стандарты качества кода
|
|
45
|
+
|
|
46
|
+
Перед отправкой изменений обязательно выполнение всех автоматических проверок:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Проверка форматирования и линтинга
|
|
50
|
+
uv run ruff check src/ tests/ examples/ docs/
|
|
51
|
+
uv run ruff format --check src/ tests/ examples/ docs/
|
|
52
|
+
|
|
53
|
+
# Проверка строгой статической типизации (Zero Any policy)
|
|
54
|
+
uv run mypy src/
|
|
55
|
+
|
|
56
|
+
# Запуск полного набора тестов с анализом покрытия
|
|
57
|
+
uv run pytest tests/ -v
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 4. Архитектурные правила и ограничения
|
|
63
|
+
|
|
64
|
+
1. **Zero Runtime Dependencies**:
|
|
65
|
+
- В секции `dependencies` файла `pyproject.toml` не допускаются внешние пакеты.
|
|
66
|
+
- Разрешено использование исключительно стандартной библиотеки Python 3.14+.
|
|
67
|
+
- Внешние интеграции (например, `async-yt-dlp`) оформляются как опциональные зависимости (`optional-dependencies`).
|
|
68
|
+
2. **Строгая статическая типизация**:
|
|
69
|
+
- Политика `Zero Any`: использование типа `Any` строго запрещено во всех публичных и внутренних сигнатурах.
|
|
70
|
+
- Для всех моделей данных используются frozen dataclass со `slots=True` (`@dataclass(frozen=True, slots=True)`).
|
|
71
|
+
- Обязательно указание типов всех аргументов и возвращаемых значений (`-> None` для процедур).
|
|
72
|
+
3. **Языковая политика**:
|
|
73
|
+
- Все docstrings, комментарии к коду и документация составляются на русском языке в нейтральной форме (инфинитивы, безличные конструкции, 3-е лицо; без использования местоимений первого и второго лица).
|
|
74
|
+
- Все идентификаторы (имена модулей, классов, методов, функций, переменных) именуются на английском языке по стандарту PEP 8.
|
|
75
|
+
4. **Кроссплатформенность**:
|
|
76
|
+
- Пути к файлам нормализуются через `normalize_path_for_ffmpeg()` из `_compat.py`.
|
|
77
|
+
- Запуск подпроцессов учитывает специфику платформ (флаг `CREATE_NO_WINDOW` для Windows, сигналы завершения для POSIX).
|
aio_ffmpeg-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 async-ffmpeg contributors
|
|
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.
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: aio-ffmpeg
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Production-ready, strictly typed async wrapper for FFmpeg and FFprobe
|
|
5
|
+
Project-URL: Homepage, https://github.com/baton-spb/AsyncFFmpeg
|
|
6
|
+
Project-URL: Documentation, https://github.com/baton-spb/AsyncFFmpeg#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/baton-spb/AsyncFFmpeg.git
|
|
8
|
+
Project-URL: Issues, https://github.com/baton-spb/AsyncFFmpeg/issues
|
|
9
|
+
Author: async-ffmpeg contributors
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: aio,async,asyncio,audio,ffmpeg,ffprobe,streaming,transcode,video
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Framework :: AsyncIO
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
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.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Topic :: Multimedia :: Sound/Audio
|
|
24
|
+
Classifier: Topic :: Multimedia :: Video
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Python: >=3.11
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: coverage>=7.6.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: mypy>=1.13.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff>=0.8.0; extra == 'dev'
|
|
34
|
+
Provides-Extra: ytdlp
|
|
35
|
+
Requires-Dist: async-yt-dlp>=0.1.0; extra == 'ytdlp'
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
# async-ffmpeg
|
|
39
|
+
|
|
40
|
+
[](https://github.com/baton-spb/AsyncFFmpeg/actions)
|
|
41
|
+
[](https://pypi.org/project/async-ffmpeg/)
|
|
42
|
+
[](https://www.python.org/downloads/)
|
|
43
|
+
[](https://peps.python.org/pep-0561/)
|
|
44
|
+
[](LICENSE)
|
|
45
|
+
|
|
46
|
+
**async-ffmpeg** — современная, строго типизированная, production-ready асинхронная библиотека-обёртка над `ffmpeg` и `ffprobe` для Python 3.11+.
|
|
47
|
+
|
|
48
|
+
Она построена непосредственно поверх `asyncio.create_subprocess_exec()` без сторонних C-библиотек, без устаревших binding-ов и с **нулевыми зависимостями времени выполнения** (zero runtime dependencies, только стандартная библиотека Python).
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Сравнение с аналогами
|
|
53
|
+
|
|
54
|
+
| Возможность | `async-ffmpeg` | `ffmpeg-python` | `moviepy` | `subprocess` (ручной) |
|
|
55
|
+
|:---|:---:|:---:|:---:|:---:|
|
|
56
|
+
| **Нативная асинхронность (`asyncio`)** | **Да** | Нет | Нет | Требует ручной реализации |
|
|
57
|
+
| **Зависимости времени выполнения** | **0 (только stdlib)** | 2 | 10+ (тяжёлые) | 0 |
|
|
58
|
+
| **Строгая типизация (`mypy --strict`)** | **100% (Zero Any)** | Нет типов | Частичная | Нет |
|
|
59
|
+
| **Парсинг прогресса в реальном времени** | **Да (`-progress pipe:1`)** | Нет | Tqdm (базовый) | Ручной парсинг |
|
|
60
|
+
| **Безопасная остановка (Graceful Shutdown)** | **Да (`q\n` -> SIGINT)** | Нет | Нет | Нет |
|
|
61
|
+
| **Многоуровневый API (Facade / Pipeline / Builder)** | **Да** | Только builder | Только facade | Нет |
|
|
62
|
+
| **Автоопределение GPU (CUDA/AMF/QSV/Toolbox)** | **Да** | Нет | Нет | Нет |
|
|
63
|
+
| **Поддержка современного Python 3.14+** | **Да** | Заброшен | Медленный | Да |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Ключевые возможности
|
|
68
|
+
|
|
69
|
+
- **Полноценная асинхронность**: неблокирующий запуск процессов через `asyncio.create_subprocess_exec()`, контроль конкурентности через `asyncio.Semaphore`.
|
|
70
|
+
- **Строгая типизация**: 100% соответствие `mypy --strict` и `Zero Any policy`, frozen dataclass-модели со `slots=True`, маркер PEP 561 (`py.typed`).
|
|
71
|
+
- **Машиночитаемый прогресс**: чтение и потоковый разбор протокола `-progress pipe:1` (кадры, время, битрейт, скорость кодирования, процент выполнения).
|
|
72
|
+
- **Graceful Shutdown**: предотвращение повреждения медиафайлов (битых заголовков MP4 / unclosed `moov` atom) путём отправки `q` в stdin перед отправкой системных сигналов завершения.
|
|
73
|
+
- **Трёхуровневый API**:
|
|
74
|
+
- **Facade (`FFmpegClient`)**: готовые методы для решения 95% повседневных задач.
|
|
75
|
+
- **Pipeline (`MediaPipeline`)**: декларативный конвейер цепочек обработки видео и аудио.
|
|
76
|
+
- **Command Builder (`FFmpegCommand`)**: строгий конструктор аргументов CLI с контролем порядка и валидацией конфликтов.
|
|
77
|
+
- **Типизированный FFprobe**: детальный разбор контейнеров, видео/аудио/субтитр-потоков, глав и метаданных.
|
|
78
|
+
- **Аппаратное ускорение**: автоопределение и конфигурация NVENC, AMF, QSV, D3D11VA, VideoToolbox.
|
|
79
|
+
- **Интеграция с `async-yt-dlp`**: бесшовный конвейер загрузки и последующей обработки медиафайлов.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Методы высокоуровневого клиента (`FFmpegClient`)
|
|
84
|
+
|
|
85
|
+
| Метод | Назначение |
|
|
86
|
+
|:---|:---|
|
|
87
|
+
| `transcode(...)` | Универсальное перекодирование с контролем кодеков, битрейта, разрешения, FPS и фильтров. |
|
|
88
|
+
| `extract_audio(...)` | Извлечение аудиодорожки (`-vn`) с конвертацией в AAC, MP3, FLAC, OPUS или WAV. |
|
|
89
|
+
| `trim(...)` | Быстрая обрезка медиафрагментов по меткам времени (со stream copy или перекодированием). |
|
|
90
|
+
| `concat(...)` | Склейка нескольких файлов без перекодирования (demuxer) или через граф фильтров. |
|
|
91
|
+
| `screenshot(...)` | Извлечение одного кадра в указанной временной метке в высоком качестве. |
|
|
92
|
+
| `thumbnails(...)` | Серийная генерация миниатюр по фиксированному интервалу, общему числу или частоте кадров. |
|
|
93
|
+
| `convert(...)` | Быстрая смена контейнера (remuxing, например MKV -> MP4) со stream copy. |
|
|
94
|
+
| `normalize_audio(...)` | Двухпроходная нормализация громкости по вещательному стандарту EBU R128 (`loudnorm`). |
|
|
95
|
+
| `scale(...)` | Масштабирование видеоряда с сохранением исходной аудиодорожки без перекодирования. |
|
|
96
|
+
| `two_pass_transcode(...)` | Двухпроходное кодирование с контролем битрейта и автоматической очисткой временных логов. |
|
|
97
|
+
| `create_contact_sheet(...)` | Сборка раскадровки (storyboard/contact sheet) в виде сетки миниатюр (`tile`). |
|
|
98
|
+
| `detect_silence(...)` | Детектирование тишины и пауз в аудиодорожке с получением интервалов (`SilenceInterval`). |
|
|
99
|
+
| `probe(...)` | Детальный анализ метаданных файла или потока с возвратом типизированного `MediaInfo`. |
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Установка
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Базовая установка (zero external dependencies)
|
|
107
|
+
uv add async-ffmpeg
|
|
108
|
+
|
|
109
|
+
# Или через pip:
|
|
110
|
+
pip install async-ffmpeg
|
|
111
|
+
|
|
112
|
+
# С опциональной поддержкой интеграции с async-yt-dlp
|
|
113
|
+
pip install "async-ffmpeg[ytdlp]"
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Требования:
|
|
117
|
+
- Python >= 3.14
|
|
118
|
+
- Установленный в системе `ffmpeg` и `ffprobe` (в `PATH` или указанный через аргументы клиента / переменную `FFMPEG_PATH`)
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Быстрый старт
|
|
123
|
+
|
|
124
|
+
### 1. Анализ медиафайла (`FFprobe`)
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
import asyncio
|
|
128
|
+
from async_ffmpeg import FFmpegClient
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
async def main() -> None:
|
|
132
|
+
client = FFmpegClient()
|
|
133
|
+
info = await client.probe("video.mp4")
|
|
134
|
+
|
|
135
|
+
print(f"Формат: {info.format.format_long_name}")
|
|
136
|
+
print(f"Длительность: {info.duration} сек")
|
|
137
|
+
|
|
138
|
+
if info.primary_video:
|
|
139
|
+
v = info.primary_video
|
|
140
|
+
print(f"Видео: {v.codec_name}, {v.width}x{v.height} @ {v.frame_rate:.2f} fps")
|
|
141
|
+
|
|
142
|
+
if info.primary_audio:
|
|
143
|
+
a = info.primary_audio
|
|
144
|
+
print(f"Аудио: {a.codec_name}, {a.sample_rate} Hz, каналов: {a.channels}")
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
asyncio.run(main())
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 2. Транскодирование с отслеживанием прогресса
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
import asyncio
|
|
154
|
+
from async_ffmpeg import FFmpegClient, ProgressInfo
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
async def main() -> None:
|
|
158
|
+
client = FFmpegClient()
|
|
159
|
+
|
|
160
|
+
async def on_progress(p: ProgressInfo) -> None:
|
|
161
|
+
print(f"Прогресс: {p.percent:.1f}% | Скорость: {p.speed} | FPS: {p.fps:.1f}")
|
|
162
|
+
|
|
163
|
+
result = await client.transcode(
|
|
164
|
+
input="input.mp4",
|
|
165
|
+
output="output_720p.mp4",
|
|
166
|
+
video_codec="libx264",
|
|
167
|
+
crf=23,
|
|
168
|
+
resolution=(1280, 720),
|
|
169
|
+
audio_codec="aac",
|
|
170
|
+
audio_bitrate="128k",
|
|
171
|
+
on_progress=on_progress,
|
|
172
|
+
)
|
|
173
|
+
print(f"Готово за {result.duration_seconds:.2f} сек!")
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
asyncio.run(main())
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 3. Декларативный конвейер (`MediaPipeline`)
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
import asyncio
|
|
183
|
+
from async_ffmpeg import FFmpegClient
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
async def main() -> None:
|
|
187
|
+
client = FFmpegClient()
|
|
188
|
+
|
|
189
|
+
# Цепочка: обрезка -> масштабирование -> нормализация звука -> вывод
|
|
190
|
+
await (
|
|
191
|
+
client.pipeline("input.mp4")
|
|
192
|
+
.trim(start=10, duration=60)
|
|
193
|
+
.scale(1280, 720)
|
|
194
|
+
.normalize_audio(target_lufs=-16.0)
|
|
195
|
+
.output("highlight_720p.mp4")
|
|
196
|
+
.run()
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
asyncio.run(main())
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### 4. Интеграция с загрузчиком (`async-yt-dlp`)
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
import asyncio
|
|
207
|
+
from async_ffmpeg import FFmpegClient
|
|
208
|
+
from async_ffmpeg.integration import process_download_result
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
async def main() -> None:
|
|
212
|
+
# Загрузка через yt-dlp (или совместимый объект с протоколом DownloadResultProtocol)
|
|
213
|
+
# Предположим, результат загрузки сохранён в download_result
|
|
214
|
+
client = FFmpegClient()
|
|
215
|
+
|
|
216
|
+
# Автоматическое извлечение аудиодорожки или конвертация
|
|
217
|
+
post_result = await process_download_result(
|
|
218
|
+
download_result,
|
|
219
|
+
action="extract_audio",
|
|
220
|
+
client=client,
|
|
221
|
+
audio_format="mp3",
|
|
222
|
+
audio_bitrate="320k",
|
|
223
|
+
)
|
|
224
|
+
print(f"Обработано: {post_result.output_path}")
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
asyncio.run(main())
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Примеры использования (`examples/`)
|
|
233
|
+
|
|
234
|
+
В каталоге [`examples/`](examples/) содержатся готовые исполняемые сценарии:
|
|
235
|
+
|
|
236
|
+
1. [`simple_transcode.py`](examples/simple_transcode.py) — Базовое перекодирование с отслеживанием прогресса в реальном времени.
|
|
237
|
+
2. [`extract_audio.py`](examples/extract_audio.py) — Извлечение звуковых дорожек в форматах MP3, AAC, FLAC и нормализация звука.
|
|
238
|
+
3. [`video_thumbnails.py`](examples/video_thumbnails.py) — Снятие скриншотов, серийная генерация миниатюр и раскадровка (contact sheet).
|
|
239
|
+
4. [`watermark_and_filters.py`](examples/watermark_and_filters.py) — Наложение водяных знаков и комплексных графов фильтров через `MediaPipeline`.
|
|
240
|
+
5. [`stream_concat.py`](examples/stream_concat.py) — Склейка медиафайлов через демультиплексор (demuxer) и фильтр объединения.
|
|
241
|
+
6. [`hardware_acceleration.py`](examples/hardware_acceleration.py) — Автоматическое обнаружение GPU и кодирование с аппаратным ускорением.
|
|
242
|
+
7. [`ytdlp_pipeline.py`](examples/ytdlp_pipeline.py) — Полный конвейер скачивания и последующей обработки с `async-yt-dlp`.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Архитектура и документация
|
|
247
|
+
|
|
248
|
+
Подробная проектная документация доступна в каталоге [`docs/`](docs/):
|
|
249
|
+
|
|
250
|
+
- [`architecture.md`](docs/architecture.md) — Системная архитектура, слои абстракции, управление процессами.
|
|
251
|
+
- [`api-design.md`](docs/api-design.md) — Детальное описание публичного API и сигнатур.
|
|
252
|
+
- [`research.md`](docs/research.md) — Исследование поведения FFmpeg CLI, протокола `-progress` и кодов возврата.
|
|
253
|
+
- [`pipeline.md`](docs/pipeline.md) — Руководство по работе с `MediaPipeline`.
|
|
254
|
+
- [`hardware.md`](docs/hardware.md) — Конфигурация и использование аппаратного ускорения (GPU).
|
|
255
|
+
- [`integration.md`](docs/integration.md) — Взаимодействие с внешними загрузчиками и `async-yt-dlp`.
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Разработка и тестирование
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
# Установка dev-окружения
|
|
263
|
+
uv sync --extra dev
|
|
264
|
+
|
|
265
|
+
# Проверка форматирования и линтинга
|
|
266
|
+
uv run ruff check src/ tests/ examples/ docs/
|
|
267
|
+
uv run ruff format --check src/ tests/ examples/ docs/
|
|
268
|
+
|
|
269
|
+
# Проверка строгой статической типизации
|
|
270
|
+
uv run mypy src/
|
|
271
|
+
|
|
272
|
+
# Запуск тестов
|
|
273
|
+
uv run pytest tests/ -v
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Лицензия
|
|
279
|
+
|
|
280
|
+
Распространяется под лицензией [MIT](LICENSE).
|