plex-generate-previews 2.4.1.dev0__tar.gz → 2.5.1.dev0__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.
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/PKG-INFO +6 -31
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/README.md +5 -30
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews/__init__.py +1 -1
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews/_version.py +3 -3
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews/gpu_detection.py +20 -157
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews/media_processing.py +2 -2
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews.egg-info/PKG-INFO +6 -31
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_gpu_detection_extended.py +9 -119
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/.codecov.yml +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/.coverage +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/.env.example +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/.github/workflows/dev-release.yml +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/.github/workflows/release.yml +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/.github/workflows/test.yml +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/.gitignore +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/Dockerfile +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/LICENSE +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/docker-init-user.sh +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/env.example +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews/__main__.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews/cli.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews/config.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews/fixtures/test_video.mp4 +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews/logging_config.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews/plex_client.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews/utils.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews/version_check.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews/worker.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews.egg-info/SOURCES.txt +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews.egg-info/dependency_links.txt +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews.egg-info/entry_points.txt +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews.egg-info/requires.txt +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/plex_generate_previews.egg-info/top_level.txt +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/pyproject.toml +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/pytest.ini +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/setup.cfg +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/__init__.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/conftest.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/fixtures/plex_responses/episode_tree.xml +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/fixtures/plex_responses/library_sections.xml +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/fixtures/plex_responses/movie_tree.xml +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/fixtures/reference.bif +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/fixtures/sample.jpg +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_basic.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_cli.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_config.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_gpu_ci.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_headers.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_integration.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_logging_config.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_main.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_media_processing.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_plex_client.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_utils.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_version_check.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_windows_compatibility.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_worker.py +0 -0
- {plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/wrapper.sh +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plex-generate-previews
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.1.dev0
|
|
4
4
|
Summary: Generate video preview thumbnails for Plex Media Server
|
|
5
5
|
Author-email: stevezau <stevezau@example.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -123,7 +123,7 @@ plex-generate-previews \
|
|
|
123
123
|
|
|
124
124
|
## Features
|
|
125
125
|
|
|
126
|
-
- **Multi-GPU Support**: NVIDIA, AMD, Intel, and
|
|
126
|
+
- **Multi-GPU Support**: NVIDIA, AMD, Intel, and Windows GPUs
|
|
127
127
|
- **Parallel Processing**: Configurable GPU and CPU worker threads
|
|
128
128
|
- **Hardware Acceleration**: CUDA, VAAPI, and D3D11VA
|
|
129
129
|
- **Library Filtering**: Process specific Plex libraries
|
|
@@ -144,7 +144,6 @@ plex-generate-previews \
|
|
|
144
144
|
|----------|---------|-------|
|
|
145
145
|
| **Linux** | ✅ Full | GPU + CPU support (CUDA, VAAPI, etc.) |
|
|
146
146
|
| **Docker** | ✅ Full | GPU + CPU support (Recommended) |
|
|
147
|
-
| **WSL2** | ✅ Full | GPU + CPU support (D3D11VA, VAAPI) |
|
|
148
147
|
| **macOS** | ✅ Full | VideoToolbox + CPU support |
|
|
149
148
|
| **Windows** | ✅ Full | D3D11VA GPU + CPU support |
|
|
150
149
|
|
|
@@ -158,7 +157,6 @@ plex-generate-previews \
|
|
|
158
157
|
- **NVIDIA**: CUDA-compatible GPU + NVIDIA drivers
|
|
159
158
|
- **AMD**: ROCm-compatible GPU + amdgpu drivers
|
|
160
159
|
- **Intel**: VAAPI-compatible iGPU/dGPU
|
|
161
|
-
- **WSL2**: D3D11VA-compatible GPU (Intel Arc, etc.)
|
|
162
160
|
|
|
163
161
|
## Installation Options
|
|
164
162
|
|
|
@@ -197,7 +195,6 @@ docker run --rm --gpus all \
|
|
|
197
195
|
**GPU Requirements:**
|
|
198
196
|
- **NVIDIA**: Install [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html)
|
|
199
197
|
- **AMD/Intel**: Mount `/dev/dri` with `--device /dev/dri:/dev/dri` (see [Troubleshooting](#troubleshooting) if you get permission errors)
|
|
200
|
-
- **WSL2**: No special configuration needed - automatically detects WSL2 GPUs
|
|
201
198
|
|
|
202
199
|
### Pip Installation
|
|
203
200
|
|
|
@@ -519,8 +516,7 @@ The tool automatically detects and supports multiple GPU types with hardware acc
|
|
|
519
516
|
| **AMD** | VAAPI | amdgpu drivers + ROCm | ✅ ROCm Docker support |
|
|
520
517
|
| **Intel** | VAAPI | Intel drivers + VA-API | ✅ Device access |
|
|
521
518
|
| **Apple Silicon** | VideoToolbox | macOS with FFmpeg + mediainfo | ❌ Native macOS only |
|
|
522
|
-
| **
|
|
523
|
-
| **WSL2 (AMD)** | VAAPI | WSL2 + ROCm + /dev/dri devices | ✅ Native WSL2 |
|
|
519
|
+
| **Windows** | D3D11VA | Windows with FFmpeg + latest GPU drivers | ❌ Native Windows only |
|
|
524
520
|
|
|
525
521
|
### GPU Detection
|
|
526
522
|
|
|
@@ -554,12 +550,10 @@ plex-generate-previews --gpu-selection "0"
|
|
|
554
550
|
### Hardware Acceleration Methods
|
|
555
551
|
|
|
556
552
|
- **NVIDIA**: Uses CUDA for maximum performance
|
|
557
|
-
- **AMD**: Uses VAAPI with ROCm drivers (native Linux
|
|
553
|
+
- **AMD**: Uses VAAPI with ROCm drivers (native Linux)
|
|
558
554
|
- **Intel**: Uses VAAPI (Video Acceleration API)
|
|
559
555
|
- **Apple Silicon**: Uses VideoToolbox (M1/M2/M3/M4 chips on macOS)
|
|
560
|
-
- **
|
|
561
|
-
- **NVIDIA GPUs**: D3D11VA via `/dev/dxg`
|
|
562
|
-
- **AMD GPUs**: VAAPI via `/dev/dri` with ROCm support
|
|
556
|
+
- **Windows**: Uses D3D11VA (DirectX 11 Video Acceleration) for universal GPU support
|
|
563
557
|
|
|
564
558
|
### Docker GPU Requirements
|
|
565
559
|
|
|
@@ -582,25 +576,6 @@ services:
|
|
|
582
576
|
- /dev/dri:/dev/dri
|
|
583
577
|
```
|
|
584
578
|
|
|
585
|
-
#### WSL2
|
|
586
|
-
GPU support in WSL2 uses a hybrid detection approach:
|
|
587
|
-
|
|
588
|
-
**Primary Method (All Vendors):**
|
|
589
|
-
- Uses DirectX acceleration (D3D11VA) via `/dev/dxg`
|
|
590
|
-
- Works universally for NVIDIA, AMD, and Intel GPUs
|
|
591
|
-
- No special configuration needed
|
|
592
|
-
|
|
593
|
-
**Alternative Method (AMD/Intel):**
|
|
594
|
-
- If Linux drivers are properly loaded, may use VAAPI via `/dev/dri`
|
|
595
|
-
- Requires proper driver configuration in WSL2
|
|
596
|
-
- May offer better performance but is less reliable
|
|
597
|
-
|
|
598
|
-
**Important Notes:**
|
|
599
|
-
- AMD GPU support in WSL2 is still evolving
|
|
600
|
-
- ROCm support is limited and not officially supported by AMD in WSL2
|
|
601
|
-
- The script automatically detects and uses the best available method
|
|
602
|
-
- If VAAPI fails, automatically falls back to D3D11VA
|
|
603
|
-
|
|
604
579
|
## Usage Examples
|
|
605
580
|
|
|
606
581
|
### Docker Compose Examples
|
|
@@ -808,7 +783,7 @@ plex-generate-previews --log-level DEBUG
|
|
|
808
783
|
### General Questions
|
|
809
784
|
|
|
810
785
|
**Q: What's new in version 2.0.0?**
|
|
811
|
-
A: Version 2.0.0 introduces multi-GPU support, improved CLI interface, better error handling,
|
|
786
|
+
A: Version 2.0.0 introduces multi-GPU support, improved CLI interface, better error handling, and a complete rewrite with modern Python practices.
|
|
812
787
|
|
|
813
788
|
**Q: Does this work on Windows?**
|
|
814
789
|
A: Yes! Windows fully supports GPU acceleration via D3D11VA, which works with NVIDIA, AMD, and Intel GPUs. Install the latest GPU drivers and the tool will automatically detect and use your GPU for faster processing.
|
|
@@ -78,7 +78,7 @@ plex-generate-previews \
|
|
|
78
78
|
|
|
79
79
|
## Features
|
|
80
80
|
|
|
81
|
-
- **Multi-GPU Support**: NVIDIA, AMD, Intel, and
|
|
81
|
+
- **Multi-GPU Support**: NVIDIA, AMD, Intel, and Windows GPUs
|
|
82
82
|
- **Parallel Processing**: Configurable GPU and CPU worker threads
|
|
83
83
|
- **Hardware Acceleration**: CUDA, VAAPI, and D3D11VA
|
|
84
84
|
- **Library Filtering**: Process specific Plex libraries
|
|
@@ -99,7 +99,6 @@ plex-generate-previews \
|
|
|
99
99
|
|----------|---------|-------|
|
|
100
100
|
| **Linux** | ✅ Full | GPU + CPU support (CUDA, VAAPI, etc.) |
|
|
101
101
|
| **Docker** | ✅ Full | GPU + CPU support (Recommended) |
|
|
102
|
-
| **WSL2** | ✅ Full | GPU + CPU support (D3D11VA, VAAPI) |
|
|
103
102
|
| **macOS** | ✅ Full | VideoToolbox + CPU support |
|
|
104
103
|
| **Windows** | ✅ Full | D3D11VA GPU + CPU support |
|
|
105
104
|
|
|
@@ -113,7 +112,6 @@ plex-generate-previews \
|
|
|
113
112
|
- **NVIDIA**: CUDA-compatible GPU + NVIDIA drivers
|
|
114
113
|
- **AMD**: ROCm-compatible GPU + amdgpu drivers
|
|
115
114
|
- **Intel**: VAAPI-compatible iGPU/dGPU
|
|
116
|
-
- **WSL2**: D3D11VA-compatible GPU (Intel Arc, etc.)
|
|
117
115
|
|
|
118
116
|
## Installation Options
|
|
119
117
|
|
|
@@ -152,7 +150,6 @@ docker run --rm --gpus all \
|
|
|
152
150
|
**GPU Requirements:**
|
|
153
151
|
- **NVIDIA**: Install [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html)
|
|
154
152
|
- **AMD/Intel**: Mount `/dev/dri` with `--device /dev/dri:/dev/dri` (see [Troubleshooting](#troubleshooting) if you get permission errors)
|
|
155
|
-
- **WSL2**: No special configuration needed - automatically detects WSL2 GPUs
|
|
156
153
|
|
|
157
154
|
### Pip Installation
|
|
158
155
|
|
|
@@ -474,8 +471,7 @@ The tool automatically detects and supports multiple GPU types with hardware acc
|
|
|
474
471
|
| **AMD** | VAAPI | amdgpu drivers + ROCm | ✅ ROCm Docker support |
|
|
475
472
|
| **Intel** | VAAPI | Intel drivers + VA-API | ✅ Device access |
|
|
476
473
|
| **Apple Silicon** | VideoToolbox | macOS with FFmpeg + mediainfo | ❌ Native macOS only |
|
|
477
|
-
| **
|
|
478
|
-
| **WSL2 (AMD)** | VAAPI | WSL2 + ROCm + /dev/dri devices | ✅ Native WSL2 |
|
|
474
|
+
| **Windows** | D3D11VA | Windows with FFmpeg + latest GPU drivers | ❌ Native Windows only |
|
|
479
475
|
|
|
480
476
|
### GPU Detection
|
|
481
477
|
|
|
@@ -509,12 +505,10 @@ plex-generate-previews --gpu-selection "0"
|
|
|
509
505
|
### Hardware Acceleration Methods
|
|
510
506
|
|
|
511
507
|
- **NVIDIA**: Uses CUDA for maximum performance
|
|
512
|
-
- **AMD**: Uses VAAPI with ROCm drivers (native Linux
|
|
508
|
+
- **AMD**: Uses VAAPI with ROCm drivers (native Linux)
|
|
513
509
|
- **Intel**: Uses VAAPI (Video Acceleration API)
|
|
514
510
|
- **Apple Silicon**: Uses VideoToolbox (M1/M2/M3/M4 chips on macOS)
|
|
515
|
-
- **
|
|
516
|
-
- **NVIDIA GPUs**: D3D11VA via `/dev/dxg`
|
|
517
|
-
- **AMD GPUs**: VAAPI via `/dev/dri` with ROCm support
|
|
511
|
+
- **Windows**: Uses D3D11VA (DirectX 11 Video Acceleration) for universal GPU support
|
|
518
512
|
|
|
519
513
|
### Docker GPU Requirements
|
|
520
514
|
|
|
@@ -537,25 +531,6 @@ services:
|
|
|
537
531
|
- /dev/dri:/dev/dri
|
|
538
532
|
```
|
|
539
533
|
|
|
540
|
-
#### WSL2
|
|
541
|
-
GPU support in WSL2 uses a hybrid detection approach:
|
|
542
|
-
|
|
543
|
-
**Primary Method (All Vendors):**
|
|
544
|
-
- Uses DirectX acceleration (D3D11VA) via `/dev/dxg`
|
|
545
|
-
- Works universally for NVIDIA, AMD, and Intel GPUs
|
|
546
|
-
- No special configuration needed
|
|
547
|
-
|
|
548
|
-
**Alternative Method (AMD/Intel):**
|
|
549
|
-
- If Linux drivers are properly loaded, may use VAAPI via `/dev/dri`
|
|
550
|
-
- Requires proper driver configuration in WSL2
|
|
551
|
-
- May offer better performance but is less reliable
|
|
552
|
-
|
|
553
|
-
**Important Notes:**
|
|
554
|
-
- AMD GPU support in WSL2 is still evolving
|
|
555
|
-
- ROCm support is limited and not officially supported by AMD in WSL2
|
|
556
|
-
- The script automatically detects and uses the best available method
|
|
557
|
-
- If VAAPI fails, automatically falls back to D3D11VA
|
|
558
|
-
|
|
559
534
|
## Usage Examples
|
|
560
535
|
|
|
561
536
|
### Docker Compose Examples
|
|
@@ -763,7 +738,7 @@ plex-generate-previews --log-level DEBUG
|
|
|
763
738
|
### General Questions
|
|
764
739
|
|
|
765
740
|
**Q: What's new in version 2.0.0?**
|
|
766
|
-
A: Version 2.0.0 introduces multi-GPU support, improved CLI interface, better error handling,
|
|
741
|
+
A: Version 2.0.0 introduces multi-GPU support, improved CLI interface, better error handling, and a complete rewrite with modern Python practices.
|
|
767
742
|
|
|
768
743
|
**Q: Does this work on Windows?**
|
|
769
744
|
A: Yes! Windows fully supports GPU acceleration via D3D11VA, which works with NVIDIA, AMD, and Intel GPUs. Install the latest GPU drivers and the tool will automatically detect and use your GPU for faster processing.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Plex Video Preview Generator
|
|
3
3
|
|
|
4
4
|
A tool for generating video preview thumbnails for Plex Media Server.
|
|
5
|
-
Supports GPU acceleration (NVIDIA, AMD, Intel,
|
|
5
|
+
Supports GPU acceleration (NVIDIA, AMD, Intel, Windows) and CPU processing.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import os
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '2.
|
|
32
|
-
__version_tuple__ = version_tuple = (2,
|
|
31
|
+
__version__ = version = '2.5.1.dev0'
|
|
32
|
+
__version_tuple__ = version_tuple = (2, 5, 1, 'dev0')
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g5762a5480'
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
GPU detection for video processing acceleration.
|
|
3
3
|
|
|
4
4
|
Detects available GPU hardware and returns appropriate configuration
|
|
5
|
-
for FFmpeg hardware acceleration. Supports NVIDIA, AMD, Intel, Apple (macOS), and
|
|
5
|
+
for FFmpeg hardware acceleration. Supports NVIDIA, AMD, Intel, Apple (macOS), and Windows GPUs.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import os
|
|
@@ -54,12 +54,6 @@ GPU_ACCELERATION_MAP = {
|
|
|
54
54
|
'requires_runtime': False,
|
|
55
55
|
'test_encoder': None # Use hwaccel test instead
|
|
56
56
|
},
|
|
57
|
-
'WSL2': {
|
|
58
|
-
'primary': 'D3D11VA',
|
|
59
|
-
'fallback': None,
|
|
60
|
-
'requires_runtime': False,
|
|
61
|
-
'test_encoder': None # Use hwaccel test instead
|
|
62
|
-
},
|
|
63
57
|
'WINDOWS_GPU': {
|
|
64
58
|
'primary': 'D3D11VA',
|
|
65
59
|
'fallback': None,
|
|
@@ -377,31 +371,6 @@ def _test_hwaccel_functionality(hwaccel: str, device_path: Optional[str] = None)
|
|
|
377
371
|
return False
|
|
378
372
|
|
|
379
373
|
|
|
380
|
-
def _is_wsl2() -> bool:
|
|
381
|
-
"""
|
|
382
|
-
Detect if running in WSL2 by checking for /dev/dxg device.
|
|
383
|
-
|
|
384
|
-
Per Microsoft's documentation, /dev/dxg is the WSL2 GPU passthrough device
|
|
385
|
-
exposed by the dxgkrnl driver.
|
|
386
|
-
|
|
387
|
-
Reference: https://devblogs.microsoft.com/directx/directx-heart-linux/
|
|
388
|
-
|
|
389
|
-
Returns:
|
|
390
|
-
bool: True if running in WSL2 with GPU support
|
|
391
|
-
"""
|
|
392
|
-
return os.path.exists('/dev/dxg')
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
def _detect_rocm_gpu() -> bool:
|
|
396
|
-
"""
|
|
397
|
-
Detect if ROCm (AMD GPU runtime) is available in WSL2.
|
|
398
|
-
|
|
399
|
-
Checks for /dev/kfd (Kernel Fusion Driver) which is the ROCm device.
|
|
400
|
-
|
|
401
|
-
Returns:
|
|
402
|
-
bool: True if ROCm device is available
|
|
403
|
-
"""
|
|
404
|
-
return os.path.exists('/dev/kfd')
|
|
405
374
|
|
|
406
375
|
|
|
407
376
|
def _is_macos() -> bool:
|
|
@@ -416,7 +385,7 @@ def _is_macos() -> bool:
|
|
|
416
385
|
|
|
417
386
|
def _is_windows() -> bool:
|
|
418
387
|
"""
|
|
419
|
-
Detect if running on native Windows
|
|
388
|
+
Detect if running on native Windows.
|
|
420
389
|
|
|
421
390
|
Returns:
|
|
422
391
|
bool: True if running on Windows
|
|
@@ -444,8 +413,7 @@ def _detect_windows_d3d11va() -> Optional[Tuple[str, str, Dict[str, Any]]]:
|
|
|
444
413
|
gpu_info = {
|
|
445
414
|
'name': 'Windows GPU',
|
|
446
415
|
'acceleration': 'D3D11VA',
|
|
447
|
-
'device_path': 'd3d11va'
|
|
448
|
-
'wsl2': False
|
|
416
|
+
'device_path': 'd3d11va'
|
|
449
417
|
}
|
|
450
418
|
logger.debug("✓ Windows D3D11VA hardware acceleration is working")
|
|
451
419
|
return ('WINDOWS_GPU', 'd3d11va', gpu_info)
|
|
@@ -554,58 +522,6 @@ def _get_gpu_devices() -> List[Tuple[str, str, str]]:
|
|
|
554
522
|
return devices
|
|
555
523
|
|
|
556
524
|
|
|
557
|
-
def _get_wsl2_render_devices() -> List[Tuple[str, str, str]]:
|
|
558
|
-
"""
|
|
559
|
-
Fallback GPU detection for WSL2 when /sys/class/drm enumeration fails.
|
|
560
|
-
|
|
561
|
-
In WSL2, especially with AMD GPUs, /sys/class/drm may not properly enumerate
|
|
562
|
-
devices, but render devices might still exist in /dev/dri. This function
|
|
563
|
-
directly checks for render devices and attempts to identify their vendor.
|
|
564
|
-
|
|
565
|
-
Returns:
|
|
566
|
-
List[Tuple[str, str, str]]: List of (card_name, render_device, driver) tuples
|
|
567
|
-
"""
|
|
568
|
-
devices = []
|
|
569
|
-
dri_dir = "/dev/dri"
|
|
570
|
-
|
|
571
|
-
if not os.path.exists(dri_dir):
|
|
572
|
-
logger.debug(f"DRI directory {dri_dir} does not exist")
|
|
573
|
-
return devices
|
|
574
|
-
|
|
575
|
-
try:
|
|
576
|
-
entries = os.listdir(dri_dir)
|
|
577
|
-
render_devices = [e for e in entries if e.startswith("renderD")]
|
|
578
|
-
|
|
579
|
-
if not render_devices:
|
|
580
|
-
logger.debug("No render devices found in /dev/dri")
|
|
581
|
-
return devices
|
|
582
|
-
|
|
583
|
-
logger.debug(f"Found render devices in WSL2: {render_devices}")
|
|
584
|
-
|
|
585
|
-
for render_device_name in sorted(render_devices):
|
|
586
|
-
render_device_path = f"/dev/dri/{render_device_name}"
|
|
587
|
-
|
|
588
|
-
# Try to determine vendor using lspci
|
|
589
|
-
vendor = _detect_gpu_type_from_lspci()
|
|
590
|
-
if vendor == 'UNKNOWN':
|
|
591
|
-
# Check if ROCm is available (indicates AMD GPU)
|
|
592
|
-
if _detect_rocm_gpu():
|
|
593
|
-
vendor = 'AMD'
|
|
594
|
-
logger.debug(f"Detected AMD GPU via ROCm for {render_device_path}")
|
|
595
|
-
else:
|
|
596
|
-
vendor = 'amdgpu' # fallback to amdgpu driver name
|
|
597
|
-
|
|
598
|
-
# Create a synthetic card name
|
|
599
|
-
card_name = f"wsl2-{render_device_name}"
|
|
600
|
-
driver = vendor.lower()
|
|
601
|
-
|
|
602
|
-
devices.append((card_name, render_device_path, driver))
|
|
603
|
-
logger.debug(f"WSL2 GPU detected: {card_name} -> {render_device_path} (driver: {driver})")
|
|
604
|
-
|
|
605
|
-
except Exception as e:
|
|
606
|
-
logger.debug(f"Error detecting WSL2 render devices: {e}")
|
|
607
|
-
|
|
608
|
-
return devices
|
|
609
525
|
|
|
610
526
|
|
|
611
527
|
def _get_gpu_vendor_from_driver(driver_name: str) -> str:
|
|
@@ -734,10 +650,6 @@ def _log_system_info() -> None:
|
|
|
734
650
|
logger.debug(f"Python version: {platform.python_version()}")
|
|
735
651
|
logger.debug(f"FFmpeg path: {os.environ.get('FFMPEG_PATH', 'ffmpeg')}")
|
|
736
652
|
|
|
737
|
-
# Check for WSL2
|
|
738
|
-
if _is_wsl2():
|
|
739
|
-
logger.debug("Running in WSL2 (detected /dev/dxg device)")
|
|
740
|
-
|
|
741
653
|
# Check FFmpeg version
|
|
742
654
|
_check_ffmpeg_version()
|
|
743
655
|
|
|
@@ -793,7 +705,7 @@ def get_gpu_name(gpu_type: str, gpu_device: str) -> str:
|
|
|
793
705
|
Extract GPU model name from system.
|
|
794
706
|
|
|
795
707
|
Args:
|
|
796
|
-
gpu_type: Type of GPU ('NVIDIA', 'AMD', 'INTEL', '
|
|
708
|
+
gpu_type: Type of GPU ('NVIDIA', 'AMD', 'INTEL', 'APPLE')
|
|
797
709
|
gpu_device: GPU device path or info string
|
|
798
710
|
|
|
799
711
|
Returns:
|
|
@@ -810,12 +722,12 @@ def get_gpu_name(gpu_type: str, gpu_device: str) -> str:
|
|
|
810
722
|
return gpu_names[0] # Return first GPU name
|
|
811
723
|
return "NVIDIA GPU"
|
|
812
724
|
|
|
813
|
-
elif gpu_type == 'WSL2':
|
|
814
|
-
return "WSL2 GPU"
|
|
815
|
-
|
|
816
725
|
elif gpu_type == 'APPLE':
|
|
817
726
|
return _get_apple_gpu_name()
|
|
818
727
|
|
|
728
|
+
elif gpu_type == 'WINDOWS_GPU':
|
|
729
|
+
return "Windows GPU"
|
|
730
|
+
|
|
819
731
|
elif gpu_type in ('AMD', 'INTEL') and gpu_device.startswith('/dev/dri/'):
|
|
820
732
|
# Try to get GPU info from lspci
|
|
821
733
|
gpu_name = _parse_lspci_gpu_name(gpu_type)
|
|
@@ -851,8 +763,6 @@ def format_gpu_info(gpu_type: str, gpu_device: str, gpu_name: str, acceleration:
|
|
|
851
763
|
# Fallback to old logic for backward compatibility
|
|
852
764
|
if gpu_type == 'NVIDIA':
|
|
853
765
|
return f"{gpu_name} (CUDA)"
|
|
854
|
-
elif gpu_type == 'WSL2':
|
|
855
|
-
return f"{gpu_name} (D3D11VA)"
|
|
856
766
|
elif gpu_type == 'WINDOWS_GPU':
|
|
857
767
|
return f"{gpu_name} (D3D11VA - Universal Windows GPU)"
|
|
858
768
|
elif gpu_type == 'APPLE':
|
|
@@ -865,7 +775,7 @@ def format_gpu_info(gpu_type: str, gpu_device: str, gpu_name: str, acceleration:
|
|
|
865
775
|
return f"{gpu_name} ({gpu_type})"
|
|
866
776
|
|
|
867
777
|
|
|
868
|
-
def _test_acceleration_method(vendor: str, acceleration: str, device_path: Optional[str] = None
|
|
778
|
+
def _test_acceleration_method(vendor: str, acceleration: str, device_path: Optional[str] = None) -> bool:
|
|
869
779
|
"""
|
|
870
780
|
Test if a specific acceleration method works for a GPU vendor.
|
|
871
781
|
|
|
@@ -873,7 +783,6 @@ def _test_acceleration_method(vendor: str, acceleration: str, device_path: Optio
|
|
|
873
783
|
vendor: GPU vendor ('NVIDIA', 'AMD', 'INTEL', etc.)
|
|
874
784
|
acceleration: Acceleration method ('CUDA', 'VAAPI', 'D3D11VA', etc.)
|
|
875
785
|
device_path: Device path for VAAPI (e.g., '/dev/dri/renderD128'), or 'cuda' for NVIDIA
|
|
876
|
-
is_wsl2: Whether running in WSL2 environment
|
|
877
786
|
|
|
878
787
|
Returns:
|
|
879
788
|
bool: True if acceleration method works
|
|
@@ -908,16 +817,12 @@ def _test_acceleration_method(vendor: str, acceleration: str, device_path: Optio
|
|
|
908
817
|
logger.debug(f"Unknown acceleration method: {acceleration}")
|
|
909
818
|
return False
|
|
910
819
|
|
|
911
|
-
#
|
|
912
|
-
if test_passed
|
|
913
|
-
|
|
914
|
-
logger.debug(f"✓ {vendor} {acceleration} hardware acceleration test passed")
|
|
915
|
-
else:
|
|
916
|
-
logger.debug(f"✓ {vendor} {acceleration} available in WSL2 (functionality test skipped)")
|
|
917
|
-
return True
|
|
820
|
+
# Return test result
|
|
821
|
+
if test_passed:
|
|
822
|
+
logger.debug(f"✓ {vendor} {acceleration} hardware acceleration test passed")
|
|
918
823
|
else:
|
|
919
824
|
logger.debug(f"✗ {vendor} {acceleration} functionality test failed")
|
|
920
|
-
|
|
825
|
+
return test_passed
|
|
921
826
|
|
|
922
827
|
|
|
923
828
|
def detect_all_gpus() -> List[Tuple[str, str, dict]]:
|
|
@@ -929,7 +834,7 @@ def detect_all_gpus() -> List[Tuple[str, str, dict]]:
|
|
|
929
834
|
|
|
930
835
|
Returns:
|
|
931
836
|
List[Tuple[str, str, dict]]: List of (gpu_type, gpu_device, gpu_info_dict)
|
|
932
|
-
- gpu_type: 'NVIDIA', 'AMD', 'INTEL', '
|
|
837
|
+
- gpu_type: 'NVIDIA', 'AMD', 'INTEL', 'APPLE', 'WINDOWS_GPU'
|
|
933
838
|
- gpu_device: Device path or info string
|
|
934
839
|
- gpu_info_dict: Dictionary with GPU details (name, vram, etc.)
|
|
935
840
|
"""
|
|
@@ -939,11 +844,6 @@ def detect_all_gpus() -> List[Tuple[str, str, dict]]:
|
|
|
939
844
|
detected_gpus = []
|
|
940
845
|
detected_vendors = set() # Track which vendors we've already detected
|
|
941
846
|
|
|
942
|
-
# Detect if running in WSL2 - makes detection more lenient
|
|
943
|
-
is_wsl2 = _is_wsl2()
|
|
944
|
-
if is_wsl2:
|
|
945
|
-
logger.debug("Detected WSL2 environment (/dev/dxg present) - GPU functionality tests may be skipped")
|
|
946
|
-
|
|
947
847
|
# Step 1: Enumerate physical GPUs from /dev/dri (Linux only)
|
|
948
848
|
logger.debug("=== Enumerating Physical GPUs ===")
|
|
949
849
|
physical_gpus = _get_gpu_devices() # Returns: [(card_name, render_device, driver)]
|
|
@@ -952,14 +852,6 @@ def detect_all_gpus() -> List[Tuple[str, str, dict]]:
|
|
|
952
852
|
if platform.system() == 'Linux':
|
|
953
853
|
if not physical_gpus:
|
|
954
854
|
logger.debug("No physical GPUs found in /dev/dri")
|
|
955
|
-
# In WSL2, try fallback detection for render devices
|
|
956
|
-
if is_wsl2:
|
|
957
|
-
logger.debug("WSL2 detected - trying fallback render device detection")
|
|
958
|
-
physical_gpus = _get_wsl2_render_devices()
|
|
959
|
-
if physical_gpus:
|
|
960
|
-
logger.debug(f"Found {len(physical_gpus)} GPU(s) via WSL2 fallback detection")
|
|
961
|
-
for card_name, render_device, driver in physical_gpus:
|
|
962
|
-
logger.debug(f" {card_name}: {render_device} (driver: {driver})")
|
|
963
855
|
else:
|
|
964
856
|
logger.debug(f"Found {len(physical_gpus)} physical GPU(s) in /dev/dri")
|
|
965
857
|
for card_name, render_device, driver in physical_gpus:
|
|
@@ -992,14 +884,13 @@ def detect_all_gpus() -> List[Tuple[str, str, dict]]:
|
|
|
992
884
|
# Test primary acceleration method
|
|
993
885
|
logger.debug(f" Testing primary method: {primary_method}")
|
|
994
886
|
logger.info(f" Testing {primary_method} acceleration...")
|
|
995
|
-
if _test_acceleration_method(vendor, primary_method, device_path
|
|
887
|
+
if _test_acceleration_method(vendor, primary_method, device_path):
|
|
996
888
|
gpu_name = get_gpu_name(vendor, device_path)
|
|
997
889
|
gpu_info = {
|
|
998
890
|
'name': gpu_name,
|
|
999
891
|
'acceleration': primary_method,
|
|
1000
892
|
'device_path': device_path,
|
|
1001
893
|
'render_device': render_device, # Store the actual /dev/dri device
|
|
1002
|
-
'wsl2': is_wsl2,
|
|
1003
894
|
'card': card_name,
|
|
1004
895
|
'driver': driver
|
|
1005
896
|
}
|
|
@@ -1023,14 +914,13 @@ def detect_all_gpus() -> List[Tuple[str, str, dict]]:
|
|
|
1023
914
|
logger.info(f" Testing fallback {fallback_method} acceleration...")
|
|
1024
915
|
fallback_device_path = render_device if fallback_method == 'VAAPI' else device_path
|
|
1025
916
|
|
|
1026
|
-
if _test_acceleration_method(vendor, fallback_method, fallback_device_path
|
|
917
|
+
if _test_acceleration_method(vendor, fallback_method, fallback_device_path):
|
|
1027
918
|
gpu_name = get_gpu_name(vendor, fallback_device_path)
|
|
1028
919
|
gpu_info = {
|
|
1029
920
|
'name': gpu_name,
|
|
1030
921
|
'acceleration': fallback_method,
|
|
1031
922
|
'device_path': fallback_device_path,
|
|
1032
923
|
'render_device': render_device,
|
|
1033
|
-
'wsl2': is_wsl2,
|
|
1034
924
|
'card': card_name,
|
|
1035
925
|
'driver': driver
|
|
1036
926
|
}
|
|
@@ -1042,47 +932,21 @@ def detect_all_gpus() -> List[Tuple[str, str, dict]]:
|
|
|
1042
932
|
else:
|
|
1043
933
|
logger.warning(f" ❌ {card_name}: No fallback available, GPU unusable")
|
|
1044
934
|
|
|
1045
|
-
# Step 3:
|
|
1046
|
-
if is_wsl2:
|
|
1047
|
-
logger.debug("Testing WSL2 D3D11VA acceleration...")
|
|
1048
|
-
logger.info(" Checking WSL2 GPU...")
|
|
1049
|
-
logger.info(" Testing D3D11VA acceleration...")
|
|
1050
|
-
if _test_acceleration_method('WSL2', 'D3D11VA', 'd3d11va', is_wsl2):
|
|
1051
|
-
# Try to identify actual GPU for better naming
|
|
1052
|
-
gpu_vendor = _detect_gpu_type_from_lspci()
|
|
1053
|
-
if gpu_vendor != 'UNKNOWN':
|
|
1054
|
-
gpu_name = f"{gpu_vendor} GPU (WSL2 DirectX)"
|
|
1055
|
-
else:
|
|
1056
|
-
gpu_name = "WSL2 GPU (DirectX)"
|
|
1057
|
-
|
|
1058
|
-
gpu_info = {
|
|
1059
|
-
'name': gpu_name,
|
|
1060
|
-
'acceleration': 'D3D11VA',
|
|
1061
|
-
'device_path': 'd3d11va',
|
|
1062
|
-
'wsl2': is_wsl2
|
|
1063
|
-
}
|
|
1064
|
-
detected_gpus.append(('WSL2', 'd3d11va', gpu_info))
|
|
1065
|
-
logger.info(f" ✅ {gpu_name} working")
|
|
1066
|
-
logger.info(" 💡 Using DirectX acceleration (universal WSL2 method)")
|
|
1067
|
-
if gpu_vendor == 'AMD':
|
|
1068
|
-
logger.info(" 💡 Note: AMD GPUs in WSL2 may have better performance with native Linux drivers")
|
|
1069
|
-
logger.info(" if properly configured, but DirectX acceleration is working.")
|
|
1070
|
-
|
|
1071
|
-
# Native Windows: try D3D11VA if ffmpeg reports it, even without /dev/dxg
|
|
935
|
+
# Step 3: Native Windows - try D3D11VA if ffmpeg reports it
|
|
1072
936
|
if platform.system() == 'Windows':
|
|
1073
937
|
hwaccels = _get_ffmpeg_hwaccels()
|
|
1074
938
|
logger.debug(f"Windows platform detected; FFmpeg hwaccels: {hwaccels}")
|
|
1075
939
|
if 'd3d11va' in hwaccels:
|
|
1076
940
|
logger.info(" Checking Windows D3D11VA GPU...")
|
|
1077
941
|
logger.info(" Testing D3D11VA acceleration...")
|
|
1078
|
-
if _test_acceleration_method('
|
|
942
|
+
if _test_acceleration_method('WINDOWS_GPU', 'D3D11VA', 'd3d11va'):
|
|
1079
943
|
gpu_name = "Windows GPU"
|
|
1080
944
|
gpu_info = {
|
|
1081
945
|
'name': gpu_name,
|
|
1082
946
|
'acceleration': 'D3D11VA',
|
|
1083
947
|
'device_path': 'd3d11va',
|
|
1084
948
|
}
|
|
1085
|
-
detected_gpus.append(('
|
|
949
|
+
detected_gpus.append(('WINDOWS_GPU', 'd3d11va', gpu_info))
|
|
1086
950
|
logger.info(" ✅ Windows D3D11VA working")
|
|
1087
951
|
else:
|
|
1088
952
|
logger.debug("d3d11va not reported by FFmpeg; skipping Windows D3D11VA probe")
|
|
@@ -1092,13 +956,12 @@ def detect_all_gpus() -> List[Tuple[str, str, dict]]:
|
|
|
1092
956
|
logger.debug("Detected macOS platform, testing VideoToolbox acceleration...")
|
|
1093
957
|
logger.info(" Checking Apple GPU...")
|
|
1094
958
|
logger.info(" Testing VideoToolbox acceleration...")
|
|
1095
|
-
if _test_acceleration_method('APPLE', 'VIDEOTOOLBOX', 'videotoolbox'
|
|
959
|
+
if _test_acceleration_method('APPLE', 'VIDEOTOOLBOX', 'videotoolbox'):
|
|
1096
960
|
gpu_name = get_gpu_name('APPLE', 'videotoolbox')
|
|
1097
961
|
gpu_info = {
|
|
1098
962
|
'name': gpu_name,
|
|
1099
963
|
'acceleration': 'VIDEOTOOLBOX',
|
|
1100
|
-
'device_path': 'videotoolbox'
|
|
1101
|
-
'wsl2': False
|
|
964
|
+
'device_path': 'videotoolbox'
|
|
1102
965
|
}
|
|
1103
966
|
detected_gpus.append(('APPLE', 'videotoolbox', gpu_info))
|
|
1104
967
|
logger.info(" ✅ Apple VideoToolbox working")
|
|
@@ -153,7 +153,7 @@ def generate_images(video_file: str, output_folder: str, gpu: Optional[str],
|
|
|
153
153
|
Args:
|
|
154
154
|
video_file: Path to input video file
|
|
155
155
|
output_folder: Directory where thumbnail images will be written
|
|
156
|
-
gpu: GPU type ('NVIDIA', 'AMD', 'INTEL', '
|
|
156
|
+
gpu: GPU type ('NVIDIA', 'AMD', 'INTEL', 'WINDOWS_GPU', 'APPLE', or None)
|
|
157
157
|
gpu_device_path: GPU device path (e.g., '/dev/dri/renderD128' for VAAPI)
|
|
158
158
|
config: Configuration object
|
|
159
159
|
progress_callback: Optional progress callback for UI updates
|
|
@@ -194,7 +194,7 @@ def generate_images(video_file: str, output_folder: str, gpu: Optional[str],
|
|
|
194
194
|
hw_local = True
|
|
195
195
|
if gpu == 'NVIDIA':
|
|
196
196
|
args += ["-hwaccel", "cuda"]
|
|
197
|
-
elif gpu == '
|
|
197
|
+
elif gpu == 'WINDOWS_GPU':
|
|
198
198
|
args += ["-hwaccel", "d3d11va"]
|
|
199
199
|
elif gpu == 'APPLE':
|
|
200
200
|
args += ["-hwaccel", "videotoolbox"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plex-generate-previews
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.1.dev0
|
|
4
4
|
Summary: Generate video preview thumbnails for Plex Media Server
|
|
5
5
|
Author-email: stevezau <stevezau@example.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -123,7 +123,7 @@ plex-generate-previews \
|
|
|
123
123
|
|
|
124
124
|
## Features
|
|
125
125
|
|
|
126
|
-
- **Multi-GPU Support**: NVIDIA, AMD, Intel, and
|
|
126
|
+
- **Multi-GPU Support**: NVIDIA, AMD, Intel, and Windows GPUs
|
|
127
127
|
- **Parallel Processing**: Configurable GPU and CPU worker threads
|
|
128
128
|
- **Hardware Acceleration**: CUDA, VAAPI, and D3D11VA
|
|
129
129
|
- **Library Filtering**: Process specific Plex libraries
|
|
@@ -144,7 +144,6 @@ plex-generate-previews \
|
|
|
144
144
|
|----------|---------|-------|
|
|
145
145
|
| **Linux** | ✅ Full | GPU + CPU support (CUDA, VAAPI, etc.) |
|
|
146
146
|
| **Docker** | ✅ Full | GPU + CPU support (Recommended) |
|
|
147
|
-
| **WSL2** | ✅ Full | GPU + CPU support (D3D11VA, VAAPI) |
|
|
148
147
|
| **macOS** | ✅ Full | VideoToolbox + CPU support |
|
|
149
148
|
| **Windows** | ✅ Full | D3D11VA GPU + CPU support |
|
|
150
149
|
|
|
@@ -158,7 +157,6 @@ plex-generate-previews \
|
|
|
158
157
|
- **NVIDIA**: CUDA-compatible GPU + NVIDIA drivers
|
|
159
158
|
- **AMD**: ROCm-compatible GPU + amdgpu drivers
|
|
160
159
|
- **Intel**: VAAPI-compatible iGPU/dGPU
|
|
161
|
-
- **WSL2**: D3D11VA-compatible GPU (Intel Arc, etc.)
|
|
162
160
|
|
|
163
161
|
## Installation Options
|
|
164
162
|
|
|
@@ -197,7 +195,6 @@ docker run --rm --gpus all \
|
|
|
197
195
|
**GPU Requirements:**
|
|
198
196
|
- **NVIDIA**: Install [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html)
|
|
199
197
|
- **AMD/Intel**: Mount `/dev/dri` with `--device /dev/dri:/dev/dri` (see [Troubleshooting](#troubleshooting) if you get permission errors)
|
|
200
|
-
- **WSL2**: No special configuration needed - automatically detects WSL2 GPUs
|
|
201
198
|
|
|
202
199
|
### Pip Installation
|
|
203
200
|
|
|
@@ -519,8 +516,7 @@ The tool automatically detects and supports multiple GPU types with hardware acc
|
|
|
519
516
|
| **AMD** | VAAPI | amdgpu drivers + ROCm | ✅ ROCm Docker support |
|
|
520
517
|
| **Intel** | VAAPI | Intel drivers + VA-API | ✅ Device access |
|
|
521
518
|
| **Apple Silicon** | VideoToolbox | macOS with FFmpeg + mediainfo | ❌ Native macOS only |
|
|
522
|
-
| **
|
|
523
|
-
| **WSL2 (AMD)** | VAAPI | WSL2 + ROCm + /dev/dri devices | ✅ Native WSL2 |
|
|
519
|
+
| **Windows** | D3D11VA | Windows with FFmpeg + latest GPU drivers | ❌ Native Windows only |
|
|
524
520
|
|
|
525
521
|
### GPU Detection
|
|
526
522
|
|
|
@@ -554,12 +550,10 @@ plex-generate-previews --gpu-selection "0"
|
|
|
554
550
|
### Hardware Acceleration Methods
|
|
555
551
|
|
|
556
552
|
- **NVIDIA**: Uses CUDA for maximum performance
|
|
557
|
-
- **AMD**: Uses VAAPI with ROCm drivers (native Linux
|
|
553
|
+
- **AMD**: Uses VAAPI with ROCm drivers (native Linux)
|
|
558
554
|
- **Intel**: Uses VAAPI (Video Acceleration API)
|
|
559
555
|
- **Apple Silicon**: Uses VideoToolbox (M1/M2/M3/M4 chips on macOS)
|
|
560
|
-
- **
|
|
561
|
-
- **NVIDIA GPUs**: D3D11VA via `/dev/dxg`
|
|
562
|
-
- **AMD GPUs**: VAAPI via `/dev/dri` with ROCm support
|
|
556
|
+
- **Windows**: Uses D3D11VA (DirectX 11 Video Acceleration) for universal GPU support
|
|
563
557
|
|
|
564
558
|
### Docker GPU Requirements
|
|
565
559
|
|
|
@@ -582,25 +576,6 @@ services:
|
|
|
582
576
|
- /dev/dri:/dev/dri
|
|
583
577
|
```
|
|
584
578
|
|
|
585
|
-
#### WSL2
|
|
586
|
-
GPU support in WSL2 uses a hybrid detection approach:
|
|
587
|
-
|
|
588
|
-
**Primary Method (All Vendors):**
|
|
589
|
-
- Uses DirectX acceleration (D3D11VA) via `/dev/dxg`
|
|
590
|
-
- Works universally for NVIDIA, AMD, and Intel GPUs
|
|
591
|
-
- No special configuration needed
|
|
592
|
-
|
|
593
|
-
**Alternative Method (AMD/Intel):**
|
|
594
|
-
- If Linux drivers are properly loaded, may use VAAPI via `/dev/dri`
|
|
595
|
-
- Requires proper driver configuration in WSL2
|
|
596
|
-
- May offer better performance but is less reliable
|
|
597
|
-
|
|
598
|
-
**Important Notes:**
|
|
599
|
-
- AMD GPU support in WSL2 is still evolving
|
|
600
|
-
- ROCm support is limited and not officially supported by AMD in WSL2
|
|
601
|
-
- The script automatically detects and uses the best available method
|
|
602
|
-
- If VAAPI fails, automatically falls back to D3D11VA
|
|
603
|
-
|
|
604
579
|
## Usage Examples
|
|
605
580
|
|
|
606
581
|
### Docker Compose Examples
|
|
@@ -808,7 +783,7 @@ plex-generate-previews --log-level DEBUG
|
|
|
808
783
|
### General Questions
|
|
809
784
|
|
|
810
785
|
**Q: What's new in version 2.0.0?**
|
|
811
|
-
A: Version 2.0.0 introduces multi-GPU support, improved CLI interface, better error handling,
|
|
786
|
+
A: Version 2.0.0 introduces multi-GPU support, improved CLI interface, better error handling, and a complete rewrite with modern Python practices.
|
|
812
787
|
|
|
813
788
|
**Q: Does this work on Windows?**
|
|
814
789
|
A: Yes! Windows fully supports GPU acceleration via D3D11VA, which works with NVIDIA, AMD, and Intel GPUs. Install the latest GPU drivers and the tool will automatically detect and use your GPU for faster processing.
|
|
@@ -15,9 +15,7 @@ from plex_generate_previews.gpu_detection import (
|
|
|
15
15
|
_get_gpu_devices,
|
|
16
16
|
_determine_vaapi_gpu_type,
|
|
17
17
|
get_gpu_name,
|
|
18
|
-
_get_ffmpeg_hwaccels
|
|
19
|
-
_get_wsl2_render_devices,
|
|
20
|
-
_detect_rocm_gpu
|
|
18
|
+
_get_ffmpeg_hwaccels
|
|
21
19
|
)
|
|
22
20
|
|
|
23
21
|
|
|
@@ -80,9 +78,8 @@ class TestDetectAllGPUs:
|
|
|
80
78
|
def test_detect_all_gpus_none(self, mock_devices):
|
|
81
79
|
"""Test when no GPUs are detected."""
|
|
82
80
|
mock_devices.return_value = []
|
|
83
|
-
# Ensure platform-specific paths (macOS
|
|
81
|
+
# Ensure platform-specific paths (macOS) are not taken in this test
|
|
84
82
|
with patch('plex_generate_previews.gpu_detection._is_macos', return_value=False), \
|
|
85
|
-
patch('plex_generate_previews.gpu_detection._is_wsl2', return_value=False), \
|
|
86
83
|
patch('plex_generate_previews.gpu_detection._get_ffmpeg_hwaccels', return_value=[]):
|
|
87
84
|
gpus = detect_all_gpus()
|
|
88
85
|
|
|
@@ -394,11 +391,11 @@ class TestGetGPUName:
|
|
|
394
391
|
assert 'NVIDIA' in name
|
|
395
392
|
assert 'GPU' in name
|
|
396
393
|
|
|
397
|
-
def
|
|
398
|
-
"""Test
|
|
399
|
-
name = get_gpu_name('
|
|
394
|
+
def test_get_gpu_name_windows(self):
|
|
395
|
+
"""Test Windows GPU name."""
|
|
396
|
+
name = get_gpu_name('WINDOWS_GPU', 'd3d11va')
|
|
400
397
|
|
|
401
|
-
assert '
|
|
398
|
+
assert 'Windows' in name
|
|
402
399
|
assert 'GPU' in name
|
|
403
400
|
|
|
404
401
|
@patch('subprocess.run')
|
|
@@ -457,113 +454,6 @@ d3d11va
|
|
|
457
454
|
assert hwaccels == []
|
|
458
455
|
|
|
459
456
|
|
|
460
|
-
class TestWSL2AMDGPUDetection:
|
|
461
|
-
"""Test WSL2 AMD GPU detection functionality."""
|
|
462
|
-
|
|
463
|
-
@patch('os.path.exists')
|
|
464
|
-
def test_detect_rocm_gpu_available(self, mock_exists):
|
|
465
|
-
"""Test ROCm GPU detection when /dev/kfd exists."""
|
|
466
|
-
mock_exists.return_value = True
|
|
467
|
-
|
|
468
|
-
result = _detect_rocm_gpu()
|
|
469
|
-
|
|
470
|
-
assert result is True
|
|
471
|
-
mock_exists.assert_called_with('/dev/kfd')
|
|
472
|
-
|
|
473
|
-
@patch('os.path.exists')
|
|
474
|
-
def test_detect_rocm_gpu_not_available(self, mock_exists):
|
|
475
|
-
"""Test ROCm GPU detection when /dev/kfd doesn't exist."""
|
|
476
|
-
mock_exists.return_value = False
|
|
477
|
-
|
|
478
|
-
result = _detect_rocm_gpu()
|
|
479
|
-
|
|
480
|
-
assert result is False
|
|
481
|
-
mock_exists.assert_called_with('/dev/kfd')
|
|
482
|
-
|
|
483
|
-
@patch('plex_generate_previews.gpu_detection._detect_gpu_type_from_lspci')
|
|
484
|
-
@patch('plex_generate_previews.gpu_detection._detect_rocm_gpu')
|
|
485
|
-
@patch('os.listdir')
|
|
486
|
-
@patch('os.path.exists')
|
|
487
|
-
def test_get_wsl2_render_devices_amd_with_rocm(self, mock_exists, mock_listdir,
|
|
488
|
-
mock_rocm, mock_lspci):
|
|
489
|
-
"""Test WSL2 render device detection with AMD GPU and ROCm."""
|
|
490
|
-
mock_exists.return_value = True
|
|
491
|
-
mock_listdir.return_value = ['renderD128', 'card0']
|
|
492
|
-
mock_lspci.return_value = 'UNKNOWN'
|
|
493
|
-
mock_rocm.return_value = True
|
|
494
|
-
|
|
495
|
-
devices = _get_wsl2_render_devices()
|
|
496
|
-
|
|
497
|
-
assert len(devices) == 1
|
|
498
|
-
assert devices[0][0] == 'wsl2-renderD128'
|
|
499
|
-
assert devices[0][1] == '/dev/dri/renderD128'
|
|
500
|
-
assert devices[0][2] == 'amd'
|
|
501
|
-
|
|
502
|
-
@patch('plex_generate_previews.gpu_detection._detect_gpu_type_from_lspci')
|
|
503
|
-
@patch('plex_generate_previews.gpu_detection._detect_rocm_gpu')
|
|
504
|
-
@patch('os.listdir')
|
|
505
|
-
@patch('os.path.exists')
|
|
506
|
-
def test_get_wsl2_render_devices_amd_via_lspci(self, mock_exists, mock_listdir,
|
|
507
|
-
mock_rocm, mock_lspci):
|
|
508
|
-
"""Test WSL2 render device detection with AMD GPU detected via lspci."""
|
|
509
|
-
mock_exists.return_value = True
|
|
510
|
-
mock_listdir.return_value = ['renderD128']
|
|
511
|
-
mock_lspci.return_value = 'AMD'
|
|
512
|
-
mock_rocm.return_value = False
|
|
513
|
-
|
|
514
|
-
devices = _get_wsl2_render_devices()
|
|
515
|
-
|
|
516
|
-
assert len(devices) == 1
|
|
517
|
-
assert devices[0][0] == 'wsl2-renderD128'
|
|
518
|
-
assert devices[0][1] == '/dev/dri/renderD128'
|
|
519
|
-
assert devices[0][2] == 'amd'
|
|
520
|
-
|
|
521
|
-
@patch('os.path.exists')
|
|
522
|
-
def test_get_wsl2_render_devices_no_dri(self, mock_exists):
|
|
523
|
-
"""Test WSL2 render device detection when /dev/dri doesn't exist."""
|
|
524
|
-
mock_exists.return_value = False
|
|
525
|
-
|
|
526
|
-
devices = _get_wsl2_render_devices()
|
|
527
|
-
|
|
528
|
-
assert devices == []
|
|
529
|
-
|
|
530
|
-
@patch('os.listdir')
|
|
531
|
-
@patch('os.path.exists')
|
|
532
|
-
def test_get_wsl2_render_devices_no_render_devices(self, mock_exists, mock_listdir):
|
|
533
|
-
"""Test WSL2 render device detection when no render devices exist."""
|
|
534
|
-
mock_exists.return_value = True
|
|
535
|
-
mock_listdir.return_value = ['card0', 'card1']
|
|
536
|
-
|
|
537
|
-
devices = _get_wsl2_render_devices()
|
|
538
|
-
|
|
539
|
-
assert devices == []
|
|
540
|
-
|
|
541
|
-
@patch('plex_generate_previews.gpu_detection._get_wsl2_render_devices')
|
|
542
|
-
@patch('plex_generate_previews.gpu_detection._test_acceleration_method')
|
|
543
|
-
@patch('plex_generate_previews.gpu_detection._get_gpu_devices')
|
|
544
|
-
@patch('plex_generate_previews.gpu_detection._is_wsl2')
|
|
545
|
-
@patch('plex_generate_previews.gpu_detection.get_gpu_name')
|
|
546
|
-
def test_detect_all_gpus_wsl2_amd_fallback(self, mock_name, mock_wsl2,
|
|
547
|
-
mock_devices, mock_test, mock_wsl2_devices):
|
|
548
|
-
"""Test full GPU detection in WSL2 with AMD GPU using fallback detection."""
|
|
549
|
-
# Simulate WSL2 environment with no /sys/class/drm enumeration
|
|
550
|
-
mock_wsl2.return_value = True
|
|
551
|
-
mock_devices.return_value = [] # No devices from standard enumeration
|
|
552
|
-
mock_wsl2_devices.return_value = [('wsl2-renderD128', '/dev/dri/renderD128', 'amdgpu')]
|
|
553
|
-
mock_test.return_value = True
|
|
554
|
-
mock_name.return_value = 'AMD Radeon RX 7900 XT'
|
|
555
|
-
# Force Linux path so fallback WSL2 detection is exercised
|
|
556
|
-
with patch('plex_generate_previews.gpu_detection.platform.system', return_value='Linux'):
|
|
557
|
-
gpus = detect_all_gpus()
|
|
558
|
-
|
|
559
|
-
# Should detect AMD GPU via WSL2 fallback
|
|
560
|
-
amd_gpus = [g for g in gpus if g[0] == 'AMD']
|
|
561
|
-
assert len(amd_gpus) > 0
|
|
562
|
-
assert 'RX 7900 XT' in amd_gpus[0][2]['name']
|
|
563
|
-
assert amd_gpus[0][2]['acceleration'] == 'VAAPI'
|
|
564
|
-
assert amd_gpus[0][1] == '/dev/dri/renderD128'
|
|
565
|
-
|
|
566
|
-
|
|
567
457
|
class TestFFmpegVersion:
|
|
568
458
|
"""Test FFmpeg version detection."""
|
|
569
459
|
|
|
@@ -811,7 +701,7 @@ class TestAccelerationMethodTesting:
|
|
|
811
701
|
|
|
812
702
|
mock_test.return_value = False
|
|
813
703
|
|
|
814
|
-
result = _test_acceleration_method('nvidia', 'CUDA', None
|
|
704
|
+
result = _test_acceleration_method('nvidia', 'CUDA', None)
|
|
815
705
|
assert result is False
|
|
816
706
|
|
|
817
707
|
@patch('plex_generate_previews.gpu_detection._test_hwaccel_functionality')
|
|
@@ -821,7 +711,7 @@ class TestAccelerationMethodTesting:
|
|
|
821
711
|
|
|
822
712
|
mock_test.return_value = False
|
|
823
713
|
|
|
824
|
-
result = _test_acceleration_method('amd', 'VAAPI', '/dev/dri/renderD128'
|
|
714
|
+
result = _test_acceleration_method('amd', 'VAAPI', '/dev/dri/renderD128')
|
|
825
715
|
assert result is False
|
|
826
716
|
|
|
827
717
|
|
|
@@ -854,7 +744,7 @@ class TestDetectAllGPUsEdgeCases:
|
|
|
854
744
|
mock_is_macos.return_value = False
|
|
855
745
|
mock_devices.return_value = [('card0', '/dev/dri/renderD128', 'nvidia')]
|
|
856
746
|
|
|
857
|
-
def test_side_effect(vendor, accel, device
|
|
747
|
+
def test_side_effect(vendor, accel, device):
|
|
858
748
|
if accel == 'CUDA':
|
|
859
749
|
return True
|
|
860
750
|
elif accel == 'NVENC':
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/.github/workflows/test.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/fixtures/reference.bif
RENAMED
|
File without changes
|
{plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/fixtures/sample.jpg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_config.py
RENAMED
|
File without changes
|
{plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_gpu_ci.py
RENAMED
|
File without changes
|
{plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_headers.py
RENAMED
|
File without changes
|
{plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_integration.py
RENAMED
|
File without changes
|
{plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_logging_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_plex_client.py
RENAMED
|
File without changes
|
|
File without changes
|
{plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_version_check.py
RENAMED
|
File without changes
|
|
File without changes
|
{plex_generate_previews-2.4.1.dev0 → plex_generate_previews-2.5.1.dev0}/tests/test_worker.py
RENAMED
|
File without changes
|
|
File without changes
|