mirror of
https://github.com/bybrooklyn/alchemist.git
synced 2026-04-18 01:43:34 -04:00
Remove ReDoc docs and tighten scan analysis handling
This commit is contained in:
63
GEMINI.md
Normal file
63
GEMINI.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Alchemist Context
|
||||
|
||||
Alchemist is a media transcoding tool designed for simplicity and space-saving. It provides a web-based dashboard to manage media libraries, monitor transcoding progress, and configure encoding profiles with automatic hardware acceleration support.
|
||||
|
||||
## Project Overview
|
||||
|
||||
- **Purpose:** Automated media transcoding and library management to save storage space.
|
||||
- **Backend:** Rust 2024 (Tokio, Axum 0.7, SQLx 0.8 with SQLite).
|
||||
- **Frontend:** Astro 5, React 18, Tailwind CSS (embedded in the Rust binary via `rust-embed`).
|
||||
- **Documentation:** Docusaurus 3.9 (located in the root `package.json`).
|
||||
- **Core Technologies:** FFmpeg (analyzer and executor), SQLite (state management), Argon2 (security).
|
||||
|
||||
## Architecture & Pipeline
|
||||
|
||||
The core logic is managed by an `Agent` in `src/media/processor.rs` that orchestrates the following pipeline:
|
||||
1. **Scanner:** Finds files in watch folders and enqueues jobs.
|
||||
2. **Analyzer:** Runs `ffprobe` to build normalized media metadata.
|
||||
3. **Planner:** Decides whether to skip, remux, or transcode based on quality profiles.
|
||||
4. **Executor:** Runs `ffmpeg` with selected encoders (NVIDIA, Intel, AMD, Apple, or CPU fallback).
|
||||
5. **Post-Encode:** Quality checks (optional VMAF), file promotion, and database updates.
|
||||
|
||||
### Engine States & Modes
|
||||
- **States:** `Running`, `Paused`, `Draining`, `SchedulerPaused`.
|
||||
- **Modes:** `Background` (1 job), `Balanced` (capped concurrency), `Throughput` (uncapped concurrency).
|
||||
|
||||
## Building and Running
|
||||
|
||||
The project uses `just` as the primary task runner.
|
||||
|
||||
- **Development:**
|
||||
- `just dev`: Builds frontend assets and starts the backend server.
|
||||
- `just web`: Starts the frontend development server (Astro) independently.
|
||||
- `just run`: Starts the backend only (requires `web/dist` to exist).
|
||||
- **Build:**
|
||||
- `just build`: Performs a full production build (Frontend then Rust).
|
||||
- `just docker-build`: Builds the local Docker image.
|
||||
- **Verification:**
|
||||
- `just check`: Runs all checks (Rust fmt, clippy, check; Frontend typecheck, build).
|
||||
- `just check-rust`: Rust-only verification.
|
||||
- **Testing:**
|
||||
- `just test`: Runs all Rust tests.
|
||||
- `just test-e2e`: Runs Playwright reliability tests in `web-e2e/`.
|
||||
|
||||
## Development Conventions
|
||||
|
||||
- **MSRV:** Rust 1.85 (Rust 2024 edition).
|
||||
- **Task Management:** Always check the `justfile` for established workflows before adding new scripts.
|
||||
- **Configuration:** Respects `ALCHEMIST_CONFIG_PATH` and `ALCHEMIST_DB_PATH`. Hot-reloading is supported for the configuration file.
|
||||
- **Database:** Uses SQLx migrations located in `migrations/`. Use `just db-reset` to wipe the local database for testing.
|
||||
- **Code Style:** Standard Rust formatting (`cargo fmt`) and clippy (`cargo clippy`) are enforced in CI.
|
||||
- **Documentation:** Maintain documentation in `docs/` (Markdown) and the Docusaurus site.
|
||||
|
||||
## Key Directories
|
||||
|
||||
- `src/`: Backend source code.
|
||||
- `server/`: Axum API routes and handlers.
|
||||
- `media/`: Transcoding pipeline, planners, and processors.
|
||||
- `db/`: SQLx database access layer.
|
||||
- `web/`: Frontend source code (Astro + React).
|
||||
- `docs/`: Comprehensive technical documentation.
|
||||
- `migrations/`: SQLite database migrations.
|
||||
- `tests/`: Integration and unit tests for the backend.
|
||||
- `web-e2e/`: Playwright end-to-end tests for the web interface.
|
||||
@@ -1,13 +0,0 @@
|
||||
# Alchemist Documentation
|
||||
|
||||
This directory contains the plain Markdown documentation for Alchemist.
|
||||
|
||||
## Structure
|
||||
|
||||
- `index.md`: landing page content
|
||||
- `getting-started/`: installation and onboarding guides
|
||||
- `guides/`: task-focused operational guides
|
||||
- `hardware/`: vendor-specific hardware notes
|
||||
- `reference/`: technical reference material
|
||||
- `reference/openapi.md`: raw OpenAPI specification wrapped in Markdown
|
||||
- `contributing/`: contributor documentation
|
||||
@@ -1,284 +0,0 @@
|
||||
# Configuration Reference
|
||||
|
||||
Complete reference for all Alchemist configuration options with examples.
|
||||
|
||||
# Configuration Reference
|
||||
|
||||
This page provides a comprehensive reference for all Alchemist configuration options. The configuration file is written in TOML format and contains settings that control every aspect of how Alchemist processes your media.
|
||||
|
||||
## Configuration File Location
|
||||
|
||||
The configuration file is automatically created during the setup wizard. Default locations:
|
||||
|
||||
- **Linux/macOS**: `~/.config/alchemist/config.toml`
|
||||
- **Windows**: `%APPDATA%\alchemist\config.toml`
|
||||
- **Docker**: Bind mount to `/app/config/config.toml`
|
||||
|
||||
You can override the location with the `ALCHEMIST_CONFIG_PATH` environment variable.
|
||||
|
||||
## Sample Configuration
|
||||
|
||||
Here's a complete example configuration file:
|
||||
|
||||
```toml
|
||||
[appearance]
|
||||
active_theme_id = "dark"
|
||||
|
||||
[transcode]
|
||||
size_reduction_threshold = 0.3
|
||||
min_bpp_threshold = 0.1
|
||||
min_file_size_mb = 100
|
||||
concurrent_jobs = 2
|
||||
threads = 0
|
||||
quality_profile = "balanced"
|
||||
output_codec = "av1"
|
||||
allow_fallback = true
|
||||
hdr_mode = "preserve"
|
||||
tonemap_algorithm = "hable"
|
||||
tonemap_peak = 100.0
|
||||
tonemap_desat = 0.2
|
||||
subtitle_mode = "copy"
|
||||
vmaf_min_score = 93.0
|
||||
|
||||
[transcode.stream_rules]
|
||||
strip_audio_by_title = ["commentary", "director"]
|
||||
keep_audio_languages = ["eng"]
|
||||
keep_only_default_audio = false
|
||||
|
||||
[hardware]
|
||||
preferred_vendor = "nvidia"
|
||||
device_path = "/dev/dri/renderD128"
|
||||
allow_cpu_fallback = true
|
||||
cpu_preset = "medium"
|
||||
allow_cpu_encoding = true
|
||||
|
||||
[scanner]
|
||||
directories = ["/media/movies", "/media/tv"]
|
||||
watch_enabled = true
|
||||
|
||||
[[scanner.extra_watch_dirs]]
|
||||
path = "/media/incoming"
|
||||
is_recursive = true
|
||||
|
||||
[notifications]
|
||||
enabled = true
|
||||
notify_on_complete = true
|
||||
notify_on_failure = true
|
||||
|
||||
[[notifications.targets]]
|
||||
name = "discord"
|
||||
target_type = "discord"
|
||||
endpoint_url = "https://discord.com/api/webhooks/..."
|
||||
enabled = true
|
||||
events = ["job_complete", "job_failed"]
|
||||
|
||||
[files]
|
||||
delete_source = false
|
||||
output_extension = "mkv"
|
||||
output_suffix = "-alchemist"
|
||||
replace_strategy = "keep"
|
||||
output_root = "/media/transcoded"
|
||||
|
||||
[schedule]
|
||||
[[schedule.windows]]
|
||||
start_time = "22:00"
|
||||
end_time = "06:00"
|
||||
days_of_week = [1, 2, 3, 4, 5]
|
||||
enabled = true
|
||||
|
||||
[quality]
|
||||
enable_vmaf = true
|
||||
min_vmaf_score = 90.0
|
||||
revert_on_low_quality = true
|
||||
|
||||
[system]
|
||||
monitoring_poll_interval = 2.0
|
||||
enable_telemetry = false
|
||||
log_retention_days = 30
|
||||
engine_mode = "balanced"
|
||||
https_only = false
|
||||
```
|
||||
|
||||
## Section Reference
|
||||
|
||||
### Appearance (`appearance`)
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `active_theme_id` | string | `null` | Theme ID for the web interface ("light", "dark", or custom) |
|
||||
|
||||
### Transcoding (`transcode`)
|
||||
|
||||
Core settings that control the video encoding process.
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `size_reduction_threshold` | float | `0.3` | Minimum expected size reduction (0.3 = 30%) to proceed with transcoding |
|
||||
| `min_bpp_threshold` | float | `0.1` | Minimum bits-per-pixel to consider a file worth transcoding |
|
||||
| `min_file_size_mb` | integer | `50` | Skip files smaller than this (in MB) |
|
||||
| `concurrent_jobs` | integer | `1` | Number of simultaneous transcoding jobs |
|
||||
| `threads` | integer | `0` | CPU threads per job (0 = automatic) |
|
||||
| `quality_profile` | string | `"balanced"` | Speed vs quality tradeoff: `"quality"`, `"balanced"`, `"speed"` |
|
||||
| `output_codec` | string | `"av1"` | Target codec: `"av1"`, `"hevc"`, `"h264"` |
|
||||
| `allow_fallback` | boolean | `true` | Fall back to CPU if hardware encoding fails |
|
||||
| `hdr_mode` | string | `"preserve"` | HDR handling: `"preserve"` or `"tonemap"` |
|
||||
| `tonemap_algorithm` | string | `"hable"` | Tonemap method: `"hable"`, `"mobius"`, `"reinhard"`, `"clip"` |
|
||||
| `tonemap_peak` | float | `100.0` | Target peak luminance for tonemapping (nits) |
|
||||
| `tonemap_desat` | float | `0.2` | Desaturation factor during tonemapping |
|
||||
| `subtitle_mode` | string | `"copy"` | Subtitle handling: `"copy"`, `"burn"`, `"extract"`, `"none"` |
|
||||
| `vmaf_min_score` | float | `null` | Minimum VMAF score to accept transcode (optional) |
|
||||
|
||||
#### Quality Profiles
|
||||
|
||||
Each profile adjusts encoding parameters for different priorities:
|
||||
|
||||
- **Quality**: Slower encoding, best compression (CRF 24, preset slow)
|
||||
- **Balanced**: Good compromise (CRF 28, preset medium)
|
||||
- **Speed**: Faster encoding, larger files (CRF 32, preset fast)
|
||||
|
||||
#### Stream Rules (`transcode.stream_rules`)
|
||||
|
||||
Audio track filtering rules applied before transcoding:
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `strip_audio_by_title` | array | `[]` | Remove tracks containing these strings (case-insensitive) |
|
||||
| `keep_audio_languages` | array | `[]` | Keep only tracks with these ISO 639-2 language codes |
|
||||
| `keep_only_default_audio` | boolean | `false` | Keep only the default audio track |
|
||||
|
||||
### Hardware (`hardware`)
|
||||
|
||||
Graphics card and CPU encoding settings.
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `preferred_vendor` | string | `null` | Preferred encoder: `"nvidia"`, `"intel"`, `"amd"`, `"apple"`, `"cpu"` |
|
||||
| `device_path` | string | `null` | Specific GPU device path (e.g., `/dev/dri/renderD128`) |
|
||||
| `allow_cpu_fallback` | boolean | `true` | Use CPU encoding if GPU unavailable |
|
||||
| `cpu_preset` | string | `"medium"` | CPU preset: `"slow"`, `"medium"`, `"fast"`, `"faster"` |
|
||||
| `allow_cpu_encoding` | boolean | `true` | Enable CPU encoding entirely |
|
||||
|
||||
### Scanner (`scanner`)
|
||||
|
||||
File discovery and monitoring settings.
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `directories` | array | `[]` | Base directories to scan for media files |
|
||||
| `watch_enabled` | boolean | `false` | Enable real-time file monitoring |
|
||||
| `extra_watch_dirs` | array | `[]` | Additional directories with custom settings |
|
||||
|
||||
#### Extra Watch Directories
|
||||
|
||||
Each entry in `extra_watch_dirs` supports:
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `path` | string | Required | Directory path to monitor |
|
||||
| `is_recursive` | boolean | `true` | Include subdirectories |
|
||||
|
||||
### Notifications (`notifications`)
|
||||
|
||||
Alert settings for job completion and failures.
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `enabled` | boolean | `false` | Enable notification system |
|
||||
| `notify_on_complete` | boolean | `false` | Send alerts when jobs complete successfully |
|
||||
| `notify_on_failure` | boolean | `false` | Send alerts when jobs fail |
|
||||
| `targets` | array | `[]` | Notification endpoints (see below) |
|
||||
|
||||
#### Notification Targets
|
||||
|
||||
Each target in the `targets` array supports:
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `name` | string | Required | Friendly name for this target |
|
||||
| `target_type` | string | Required | Type: `"discord"`, `"gotify"`, `"webhook"` |
|
||||
| `endpoint_url` | string | Required | Full URL for the notification service |
|
||||
| `auth_token` | string | `null` | Authentication token if required |
|
||||
| `events` | array | `[]` | Events to send: `"job_complete"`, `"job_failed"` |
|
||||
| `enabled` | boolean | `true` | Whether this target is active |
|
||||
|
||||
### Files (`files`)
|
||||
|
||||
Output file naming and handling preferences.
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `delete_source` | boolean | `false` | Delete original files after successful transcode |
|
||||
| `output_extension` | string | `"mkv"` | Container format for output files |
|
||||
| `output_suffix` | string | `"-alchemist"` | Suffix added to transcoded filenames |
|
||||
| `replace_strategy` | string | `"keep"` | How to handle existing output files: `"keep"`, `"overwrite"` |
|
||||
| `output_root` | string | `null` | Alternative output directory (preserves folder structure) |
|
||||
|
||||
### Schedule (`schedule`)
|
||||
|
||||
Time-based restrictions for when transcoding can occur.
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `windows` | array | `[]` | Time windows when transcoding is allowed |
|
||||
|
||||
#### Schedule Windows
|
||||
|
||||
Each window supports:
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `start_time` | string | Required | Start time in 24-hour format (HH:MM) |
|
||||
| `end_time` | string | Required | End time in 24-hour format (HH:MM) |
|
||||
| `days_of_week` | array | `[]` | Days 0-6 (Sunday=0) when this window applies |
|
||||
| `enabled` | boolean | `true` | Whether this window is active |
|
||||
|
||||
### Quality (`quality`)
|
||||
|
||||
Advanced quality verification settings.
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `enable_vmaf` | boolean | `false` | Enable VMAF quality scoring (slow) |
|
||||
| `min_vmaf_score` | float | `90.0` | Minimum VMAF score to accept transcode |
|
||||
| `revert_on_low_quality` | boolean | `true` | Delete output and keep original if VMAF score too low |
|
||||
|
||||
### System (`system`)
|
||||
|
||||
Application-level settings and monitoring.
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
|---------|------|---------|-------------|
|
||||
| `monitoring_poll_interval` | float | `2.0` | Seconds between system status updates |
|
||||
| `enable_telemetry` | boolean | `false` | Send anonymous usage statistics |
|
||||
| `log_retention_days` | integer | `30` | Days to keep log files (null = forever) |
|
||||
| `engine_mode` | string | `"balanced"` | Processing mode: `"background"`, `"balanced"`, `"throughput"` |
|
||||
| `https_only` | boolean | `false` | Enforce HTTPS (only enable behind reverse proxy) |
|
||||
|
||||
#### Engine Modes
|
||||
|
||||
- **Background**: Minimal resource usage (1 job max)
|
||||
- **Balanced**: Reasonable performance (½ CPU cores, max 4 jobs)
|
||||
- **Throughput**: Maximum performance (½ CPU cores, no job limit)
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Alchemist respects these environment variables:
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `ALCHEMIST_CONFIG_PATH` | Path to config file | `~/.config/alchemist/config.toml` |
|
||||
| `ALCHEMIST_DB_PATH` | Path to database file | `~/.config/alchemist/alchemist.db` |
|
||||
| `ALCHEMIST_CONFIG_MUTABLE` | Allow runtime config changes | `true` |
|
||||
| `RUST_LOG` | Logging level | `info` |
|
||||
| `PORT` | Web server port | `3000` |
|
||||
| `HOST` | Web server bind address | `0.0.0.0` |
|
||||
|
||||
## Configuration Validation
|
||||
|
||||
Alchemist validates your configuration on startup and will show specific error messages for:
|
||||
- Invalid values or types
|
||||
- Missing required fields
|
||||
- Conflicting settings
|
||||
- Unreachable file paths
|
||||
|
||||
Check the logs if Alchemist fails to start after configuration changes.
|
||||
@@ -1,109 +0,0 @@
|
||||
# Development Setup
|
||||
|
||||
Guide for setting up a local development environment for Alchemist.
|
||||
|
||||
This guide is for developers who want to modify Alchemist's code. We explain how to set up your computer to run the back-end (Rust) and the front-end (React) separately for faster development.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
Alchemist is built using:
|
||||
- **Back-end**: [Rust](https://www.rust-lang.org/) with [Axum](https://github.com/tokio-rs/axum).
|
||||
- **Front-end**: [React](https://react.dev/) with [Astro](https://astro.build/) (located in the `web/` folder).
|
||||
- **Database**: [SQLite](https://www.sqlite.org/index.html).
|
||||
- **Transcoding**: [FFmpeg](https://ffmpeg.org/).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To work on Alchemist, you'll need:
|
||||
1. **Rust**: Install via [rustup](https://rustup.rs/).
|
||||
2. **Bun**: Used for front-end package management (install via the official Bun installer).
|
||||
3. **FFmpeg**: Installed on your system (for local testing).
|
||||
|
||||
## Local Development
|
||||
|
||||
### 1. Full stack with `just`
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/bybrooklyn/alchemist.git
|
||||
cd alchemist
|
||||
|
||||
# Build the frontend and start the backend
|
||||
just dev
|
||||
```
|
||||
|
||||
`just dev` builds the Astro site into `web/dist` and then starts the Rust server.
|
||||
|
||||
### 2. Back-end (Rust)
|
||||
The back-end handles the database, scanning files, and running FFmpeg.
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/bybrooklyn/alchemist.git
|
||||
cd alchemist
|
||||
|
||||
# Build the back-end
|
||||
cargo build
|
||||
|
||||
# Run the back-end (starts the API on port 3000)
|
||||
cargo run
|
||||
```
|
||||
|
||||
### 3. Front-end (Web UI)
|
||||
The web interface is located in the `web/` directory.
|
||||
|
||||
```bash
|
||||
cd web
|
||||
|
||||
# Install dependencies
|
||||
bun install
|
||||
|
||||
# Start the development server (runs on port 4321)
|
||||
bun run dev
|
||||
```
|
||||
|
||||
The front-end will automatically "talk" to the back-end running on port 3000.
|
||||
|
||||
## Running Tests
|
||||
|
||||
We value high-quality, tested code. Please ensure your changes don't break existing functionality.
|
||||
|
||||
```bash
|
||||
# Run the main repo validation gate
|
||||
just check
|
||||
|
||||
# Run the Rust test suite
|
||||
just test
|
||||
|
||||
# Run the frontend verification gate
|
||||
cd web
|
||||
bun run typecheck && bun run build
|
||||
|
||||
# Build the docs site
|
||||
cd ../docs
|
||||
bun install --frozen-lockfile
|
||||
bun run build
|
||||
|
||||
# Run the reliability Playwright suite on an isolated test port
|
||||
cd ../web-e2e
|
||||
ALCHEMIST_E2E_PORT=4173 bun install --frozen-lockfile
|
||||
ALCHEMIST_E2E_PORT=4173 bun run test:reliability
|
||||
```
|
||||
|
||||
## Release Workflow
|
||||
|
||||
The repo ships a `justfile` for release preparation:
|
||||
|
||||
```bash
|
||||
# Rewrite version files only
|
||||
just bump 0.2.10-rc.5
|
||||
|
||||
# Full guarded release flow
|
||||
just update v0.2.10-rc.5
|
||||
```
|
||||
|
||||
`just update` can checkpoint dirty local work, validates the repo before release, blocks behind/diverged remote state, and only creates the release commit/tag/push after the full validation gate passes.
|
||||
|
||||
## UI Development
|
||||
|
||||
The `web/` folder uses **Tailwind CSS** for styling and **Lucide React** for icons. If you add new components, please follow the existing patterns in `web/src/components/ui/`.
|
||||
@@ -1,26 +0,0 @@
|
||||
# Contributing Overview
|
||||
|
||||
How to report bugs, suggest features, and contribute to Alchemist.
|
||||
|
||||
This page explains how you can help make Alchemist even better. You don't need to be a programmer to contribute; reporting bugs and suggesting new ideas is just as important.
|
||||
|
||||
Alchemist is an open-source project released under the **GPLv3 License**. This means the code is free to use, modify, and share, as long as it stays open for everyone.
|
||||
|
||||
## Reporting Bugs
|
||||
|
||||
If you find something that isn't working right, please let us know!
|
||||
1. Go to our [GitHub Issues](https://github.com/bybrooklyn/alchemist/issues).
|
||||
2. Search to see if someone else has already reported the same problem.
|
||||
3. If not, click **New Issue** and use the "Bug Report" template.
|
||||
4. Include as much detail as possible, especially your logs and what kind of computer/graphics card you are using.
|
||||
|
||||
## Suggesting Features
|
||||
|
||||
Have a great idea for Alchemist? We'd love to hear it!
|
||||
1. Go to our [GitHub Issues](https://github.com/bybrooklyn/alchemist/issues).
|
||||
2. Use the "Feature Request" template.
|
||||
3. Explain **why** this feature would be useful and how you imagine it working.
|
||||
|
||||
## Licensing
|
||||
|
||||
By contributing to Alchemist, you agree that your contributions will be licensed under the **GPLv3 License**. This ensures that Alchemist remains free and open-source forever.
|
||||
499
redoc/faq.md
499
redoc/faq.md
@@ -1,499 +0,0 @@
|
||||
# Frequently Asked Questions
|
||||
|
||||
Comprehensive FAQ covering everything you need to know about Alchemist.
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
This comprehensive FAQ answers the most common questions about Alchemist. Questions are organized by topic for easy navigation.
|
||||
|
||||
## General Questions
|
||||
|
||||
### What exactly does Alchemist do?
|
||||
|
||||
Alchemist is a **smart video transcoding pipeline** that automatically converts your media library to more efficient formats. Think of it as a "garbage compactor" for video files that:
|
||||
|
||||
- Scans your media collection automatically
|
||||
- Analyzes each file to determine if transcoding would help
|
||||
- Uses hardware acceleration (GPU) when available
|
||||
- Only transcodes files that will actually benefit
|
||||
- Preserves your originals until you're satisfied with results
|
||||
- Provides a web dashboard to monitor everything
|
||||
|
||||
### Is Alchemist free?
|
||||
|
||||
**Yes, completely free!** Alchemist is open-source software released under the GPLv3 license. This means:
|
||||
|
||||
- No cost to download, install, or use
|
||||
- Source code is publicly available
|
||||
- No premium features or subscriptions
|
||||
- No telemetry or tracking (unless you explicitly enable it)
|
||||
- Community-driven development
|
||||
|
||||
### How much storage will I save?
|
||||
|
||||
Typical savings depend on your source content:
|
||||
|
||||
| Content Type | Typical Savings | Example |
|
||||
|-------------|----------------|---------|
|
||||
| **Old TV shows** (DVD/early digital) | 50-80% | 2GB → 600MB |
|
||||
| **Blu-ray rips** (H.264) | 30-60% | 25GB → 12GB |
|
||||
| **Modern streaming** (already efficient) | 0-20% | Often skipped |
|
||||
| **4K content** | 40-70% | 60GB → 25GB |
|
||||
|
||||
**Average across mixed libraries: 40-60% space savings**
|
||||
|
||||
### Will Alchemist ruin my video quality?
|
||||
|
||||
**No.** Alchemist is designed with quality protection:
|
||||
|
||||
- **Intelligent analysis** checks if transcoding will help before starting
|
||||
- **Quality thresholds** prevent processing files that are already efficient
|
||||
- **VMAF scoring** (optional) verifies output quality mathematically
|
||||
- **Conservative defaults** prioritize quality over maximum compression
|
||||
- **Originals preserved** until you manually approve deletion
|
||||
|
||||
If Alchemist thinks a transcode would hurt quality, it skips the file and tells you why.
|
||||
|
||||
### Does it work on Windows, Mac, and Linux?
|
||||
|
||||
**Yes, all three.** Alchemist works on:
|
||||
|
||||
| Platform | Status | Notes |
|
||||
|----------|--------|-------|
|
||||
| **Linux x86_64/ARM64** | ✅ Fully supported | Best performance |
|
||||
| **Windows x86_64** | ✅ Fully supported | Good GPU support |
|
||||
| **macOS Intel/Apple Silicon** | ✅ Fully supported | VideoToolbox acceleration |
|
||||
| **Docker** | ✅ Recommended | Works anywhere Docker runs |
|
||||
|
||||
## Hardware & Performance
|
||||
|
||||
### Do I need a powerful graphics card?
|
||||
|
||||
**No, but it helps a lot.** Alchemist works in any configuration:
|
||||
|
||||
- **With GPU**: 20-60 minutes per movie, low power usage
|
||||
- **CPU only**: 2-8 hours per movie, higher power usage
|
||||
- **Automatic fallback**: Uses GPU when available, CPU when not
|
||||
|
||||
**Supported GPUs:**
|
||||
- NVIDIA (GTX 10-series and newer)
|
||||
- Intel integrated graphics (6th gen and newer)
|
||||
- AMD Radeon (RX 400-series and newer)
|
||||
- Apple Silicon (M1/M2/M3)
|
||||
|
||||
### What's the difference between GPU and CPU encoding?
|
||||
|
||||
| Aspect | GPU Encoding | CPU Encoding |
|
||||
|--------|--------------|--------------|
|
||||
| **Speed** | 5-20x faster | Baseline |
|
||||
| **Quality** | Very good | Excellent |
|
||||
| **Power usage** | Lower | Higher |
|
||||
| **Compatibility** | Requires supported GPU | Works everywhere |
|
||||
| **Cost** | GPU hardware needed | Uses existing CPU |
|
||||
|
||||
**Bottom line**: GPU encoding is much faster and more efficient, but CPU encoding produces slightly better quality.
|
||||
|
||||
### Can I limit when Alchemist runs?
|
||||
|
||||
**Yes!** Multiple ways to control when processing happens:
|
||||
|
||||
1. **Engine modes**:
|
||||
- **Background**: Minimal resource usage
|
||||
- **Balanced**: Moderate performance (default)
|
||||
- **Throughput**: Maximum performance
|
||||
|
||||
2. **Scheduling**:
|
||||
```toml
|
||||
[schedule]
|
||||
[[schedule.windows]]
|
||||
start_time = "22:00" # 10 PM
|
||||
end_time = "06:00" # 6 AM
|
||||
days_of_week = [1, 2, 3, 4, 5] # Weekdays only
|
||||
```
|
||||
|
||||
3. **Manual control**: Pause/resume anytime from the dashboard
|
||||
|
||||
### How many files can it process simultaneously?
|
||||
|
||||
Depends on your hardware:
|
||||
|
||||
| System Type | Recommended Concurrent Jobs |
|
||||
|-------------|----------------------------|
|
||||
| **Basic CPU** (4 cores) | 1 |
|
||||
| **Good CPU** (8+ cores) | 2 |
|
||||
| **GPU + good CPU** | 2-3 |
|
||||
| **High-end workstation** | 4+ |
|
||||
|
||||
The system auto-adjusts based on available resources, but you can override:
|
||||
|
||||
```toml
|
||||
[transcode]
|
||||
concurrent_jobs = 2 # Manual override
|
||||
```
|
||||
|
||||
## Quality & Codecs
|
||||
|
||||
### What's the difference between AV1, HEVC, and H.264?
|
||||
|
||||
| Codec | Compression | Compatibility | Encoding Speed | Best For |
|
||||
|-------|-------------|---------------|----------------|----------|
|
||||
| **AV1** | Excellent (30% better than HEVC) | Newer devices | Slower | Future-proofing, archival |
|
||||
| **HEVC/H.265** | Very good (50% better than H.264) | Most modern devices | Medium | General use, good balance |
|
||||
| **H.264** | Good (baseline) | Universal | Fastest | Compatibility, quick results |
|
||||
|
||||
**Recommendation**: Start with HEVC for best balance of quality, compatibility, and encoding speed.
|
||||
|
||||
### Should I enable VMAF quality checking?
|
||||
|
||||
**VMAF** is Netflix's quality measurement tool. Enable if:
|
||||
|
||||
✅ **Yes, if you:**
|
||||
- Have critical content you can't re-encode
|
||||
- Want mathematical quality verification
|
||||
- Don't mind 2-3x slower encoding
|
||||
- Are a quality enthusiast
|
||||
|
||||
❌ **No, if you:**
|
||||
- Want fast processing
|
||||
- Trust Alchemist's quality settings
|
||||
- Have large libraries to process
|
||||
- Use reasonable quality settings already
|
||||
|
||||
### What happens to HDR content?
|
||||
|
||||
Alchemist can handle HDR content two ways:
|
||||
|
||||
1. **Preserve HDR** (default):
|
||||
```toml
|
||||
[transcode]
|
||||
hdr_mode = "preserve"
|
||||
```
|
||||
- Keeps HDR metadata intact
|
||||
- Requires HDR-capable display for viewing
|
||||
- Smaller file size impact
|
||||
|
||||
2. **Tonemap to SDR**:
|
||||
```toml
|
||||
[transcode]
|
||||
hdr_mode = "tonemap"
|
||||
tonemap_algorithm = "hable" # Recommended
|
||||
```
|
||||
- Converts to standard dynamic range
|
||||
- Works on any display
|
||||
- Slight quality loss in bright scenes
|
||||
|
||||
### Can I customize quality settings per library?
|
||||
|
||||
**Yes!** Use different profiles for different content:
|
||||
|
||||
```toml
|
||||
# Movies: Maximum quality
|
||||
[profiles.movies]
|
||||
quality_profile = "quality"
|
||||
output_codec = "av1"
|
||||
min_file_size_mb = 500 # Only large files
|
||||
|
||||
# TV Shows: Faster processing
|
||||
[profiles.tv_shows]
|
||||
quality_profile = "speed"
|
||||
output_codec = "hevc"
|
||||
min_file_size_mb = 100
|
||||
|
||||
# Home videos: Preserve originals
|
||||
[profiles.home_videos]
|
||||
delete_source = false
|
||||
output_codec = "h264"
|
||||
```
|
||||
|
||||
## File Management
|
||||
|
||||
### What happens to my original files?
|
||||
|
||||
**By default, originals are kept safe.** Alchemist:
|
||||
|
||||
1. Creates new file with `-alchemist` suffix
|
||||
2. Verifies the new file works correctly
|
||||
3. Keeps both files until you decide
|
||||
|
||||
**Options for originals:**
|
||||
- **Keep both** (default, safest)
|
||||
- **Manual review** then delete originals
|
||||
- **Auto-delete** after successful transcode (risky)
|
||||
|
||||
```toml
|
||||
[files]
|
||||
delete_source = false # Keep originals (recommended)
|
||||
output_suffix = "-alchemist"
|
||||
replace_strategy = "keep" # Don't overwrite existing files
|
||||
```
|
||||
|
||||
### Can I organize output files differently?
|
||||
|
||||
**Yes!** Several organization options:
|
||||
|
||||
1. **Same location with suffix** (default):
|
||||
```
|
||||
/media/Movie.mkv
|
||||
/media/Movie-alchemist.mkv
|
||||
```
|
||||
|
||||
2. **Separate output directory**:
|
||||
```toml
|
||||
[files]
|
||||
output_root = "/media/transcoded"
|
||||
```
|
||||
Result:
|
||||
```
|
||||
/media/movies/Movie.mkv (original)
|
||||
/media/transcoded/movies/Movie.mkv (transcoded)
|
||||
```
|
||||
|
||||
3. **Custom file extensions**:
|
||||
```toml
|
||||
[files]
|
||||
output_extension = "mp4" # Change container format
|
||||
```
|
||||
|
||||
### How do I handle different languages and audio tracks?
|
||||
|
||||
**Stream rules** let you customize audio handling:
|
||||
|
||||
```toml
|
||||
[transcode.stream_rules]
|
||||
# Remove commentary tracks
|
||||
strip_audio_by_title = ["commentary", "director", "behind"]
|
||||
|
||||
# Keep only English and Japanese audio
|
||||
keep_audio_languages = ["eng", "jpn"]
|
||||
|
||||
# Or keep only the default audio track
|
||||
keep_only_default_audio = true
|
||||
```
|
||||
|
||||
**Audio encoding options**:
|
||||
```toml
|
||||
[transcode]
|
||||
audio_mode = "copy" # Keep original (recommended)
|
||||
# audio_mode = "aac" # Transcode to AAC
|
||||
# audio_mode = "aac_stereo" # Downmix to stereo AAC
|
||||
```
|
||||
|
||||
## Setup & Configuration
|
||||
|
||||
### Docker vs. binary installation - which should I choose?
|
||||
|
||||
| Method | Pros | Cons | Best For |
|
||||
|--------|------|------|----------|
|
||||
| **Docker** | ✅ Easy setup<br>✅ All dependencies included<br>✅ Consistent across systems<br>✅ Easy updates | ❌ Slightly more complex config<br>❌ Docker overhead | Most users, especially beginners |
|
||||
| **Binary** | ✅ Direct system access<br>✅ Lower overhead<br>✅ No Docker complexity | ❌ Manual dependency management<br>❌ Platform-specific issues | Advanced users, specialized setups |
|
||||
|
||||
**Recommendation**: Use Docker unless you have specific needs for binary installation.
|
||||
|
||||
### How do I update Alchemist?
|
||||
|
||||
**Docker update**:
|
||||
```bash
|
||||
# Pull latest image
|
||||
docker pull ghcr.io/bybrooklyn/alchemist:latest
|
||||
|
||||
# Restart container
|
||||
docker compose down && docker compose up -d
|
||||
```
|
||||
|
||||
**Binary update**:
|
||||
1. Download new binary from GitHub releases
|
||||
2. Stop current Alchemist instance
|
||||
3. Replace binary file
|
||||
4. Restart Alchemist
|
||||
|
||||
**Database migrations** are automatic - your settings and history are preserved.
|
||||
|
||||
### Can I run multiple Alchemist instances?
|
||||
|
||||
**Generally no** - Alchemist is designed as a single-instance application. However:
|
||||
|
||||
✅ **Supported scenarios**:
|
||||
- Different libraries on different machines
|
||||
- Test instance with separate config/database
|
||||
|
||||
❌ **Not supported**:
|
||||
- Multiple instances accessing the same library
|
||||
- Multiple instances sharing a database
|
||||
- Load balancing across instances
|
||||
|
||||
For high-performance setups, use:
|
||||
- Higher concurrent job count
|
||||
- Faster hardware
|
||||
- Multiple GPUs in single instance (future feature)
|
||||
|
||||
## Troubleshooting & Support
|
||||
|
||||
### Why aren't my files being processed?
|
||||
|
||||
**Common reasons files get skipped**:
|
||||
|
||||
1. **Too small**: Below `min_file_size_mb` threshold
|
||||
2. **Already efficient**: Below `size_reduction_threshold`
|
||||
3. **Good quality**: Above `min_bpp_threshold`
|
||||
4. **Wrong format**: Not a supported video file
|
||||
5. **File errors**: Corrupted or unreadable
|
||||
|
||||
Check the **Library Doctor** for detailed analysis of why files were skipped.
|
||||
|
||||
### How do I know if hardware acceleration is working?
|
||||
|
||||
**Check the Dashboard**:
|
||||
- Hardware status shows detected GPU
|
||||
- Job details show encoder being used
|
||||
|
||||
**Check system monitors**:
|
||||
```bash
|
||||
# NVIDIA
|
||||
nvidia-smi
|
||||
|
||||
# Intel
|
||||
intel_gpu_top
|
||||
|
||||
# AMD
|
||||
radeontop
|
||||
|
||||
# General
|
||||
htop # Look for low CPU usage during encoding
|
||||
```
|
||||
|
||||
**Look for logs**:
|
||||
```
|
||||
[INFO] Using NVENC for encoding
|
||||
[INFO] Hardware encoder initialized: hevc_nvenc
|
||||
```
|
||||
|
||||
### What are "Library Doctor" issues?
|
||||
|
||||
**Library Doctor** scans your media for problems:
|
||||
|
||||
- **Corrupted files**: Won't play properly
|
||||
- **Encoding errors**: Video/audio sync issues
|
||||
- **Missing data**: Incomplete downloads
|
||||
- **Format issues**: Unusual codecs or containers
|
||||
|
||||
It's a **diagnostic tool** - not all issues need fixing, but you should be aware of them.
|
||||
|
||||
### Performance is slower than expected - what to check?
|
||||
|
||||
**Diagnosis checklist**:
|
||||
|
||||
1. **Verify hardware acceleration**:
|
||||
- Check dashboard shows GPU detected
|
||||
- Monitor GPU usage during encoding
|
||||
|
||||
2. **Check system resources**:
|
||||
- CPU usage (should be low with GPU)
|
||||
- RAM availability
|
||||
- Disk speed (especially important for 4K)
|
||||
|
||||
3. **Optimize settings**:
|
||||
```toml
|
||||
[transcode]
|
||||
quality_profile = "speed" # Faster encoding
|
||||
concurrent_jobs = 1 # Reduce if system struggles
|
||||
```
|
||||
|
||||
4. **Check thermal throttling**:
|
||||
- Monitor CPU/GPU temperatures
|
||||
- Ensure adequate cooling
|
||||
|
||||
### Getting help with issues
|
||||
|
||||
**Before asking for help**:
|
||||
|
||||
1. **Check this FAQ** and the [Troubleshooting Guide](troubleshooting.md)
|
||||
2. **Search existing issues** on GitHub
|
||||
3. **Enable debug logging**: `RUST_LOG=debug`
|
||||
|
||||
**When reporting issues, include**:
|
||||
- System information (OS, hardware)
|
||||
- Alchemist version
|
||||
- Configuration file (remove sensitive data)
|
||||
- Relevant log excerpts
|
||||
- Steps to reproduce the problem
|
||||
|
||||
**Where to get help**:
|
||||
- **GitHub Issues**: [github.com/bybrooklyn/alchemist/issues](https://github.com/bybrooklyn/alchemist/issues)
|
||||
- **Documentation**: This site
|
||||
- **Community**: GitHub Discussions
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Can I customize the FFmpeg commands?
|
||||
|
||||
**Limited customization** is available through encoder args:
|
||||
|
||||
```toml
|
||||
[transcode.encoder_args]
|
||||
# Example: Custom quality settings
|
||||
extra_args = [
|
||||
"-crf", "22", # Custom quality level
|
||||
"-preset", "slower", # Custom speed preset
|
||||
"-tune", "film" # Optimize for film content
|
||||
]
|
||||
```
|
||||
|
||||
**Note**: Full FFmpeg customization isn't supported to maintain reliability and quality consistency.
|
||||
|
||||
### How do I migrate from other transcoding tools?
|
||||
|
||||
**From Tdarr**:
|
||||
- Export your Tdarr library database
|
||||
- Point Alchemist at the same directories
|
||||
- Let Alchemist re-scan and analyze files
|
||||
- Alchemist will skip already-optimized files
|
||||
|
||||
**From HandBrake batch scripts**:
|
||||
- Point Alchemist at your source directories
|
||||
- Configure similar quality settings
|
||||
- Alchemist automates the batch process
|
||||
|
||||
**From other tools**:
|
||||
- Most tools can coexist with Alchemist
|
||||
- Use different output suffixes to avoid conflicts
|
||||
- Alchemist focuses on automation vs. manual control
|
||||
|
||||
### Can I use Alchemist in a production environment?
|
||||
|
||||
**Alchemist is designed for home users** but can work in professional contexts:
|
||||
|
||||
✅ **Good for**:
|
||||
- Personal media servers
|
||||
- Small office setups
|
||||
- Content creators' personal libraries
|
||||
- Automated archival workflows
|
||||
|
||||
⚠️ **Consider limitations**:
|
||||
- Single-instance design
|
||||
- Limited customization
|
||||
- Home-focused feature set
|
||||
- Community support only
|
||||
|
||||
For enterprise needs, consider commercial solutions or custom development.
|
||||
|
||||
### Integration with media servers (Plex, Jellyfin, etc.)
|
||||
|
||||
**Alchemist works alongside media servers**:
|
||||
|
||||
1. **Point Alchemist** at your media directories
|
||||
2. **Configure output** to same location or separate folder
|
||||
3. **Media servers** automatically detect transcoded files
|
||||
4. **Use scheduling** to avoid conflicts during peak usage
|
||||
|
||||
**Best practices**:
|
||||
- Run during off-peak hours
|
||||
- Test with small batches first
|
||||
- Monitor media server performance
|
||||
- Keep originals until you verify everything works
|
||||
|
||||
**Common workflow**:
|
||||
```
|
||||
Media files → Alchemist → Optimized files → Media server → Streaming
|
||||
```
|
||||
|
||||
This setup gives you both the convenience of automated transcoding and the features of your preferred media server.
|
||||
@@ -1,182 +0,0 @@
|
||||
# Getting Started
|
||||
|
||||
Complete guide to installing and setting up Alchemist for the first time.
|
||||
|
||||
# Getting Started with Alchemist
|
||||
|
||||
This guide will walk you through installing Alchemist, completing the setup wizard, and adding your first media library. By the end, you'll have Alchemist automatically transcoding your videos to save storage space.
|
||||
|
||||
## Installation Options
|
||||
|
||||
Alchemist can be installed in three ways. **Docker is strongly recommended** for the best experience since it includes all necessary dependencies and hardware drivers.
|
||||
|
||||
### Docker (Recommended)
|
||||
|
||||
Docker provides the smoothest installation experience with automatic hardware detection and all FFmpeg dependencies pre-installed.
|
||||
|
||||
#### Docker Compose
|
||||
Create a `docker-compose.yml` file:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
alchemist:
|
||||
image: ghcr.io/bybrooklyn/alchemist:latest
|
||||
container_name: alchemist
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- ./config:/app/config
|
||||
- ./data:/app/data
|
||||
- /path/to/your/media:/media
|
||||
environment:
|
||||
- ALCHEMIST_CONFIG_PATH=/app/config/config.toml
|
||||
- ALCHEMIST_DB_PATH=/app/data/alchemist.db
|
||||
- TZ=UTC
|
||||
restart: unless-stopped
|
||||
# For NVIDIA GPUs:
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: 1
|
||||
capabilities: [gpu]
|
||||
# For Intel/AMD GPUs on Linux:
|
||||
devices:
|
||||
- /dev/dri:/dev/dri
|
||||
```
|
||||
|
||||
Then run:
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
#### Docker Run
|
||||
For a quick one-liner installation:
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name alchemist \
|
||||
-p 3000:3000 \
|
||||
-v ./config:/app/config \
|
||||
-v ./data:/app/data \
|
||||
-v /path/to/your/media:/media \
|
||||
-e ALCHEMIST_CONFIG_PATH=/app/config/config.toml \
|
||||
-e ALCHEMIST_DB_PATH=/app/data/alchemist.db \
|
||||
--restart unless-stopped \
|
||||
ghcr.io/bybrooklyn/alchemist:latest
|
||||
```
|
||||
|
||||
### Binary Installation
|
||||
|
||||
Download pre-built binaries from [GitHub Releases](https://github.com/bybrooklyn/alchemist/releases) for:
|
||||
- Linux x86_64 and ARM64
|
||||
- Windows x86_64
|
||||
- macOS Intel and Apple Silicon
|
||||
|
||||
**Requirements:**
|
||||
- FFmpeg must be installed separately
|
||||
- Hardware drivers for GPU acceleration (optional but recommended)
|
||||
|
||||
#### Install FFmpeg
|
||||
|
||||
**Linux:**
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt install ffmpeg
|
||||
|
||||
# Fedora/RHEL
|
||||
sudo dnf install ffmpeg
|
||||
|
||||
# Arch Linux
|
||||
sudo pacman -S ffmpeg
|
||||
```
|
||||
|
||||
**macOS:**
|
||||
```bash
|
||||
brew install ffmpeg
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
```bash
|
||||
winget install Gyan.FFmpeg
|
||||
```
|
||||
|
||||
#### Run Alchemist
|
||||
```bash
|
||||
# Linux/macOS
|
||||
./alchemist
|
||||
|
||||
# Windows
|
||||
alchemist.exe
|
||||
```
|
||||
|
||||
### Build from Source
|
||||
|
||||
For developers or users who want the latest features:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/bybrooklyn/alchemist.git
|
||||
cd alchemist
|
||||
cargo build --release
|
||||
./target/release/alchemist
|
||||
```
|
||||
|
||||
**Requirements:**
|
||||
- Rust toolchain (latest stable)
|
||||
- FFmpeg installed separately
|
||||
- Node.js 18+ for building the web interface
|
||||
|
||||
## First Run Setup
|
||||
|
||||
1. **Access the Web Interface**
|
||||
Open http://localhost:3000 in your browser
|
||||
|
||||
2. **Complete the Setup Wizard**
|
||||
- Set admin password
|
||||
- Choose hardware preferences
|
||||
- Configure basic transcoding settings
|
||||
- This takes about 2-3 minutes
|
||||
|
||||
3. **Hardware Detection**
|
||||
Alchemist will automatically detect:
|
||||
- NVIDIA GPUs (NVENC)
|
||||
- Intel integrated graphics (QSV)
|
||||
- AMD graphics (VAAPI/AMF)
|
||||
- Apple Silicon (VideoToolbox)
|
||||
- Falls back to CPU encoding if no GPU found
|
||||
|
||||
## Adding Your First Library
|
||||
|
||||
1. **Navigate to Watch Folders**
|
||||
Go to Settings → Watch Folders
|
||||
|
||||
2. **Add Media Directory**
|
||||
- Click "Add Folder"
|
||||
- Browse to your media collection
|
||||
- Enable "Recursive" to include subdirectories
|
||||
- Enable "Watch Mode" for automatic scanning
|
||||
|
||||
3. **Start Processing**
|
||||
- Alchemist begins scanning immediately
|
||||
- Initial scan shows which files are candidates for transcoding
|
||||
- Processing starts automatically based on your settings
|
||||
|
||||
## Understanding the Dashboard
|
||||
|
||||
Once running, monitor progress from the main dashboard:
|
||||
|
||||
- **Active Jobs**: Currently transcoding files
|
||||
- **Queue**: Files waiting to be processed
|
||||
- **Statistics**: Storage saved, files processed
|
||||
- **System Status**: Hardware usage, temperatures
|
||||
|
||||
## Next Steps
|
||||
|
||||
- **Configure Profiles**: Set different behaviors for movies vs TV shows
|
||||
- **Set Schedules**: Limit transcoding to off-peak hours
|
||||
- **Enable Notifications**: Get alerts when jobs complete
|
||||
- **Review Quality Settings**: Adjust the balance between size and quality
|
||||
|
||||
See the [Configuration Reference](reference/configuration.md) for detailed setting explanations.
|
||||
@@ -1,69 +0,0 @@
|
||||
# First Run & Setup Wizard
|
||||
|
||||
Getting through the setup wizard and starting your first scan.
|
||||
|
||||
When you first open Alchemist at
|
||||
[http://localhost:3000](http://localhost:3000), the setup
|
||||
wizard runs automatically. It takes about two minutes.
|
||||
|
||||
## The wizard steps
|
||||
|
||||
1. **Create your admin account**
|
||||
|
||||
Set a username and password. These are the credentials
|
||||
you'll use to log in to the web interface. Telemetry is
|
||||
opt-in and off by default.
|
||||
|
||||
2. **Library selection**
|
||||
|
||||
Add the server folders Alchemist should scan. If you're
|
||||
running in Docker, these are the paths as the container
|
||||
sees them - so if you mounted `/path/to/media` as
|
||||
`/media`, you enter `/media` here.
|
||||
|
||||
Alchemist auto-discovers likely media folders and shows
|
||||
them as suggestions. You can add any path manually or
|
||||
use the server browser to navigate the filesystem.
|
||||
|
||||
3. **Processing settings**
|
||||
|
||||
Choose your target codec (AV1 is the default - best
|
||||
compression, growing hardware support), quality profile,
|
||||
and output rules. The defaults are sensible for most
|
||||
libraries. You can change everything later.
|
||||
|
||||
4. **Hardware, notifications & schedule**
|
||||
|
||||
Alchemist detects your GPU automatically. You can pin a
|
||||
specific vendor, set CPU fallback behavior, configure
|
||||
Discord or webhook notifications, and define schedule
|
||||
windows so encoding only runs during off-peak hours.
|
||||
|
||||
5. **Review & complete**
|
||||
|
||||
A summary of all your choices. Click **Complete Setup**
|
||||
to write the config and start the first library scan.
|
||||
|
||||
## After setup
|
||||
|
||||
The engine starts paused after setup completes. You'll see
|
||||
an "Engine Paused" banner on the dashboard. Click **Start**
|
||||
in the header to begin processing.
|
||||
|
||||
The initial scan runs automatically in the background.
|
||||
Depending on your library size it may take a few minutes.
|
||||
Check the **Jobs** tab to watch files enter the queue.
|
||||
|
||||
> Note: The engine starts paused intentionally - this gives
|
||||
> you a chance to review what was queued before any encoding
|
||||
> begins.
|
||||
|
||||
## Changing settings later
|
||||
|
||||
Everything configured in the wizard is accessible in
|
||||
**Settings** at any time. To fully reset and re-run the
|
||||
wizard:
|
||||
|
||||
```bash
|
||||
just db-reset-all
|
||||
```
|
||||
@@ -1,126 +0,0 @@
|
||||
# Installation
|
||||
|
||||
Install Alchemist via Docker, binary, or from source.
|
||||
|
||||
Alchemist ships as a single binary with the web UI embedded.
|
||||
The Docker image also bundles FFmpeg so you don't need to
|
||||
install it separately.
|
||||
|
||||
## Docker (recommended)
|
||||
|
||||
### Docker Compose
|
||||
|
||||
Create a `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
alchemist:
|
||||
image: ghcr.io/bybrooklyn/alchemist:latest
|
||||
container_name: alchemist
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- /path/to/config:/app/config
|
||||
- /path/to/data:/app/data
|
||||
- /path/to/media:/media
|
||||
environment:
|
||||
- ALCHEMIST_CONFIG_PATH=/app/config/config.toml
|
||||
- ALCHEMIST_DB_PATH=/app/data/alchemist.db
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
Then start it:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
|
||||
### docker run
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name alchemist \
|
||||
-p 3000:3000 \
|
||||
-v /path/to/config:/app/config \
|
||||
-v /path/to/data:/app/data \
|
||||
-v /path/to/media:/media \
|
||||
-e ALCHEMIST_CONFIG_PATH=/app/config/config.toml \
|
||||
-e ALCHEMIST_DB_PATH=/app/data/alchemist.db \
|
||||
--restart unless-stopped \
|
||||
ghcr.io/bybrooklyn/alchemist:latest
|
||||
```
|
||||
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000). The
|
||||
setup wizard will guide you through the rest.
|
||||
|
||||
> Tip: For hardware acceleration (NVIDIA, Intel, AMD), you
|
||||
> need to pass your GPU into the container. See the
|
||||
> [GPU Passthrough guide](../guides/gpu-passthrough.md).
|
||||
|
||||
## Binary
|
||||
|
||||
Download the latest release from
|
||||
[GitHub Releases](https://github.com/bybrooklyn/alchemist/releases).
|
||||
Prebuilt binaries are available for:
|
||||
|
||||
- Linux x86_64 and ARM64
|
||||
- Windows x86_64
|
||||
- macOS Apple Silicon and Intel
|
||||
|
||||
FFmpeg must be installed separately for binary installs:
|
||||
|
||||
```bash
|
||||
# Debian / Ubuntu
|
||||
sudo apt install ffmpeg
|
||||
|
||||
# Fedora
|
||||
sudo dnf install ffmpeg
|
||||
|
||||
# Arch
|
||||
sudo pacman -S ffmpeg
|
||||
|
||||
# macOS
|
||||
brew install ffmpeg
|
||||
|
||||
# Windows
|
||||
winget install Gyan.FFmpeg
|
||||
```
|
||||
|
||||
Start Alchemist:
|
||||
|
||||
```bash
|
||||
./alchemist # Linux / macOS
|
||||
alchemist.exe # Windows
|
||||
```
|
||||
|
||||
Then open [http://localhost:3000](http://localhost:3000).
|
||||
|
||||
## From source
|
||||
|
||||
```bash
|
||||
git clone https://github.com/bybrooklyn/alchemist.git
|
||||
cd alchemist
|
||||
# Build frontend first
|
||||
cd web && bun install --frozen-lockfile && bun run build && cd ..
|
||||
# Build the binary
|
||||
cargo build --release
|
||||
./target/release/alchemist
|
||||
```
|
||||
|
||||
Alchemist requires Rust 1.85 or later. Run
|
||||
`rustup update stable` to ensure you are on a recent toolchain.
|
||||
FFmpeg must be installed separately.
|
||||
|
||||
## Nightly builds
|
||||
|
||||
Nightly builds are published on every push to `main` after
|
||||
Rust checks pass:
|
||||
|
||||
```bash
|
||||
docker pull ghcr.io/bybrooklyn/alchemist:nightly
|
||||
```
|
||||
|
||||
Nightly builds include the short commit hash in the version
|
||||
string (e.g. `0.3.0-dev.3-nightly+abc1234`).
|
||||
@@ -1,51 +0,0 @@
|
||||
# Quick Start
|
||||
|
||||
The essentials for getting Alchemist processing your library.
|
||||
|
||||
This guide assumes you've completed the setup wizard. If not,
|
||||
start with [First Run](first-run.md).
|
||||
|
||||
1. **Start the engine**
|
||||
|
||||
The engine starts paused after setup. Click **Start** in
|
||||
the header bar to begin processing. The button shows the
|
||||
current state - Paused, Running, or Draining.
|
||||
|
||||
2. **Watch the queue**
|
||||
|
||||
Go to **Jobs**. Files move through these states:
|
||||
`Queued -> Analyzing -> Encoding -> Completed`.
|
||||
|
||||
Skipped files appear in the **Skipped** tab with a
|
||||
plain-English explanation of why Alchemist decided not to
|
||||
transcode them. This is normal - it means the files are
|
||||
already efficiently compressed.
|
||||
|
||||
3. **Check hardware detection**
|
||||
|
||||
Go to **Settings -> Hardware** to confirm your GPU is
|
||||
detected. If you see `CPU (Software)` and you have a
|
||||
supported GPU, check the
|
||||
[GPU Passthrough guide](../guides/gpu-passthrough.md).
|
||||
|
||||
4. **See your savings**
|
||||
|
||||
Once jobs start completing, the **Statistics** page shows
|
||||
total space recovered, average compression ratio, and a
|
||||
chart of activity over time.
|
||||
|
||||
## Useful controls
|
||||
|
||||
| What | Where | Notes |
|
||||
|------|-------|-------|
|
||||
| Pause encoding | Header -> Pause | Active jobs freeze mid-encode |
|
||||
| Stop after current jobs | Header -> Stop | Drains the active jobs, starts no new ones |
|
||||
| Cancel a job | Jobs -> ... -> Cancel | Stops the job immediately |
|
||||
| Boost a job's priority | Jobs -> ... -> Boost | Moves it to the front of the queue |
|
||||
| Trigger a manual scan | Settings -> Library -> Scan | Picks up newly added files |
|
||||
| Change engine mode | Settings -> Runtime | Background / Balanced / Throughput |
|
||||
|
||||
> Tip: Use **Background** mode when you want Alchemist to run
|
||||
> without impacting your server's responsiveness. Use
|
||||
> **Throughput** when you want to clear a large backlog as
|
||||
> fast as possible.
|
||||
@@ -1,76 +0,0 @@
|
||||
# Docker
|
||||
|
||||
Docker Compose configuration, volume setup, and advanced options.
|
||||
|
||||
## Recommended Compose file
|
||||
|
||||
```yaml
|
||||
services:
|
||||
alchemist:
|
||||
image: ghcr.io/bybrooklyn/alchemist:latest
|
||||
container_name: alchemist
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- /path/to/config:/app/config
|
||||
- /path/to/data:/app/data
|
||||
- /path/to/media:/media
|
||||
- /tmp/alchemist:/tmp # optional: fast SSD for temp files
|
||||
environment:
|
||||
- ALCHEMIST_CONFIG_PATH=/app/config/config.toml
|
||||
- ALCHEMIST_DB_PATH=/app/data/alchemist.db
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
### Volume explanations
|
||||
|
||||
| Volume | Purpose |
|
||||
|--------|---------|
|
||||
| `/app/config` | Stores `config.toml`. Survives container restarts. |
|
||||
| `/app/data` | Stores `alchemist.db` (the SQLite database). Survives restarts. |
|
||||
| `/media` | Your media library. Mount read-write if Alchemist needs to write encoded files beside the source. |
|
||||
| `/tmp` (optional) | Temp directory for in-progress encodes. Mounting a fast SSD here speeds things up on large files. |
|
||||
|
||||
### Environment variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `ALCHEMIST_CONFIG_PATH` | Path to `config.toml` inside the container |
|
||||
| `ALCHEMIST_DB_PATH` | Path to the SQLite database file inside the container |
|
||||
| `ALCHEMIST_CONFIG_MUTABLE` | Set to `false` if you want config changes blocked at runtime |
|
||||
| `RUST_LOG` | Log verbosity, e.g. `info` or `alchemist=debug` |
|
||||
|
||||
> Caution: Alchemist does not use LinuxServer-style user/group
|
||||
> env vars. File permissions are handled at the host level.
|
||||
> Ensure the user running Docker has read/write access to your
|
||||
> media directories.
|
||||
|
||||
## Hardware acceleration
|
||||
|
||||
See the [GPU Passthrough guide](gpu-passthrough.md) for
|
||||
vendor-specific Docker configuration (NVIDIA, Intel, AMD).
|
||||
|
||||
## Unraid
|
||||
|
||||
An Unraid Community App template is planned. For now, use
|
||||
Docker Compose or the manual container setup.
|
||||
|
||||
## Updating
|
||||
|
||||
```bash
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Your config and database are preserved in the mounted volumes.
|
||||
Alchemist runs migrations automatically on startup when the
|
||||
schema needs updating.
|
||||
|
||||
## Nightly builds
|
||||
|
||||
```bash
|
||||
image: ghcr.io/bybrooklyn/alchemist:nightly
|
||||
```
|
||||
|
||||
Nightly builds are published on every push to `main` that
|
||||
passes Rust checks. Use `:latest` for stable releases.
|
||||
@@ -1,149 +0,0 @@
|
||||
# GPU Passthrough Guide
|
||||
|
||||
How to enable hardware acceleration for video encoding in Docker containers.
|
||||
|
||||
This guide explains how to enable hardware acceleration for video encoding in Docker containers. Using your GPU (Graphics Processing Unit) instead of your CPU (Central Processing Unit) can significantly speed up transcoding and reduce system load.
|
||||
|
||||
## NVIDIA GPU (NVENC)
|
||||
|
||||
### Prerequisites
|
||||
1. NVIDIA GPU with NVENC support (GTX 1050+ / RTX series / Quadro)
|
||||
2. NVIDIA drivers installed on host
|
||||
3. NVIDIA Container Toolkit
|
||||
|
||||
### Install NVIDIA Container Toolkit
|
||||
|
||||
```bash
|
||||
# Add NVIDIA package repository
|
||||
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
|
||||
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
|
||||
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \
|
||||
sudo tee /etc/apt/sources.list.d/nvidia-docker.list
|
||||
|
||||
# Install toolkit
|
||||
sudo apt update
|
||||
sudo apt install -y nvidia-container-toolkit
|
||||
sudo systemctl restart docker
|
||||
```
|
||||
|
||||
### Docker Compose Configuration
|
||||
|
||||
To use your NVIDIA GPU in Docker Compose, add the `deploy` section to your service:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
alchemist:
|
||||
image: ghcr.io/bybrooklyn/alchemist:latest
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: 1
|
||||
capabilities: [gpu]
|
||||
environment:
|
||||
- NVIDIA_VISIBLE_DEVICES=all
|
||||
```
|
||||
|
||||
### Docker CLI
|
||||
|
||||
If you're running Alchemist via the command line:
|
||||
|
||||
```bash
|
||||
docker run --gpus all \
|
||||
-p 3000:3000 \
|
||||
-v /media:/media \
|
||||
ghcr.io/bybrooklyn/alchemist:latest
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Intel QuickSync (QSV)
|
||||
|
||||
### Prerequisites
|
||||
1. Intel CPU with integrated graphics (6th Gen+)
|
||||
2. VAAPI drivers installed on host
|
||||
|
||||
### Install VAAPI Drivers (Host)
|
||||
|
||||
```bash
|
||||
# Debian/Ubuntu
|
||||
sudo apt install intel-media-va-driver-non-free vainfo
|
||||
|
||||
# Verify
|
||||
vainfo
|
||||
```
|
||||
|
||||
### Docker Compose Configuration
|
||||
|
||||
Pass the `/dev/dri` device into the container:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
alchemist:
|
||||
image: ghcr.io/bybrooklyn/alchemist:latest
|
||||
devices:
|
||||
- /dev/dri:/dev/dri
|
||||
group_add:
|
||||
- video
|
||||
- render
|
||||
environment:
|
||||
- LIBVA_DRIVER_NAME=iHD
|
||||
```
|
||||
|
||||
### Docker CLI
|
||||
|
||||
```bash
|
||||
docker run --device /dev/dri:/dev/dri \
|
||||
--group-add video --group-add render \
|
||||
-e LIBVA_DRIVER_NAME=iHD \
|
||||
-p 3000:3000 \
|
||||
-v /media:/media \
|
||||
ghcr.io/bybrooklyn/alchemist:latest
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## AMD GPU (VAAPI)
|
||||
|
||||
### Prerequisites
|
||||
1. AMD GPU with VAAPI support
|
||||
2. Mesa VAAPI drivers
|
||||
|
||||
### Install Drivers (Host)
|
||||
|
||||
```bash
|
||||
# Debian/Ubuntu
|
||||
sudo apt install mesa-va-drivers vainfo
|
||||
```
|
||||
|
||||
### Docker Configuration
|
||||
|
||||
Same as Intel QSV, but set the driver name to `radeonsi`:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- LIBVA_DRIVER_NAME=radeonsi
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verification
|
||||
|
||||
After starting the container, check the hardware detection in the logs (available at `/logs` in the web UI):
|
||||
|
||||
```
|
||||
Selected Hardware: Intel QSV
|
||||
Device Path: /dev/dri/renderD128
|
||||
```
|
||||
|
||||
If you see `CPU (Software)`, hardware acceleration is not working, and Alchemist is falling back to your processor.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| `vainfo: error` | Install VAAPI drivers on host |
|
||||
| `CUDA error` | Install NVIDIA Container Toolkit |
|
||||
| CPU fallback despite GPU | Check device permissions in container |
|
||||
| Permission denied on `/dev/dri` | Add `--group-add video --group-add render` |
|
||||
@@ -1,82 +0,0 @@
|
||||
# Hardware Support
|
||||
|
||||
Vendor-specific guide for hardware-accelerated transcoding.
|
||||
|
||||
This guide helps you set up and verify that Alchemist is using your computer's graphics card (GPU) or processor (CPU) correctly. Using a graphics card makes transcoding much faster and uses less electricity.
|
||||
|
||||
Alchemist supports hardware-accelerated transcoding across all major GPU vendors. This guide provides detailed information on each vendor and how to enable their specific features.
|
||||
|
||||
## Hardware Probing
|
||||
|
||||
Alchemist automatically probes for available hardware at startup. You can see the detected hardware in **Settings** > **Hardware**.
|
||||
|
||||
| Vendor | Probing Method |
|
||||
| :--- | :--- |
|
||||
| **NVIDIA** | `nvidia-smi` and checking for `_nvenc` encoders in FFmpeg. |
|
||||
| **Intel** | Checking `/dev/dri/renderD128` (or `renderD129`) and `_qsv` encoders. |
|
||||
| **AMD** | `/dev/dri/renderD128` and `_vaapi` (Linux) or `_amf` (Windows) encoders. |
|
||||
| **Apple** | Checking for `VideoToolbox` encoders. |
|
||||
| **CPU** | Always available via `libsvtav1`, `libx265`, and `libx264`. |
|
||||
|
||||
## NVIDIA (NVENC)
|
||||
|
||||
NVIDIA GPUs are highly recommended for high-quality, high-speed transcoding.
|
||||
|
||||
### Enabling NVENC
|
||||
1. Install the **NVIDIA Container Toolkit** on your host.
|
||||
2. Pass the GPU to the Docker container (see [Docker Guide](docker.md)).
|
||||
3. Set **Preferred Vendor** to `nvidia` in **Settings** > **Hardware**.
|
||||
|
||||
### Verification
|
||||
- **Log Check**: Look for "Using NVENC" in the Alchemist logs when a transcode starts.
|
||||
- **System Check**: Run `nvidia-smi` on your host machine while a transcode is running. You should see an `ffmpeg` process in the list.
|
||||
|
||||
## Intel (QuickSync / QSV)
|
||||
|
||||
Intel Integrated Graphics (iGPU) provide excellent transcoding performance with very low power consumption.
|
||||
|
||||
### Enabling QSV
|
||||
1. Ensure `/dev/dri` is passed to the container.
|
||||
2. Set **Preferred Vendor** to `intel` in **Settings** > **Hardware**.
|
||||
|
||||
### Verification
|
||||
- **Log Check**: Look for "Using QSV" in the Alchemist logs.
|
||||
- **Device Check**: Ensure `/dev/dri/renderD128` (or similar) exists inside the container. You can check this by running `ls /dev/dri` inside the container terminal.
|
||||
|
||||
## AMD (VAAPI / AMF)
|
||||
|
||||
AMD GPUs are supported on both Linux (via VAAPI) and Windows (via AMF).
|
||||
|
||||
### Enabling VAAPI (Linux)
|
||||
1. Ensure `/dev/dri` is passed to the container.
|
||||
2. Set **Preferred Vendor** to `amd` in **Settings** > **Hardware**.
|
||||
|
||||
### Verification
|
||||
- **Log Check**: Look for "Using VAAPI" (Linux) or "Using AMF" (Windows) in the logs.
|
||||
- **Device Check**: Similar to Intel, ensure `/dev/dri` devices are visible inside the container.
|
||||
|
||||
## Apple (VideoToolbox)
|
||||
|
||||
If you're running Alchemist on macOS (Apple Silicon or Intel), you can use Apple's VideoToolbox.
|
||||
|
||||
### Enabling VideoToolbox
|
||||
1. Set **Preferred Vendor** to `apple` in **Settings** > **Hardware**.
|
||||
|
||||
### Verification
|
||||
- **Log Check**: Look for "Using VideoToolbox" in the Alchemist logs.
|
||||
- **Activity Monitor**: Open Activity Monitor on your Mac; you should see `ffmpeg` using "GPU" or "Media Engine" resources.
|
||||
|
||||
## CPU Fallback (Software Encoding)
|
||||
|
||||
If no GPU is available or supported, Alchemist will fall back to software encoding using your processor.
|
||||
|
||||
### Key Features
|
||||
- **Highest Quality**: Software encoding often produces the best quality at the lowest file size, but it takes much longer.
|
||||
- **Very Slow**: Can be 10-50x slower than a graphics card.
|
||||
- **High Heat**: Your CPU will run at 100% and generate significant heat.
|
||||
|
||||
### Verification
|
||||
- **Log Check**: Look for "Using CPU (Software)" in the logs.
|
||||
- **System Check**: Your CPU usage will spike to near 100%.
|
||||
|
||||
To enable CPU fallback, check **Allow CPU fallback** in **Settings** > **Hardware**.
|
||||
@@ -1,59 +0,0 @@
|
||||
# Library Doctor
|
||||
|
||||
Scan your library for corrupt, unreadable, and broken media files.
|
||||
|
||||
Library Doctor scans your configured media directories for
|
||||
files that are corrupt, truncated, or unreadable by FFprobe.
|
||||
It surfaces issues before they surprise you during playback
|
||||
or transcoding.
|
||||
|
||||
## What it checks
|
||||
|
||||
| Check | What it detects |
|
||||
|-------|-----------------|
|
||||
| **Probe failure** | Files FFprobe cannot read at all - fully corrupt or wrong format |
|
||||
| **No video stream** | Files with no detectable video track |
|
||||
| **Zero duration** | Files reporting 0 seconds of content |
|
||||
| **Truncated file** | Files that appear to end prematurely |
|
||||
| **Missing codec data** | Files missing required metadata Alchemist needs to plan a transcode |
|
||||
|
||||
## Running a scan
|
||||
|
||||
1. Go to **Settings -> Runtime**
|
||||
2. Scroll to the **Library Doctor** section
|
||||
3. Click **Run Scan**
|
||||
4. Alchemist scans in the background - the dashboard
|
||||
shows progress
|
||||
|
||||
Results appear in the Library Doctor section after the scan
|
||||
completes. Each issue shows the file path, the issue type,
|
||||
and a brief explanation.
|
||||
|
||||
## What to do with results
|
||||
|
||||
Library Doctor reports issues but does not automatically
|
||||
delete or repair files - that decision is yours.
|
||||
|
||||
**Common actions:**
|
||||
|
||||
- **Re-download the file** - if it came from a torrent or
|
||||
download that was interrupted
|
||||
- **Re-rip the disc** - if it came from a Blu-ray or DVD
|
||||
that had errors
|
||||
- **Delete it** - if it's a duplicate or you no longer need it
|
||||
- **Ignore it** - if you know it's a weird format that
|
||||
FFprobe can't handle but your player can
|
||||
|
||||
## Scheduled scans
|
||||
|
||||
Library Doctor runs on-demand only. There is no automatic
|
||||
scheduled scan - run it manually after large library changes
|
||||
or when you suspect drive issues.
|
||||
|
||||
## Relationship to transcoding
|
||||
|
||||
Files that fail Library Doctor checks will typically also
|
||||
fail the **Analyzing** stage of a transcode job and appear
|
||||
as `Failed` in the Jobs tab with an error message. Running
|
||||
Library Doctor beforehand helps you identify and fix these
|
||||
files before queueing them.
|
||||
@@ -1,45 +0,0 @@
|
||||
# Library Setup
|
||||
|
||||
Organizing and managing your media libraries in Alchemist.
|
||||
|
||||
This page explains how to organize your movies and TV shows so Alchemist can find them easily. A little bit of organization now makes it much easier to save space later.
|
||||
|
||||
## Recommended Folder Structure
|
||||
|
||||
Alchemist works best if you group your videos by type. This lets you give different "shrinking rules" to movies versus TV shows.
|
||||
|
||||
```text
|
||||
/media/
|
||||
├── movies/
|
||||
│ ├── The Matrix (1999)/
|
||||
│ │ └── matrix.mkv
|
||||
│ └── Inception (2010)/
|
||||
│ └── inception.mp4
|
||||
└── tv/
|
||||
├── Breaking Bad/
|
||||
│ ├── Season 1/
|
||||
│ └── Season 2/
|
||||
```
|
||||
|
||||
## Adding your Folders to Alchemist
|
||||
|
||||
Once your files are organized, tell Alchemist where they are:
|
||||
1. Go to **Settings** > **Library**.
|
||||
2. Click **Add Directory**.
|
||||
3. Type in the path (like `/media/movies`).
|
||||
4. Pick a **Profile** (like "Quality First" or "Balanced").
|
||||
|
||||
## Automatic Watching
|
||||
|
||||
If you turn on **Watch folders**, Alchemist becomes a "set it and forget it" tool. Whenever you download or move a new movie into your folder, Alchemist will see it within a few seconds and automatically put it in the "to-be-shrunk" line.
|
||||
|
||||
## Using Different Settings for Different Folders
|
||||
|
||||
One of the best things about Alchemist is that you don't have to use the same settings for everything.
|
||||
- You can tell Alchemist to make your **Movies** look perfect.
|
||||
- You can tell Alchemist to make your **TV Shows** as small as possible.
|
||||
- You can tell Alchemist to **completely ignore** your "Home Videos" folder.
|
||||
|
||||
## Keeping it Clean
|
||||
|
||||
Alchemist also includes the **Library Doctor**, which checks your folders for broken files. You can run this check from the Dashboard to make sure your library stays healthy.
|
||||
@@ -1,39 +0,0 @@
|
||||
# Notifications
|
||||
|
||||
Stay informed with Alchemist's notification system.
|
||||
|
||||
Alchemist can send messages to your phone or computer to let you know when it finishes a job or if it runs into a problem. This page explains how to set up Discord, Gotify, and other alerts.
|
||||
|
||||
Alchemist can notify you when important events occur. This ensures you're always up-to-date on your transcoding progress and library health.
|
||||
|
||||
## What can Alchemist tell me?
|
||||
|
||||
You can choose to get alerts for:
|
||||
- **Transcode Finished:** "I just shrunk 'The Matrix' and saved 4GB!"
|
||||
- **Transcode Failed:** "Something went wrong with this file, please check the logs."
|
||||
- **Library Scan Finished:** "I found 10 new movies in your folders."
|
||||
- **Library Doctor Alert:** "I found a broken file that might not play correctly."
|
||||
|
||||
## How to Set it Up
|
||||
|
||||
Go to **Settings** > **Notifications** in the Alchemist web interface.
|
||||
|
||||
### Discord
|
||||
If you use Discord, Alchemist can post messages to a specific channel.
|
||||
- Create a "Webhook" in your Discord channel settings.
|
||||
- Paste that URL into Alchemist.
|
||||
- You can even give Alchemist a custom nickname like "The Alchemist Bot."
|
||||
|
||||
### Gotify
|
||||
Gotify is a great way to get private notifications on your phone without using a big service like Discord.
|
||||
- Paste your Gotify server address and "App Token" into Alchemist.
|
||||
|
||||
### Webhooks (For Techies)
|
||||
If you have your own custom system, Alchemist can send a "JSON" message to any web address you provide.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you aren't getting messages:
|
||||
1. Check that you pasted the URL or Token correctly (no extra spaces!).
|
||||
2. Make sure your computer has an internet connection.
|
||||
3. Check the **Logs** page in Alchemist; it will usually say exactly why a notification failed.
|
||||
@@ -1,39 +0,0 @@
|
||||
# Profiles
|
||||
|
||||
Customizing transcoding profiles for your media.
|
||||
|
||||
Think of "Profiles" as a set of rules for how Alchemist should shrink your videos. You can have one set of rules for high-quality movies and another for old TV shows.
|
||||
|
||||
Transcoding profiles define how Alchemist handles your media. You can choose from built-in profiles to match your specific needs.
|
||||
|
||||
## Built-in Profiles
|
||||
|
||||
Alchemist comes with several built-in profiles:
|
||||
|
||||
| Profile | Description | Best For |
|
||||
| :--- | :--- | :--- |
|
||||
| **Quality First** | Focuses on keeping every detail perfect. Files will be larger but look amazing. | 4K Movies and your favorites. |
|
||||
| **Balanced** | The "just right" setting for most people. Good size and great quality. | Standard movies and TV shows. |
|
||||
| **Space Saver** | Focuses on saving the most disk space possible. | Shows you've already seen or don't care about the tiny details. |
|
||||
| **Streaming** | Makes sure the file plays smoothly on any device, even over slow Wi-Fi. | Watching on phones or tablets. |
|
||||
|
||||
## Assigning Profiles to Folders
|
||||
|
||||
When you tell Alchemist about a folder (like `/media/movies`), you pick a profile for it. This lets you treat different parts of your library differently.
|
||||
|
||||
### Example
|
||||
- Your **Movies** folder uses **Quality First**.
|
||||
- Your **TV Shows** folder uses **Balanced**.
|
||||
- Your **Backups** folder uses **Space Saver**.
|
||||
|
||||
## What's inside a Profile?
|
||||
|
||||
If you want to get technical, each profile controls:
|
||||
- **Codec:** Which "language" the video is written in (AV1, HEVC, or H.264).
|
||||
- **Speed:** How hard the computer works. Faster is... well, faster, but slower usually makes smaller files.
|
||||
- **Subtitles:** Whether to keep them, remove them, or "burn" them into the picture.
|
||||
- **HDR:** How to handle those super-bright colors on modern TVs.
|
||||
|
||||
## Smart Skipping
|
||||
|
||||
Profiles also tell Alchemist when to *stop*. If a file is already smaller or better quality than what the profile would produce, Alchemist will skip it automatically to save time and electricity.
|
||||
@@ -1,34 +0,0 @@
|
||||
# Scheduling
|
||||
|
||||
Automating your transcoding with Alchemist's scheduler.
|
||||
|
||||
The **Scheduler** lets you decide *when* Alchemist is allowed to work. This is perfect if you want Alchemist to run while you're asleep but stop during the day so it doesn't slow down your internet or your games.
|
||||
|
||||
## Setting a Schedule
|
||||
|
||||
Go to **Settings** > **Schedule** to tell Alchemist when to work.
|
||||
|
||||
### Creating a "Work Window"
|
||||
You define a start and end time for Alchemist.
|
||||
- **Start Time:** When Alchemist can start shrinking files (e.g., 11:00 PM).
|
||||
- **End Time:** When Alchemist must stop and take a break (e.g., 7:00 AM).
|
||||
- **Days:** You can set different schedules for weekdays and weekends.
|
||||
|
||||
### Can I have more than one?
|
||||
Yes! You can have Alchemist work at night during the week, but stay active all day on Sunday while you're out of the house.
|
||||
|
||||
## What happens when time runs out?
|
||||
|
||||
If Alchemist is in the middle of shrinking a movie and the "work window" ends, it will **pause**. It saves its spot and will pick up exactly where it left off the next time the clock hits your start time.
|
||||
|
||||
## Manual Overrides
|
||||
|
||||
Even if you have a schedule set, you can always tell Alchemist to "Work Now" by clicking the **Force Start** button in the Job Manager. This is useful if you know you're going to be away from your computer for a few hours.
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
**Does pausing ruin the file?**
|
||||
No. Alchemist is very careful. It pauses FFmpeg (the engine) safely so the file stays perfectly fine.
|
||||
|
||||
**Will it wake up my computer?**
|
||||
Alchemist needs the computer to be turned on to work. It won't wake a "sleeping" computer, so make sure your power settings allow the computer to stay awake during the work window.
|
||||
@@ -1,82 +0,0 @@
|
||||
# Stream Rules
|
||||
|
||||
Control which audio tracks are kept, stripped, or filtered during transcoding.
|
||||
|
||||
Stream rules let you control which audio tracks survive the
|
||||
transcode. They run during the planning phase - before FFmpeg
|
||||
is invoked - and determine which audio streams are included
|
||||
in the output.
|
||||
|
||||
## Why use stream rules?
|
||||
|
||||
Blu-ray rips often contain three to eight audio tracks:
|
||||
the main soundtrack in multiple formats (TrueHD, DTS-HD,
|
||||
AC3), commentary tracks, descriptive audio, and foreign
|
||||
dubs. Most of that is wasted space if you only ever watch
|
||||
in one language. Stream rules let you strip it automatically.
|
||||
|
||||
## Available rules
|
||||
|
||||
### Strip audio by title
|
||||
|
||||
Removes audio tracks whose title contains any of the specified
|
||||
strings. Comparison is case-insensitive.
|
||||
|
||||
```toml
|
||||
[transcode.stream_rules]
|
||||
strip_audio_by_title = ["commentary", "director", "description", "ad"]
|
||||
```
|
||||
|
||||
This would strip tracks titled "Director's Commentary",
|
||||
"Audio Description", "AD", etc.
|
||||
|
||||
### Keep audio by language
|
||||
|
||||
Keeps only audio tracks whose language tag matches the
|
||||
specified ISO 639-2 codes. All other tracks are dropped.
|
||||
|
||||
```toml
|
||||
[transcode.stream_rules]
|
||||
keep_audio_languages = ["eng", "jpn"]
|
||||
```
|
||||
|
||||
If a track has no language tag, it is kept regardless of this
|
||||
setting (to avoid accidentally removing the only audio).
|
||||
|
||||
### Keep only default audio
|
||||
|
||||
Keeps only the track flagged as the default in the source
|
||||
file. Useful when you trust the source to have flagged the
|
||||
main soundtrack correctly.
|
||||
|
||||
```toml
|
||||
[transcode.stream_rules]
|
||||
keep_only_default_audio = true
|
||||
```
|
||||
|
||||
> Note: `keep_only_default_audio` is evaluated after language
|
||||
> rules. If no track survives the language filter, the
|
||||
> default track is kept as a fallback to ensure the output
|
||||
> always has audio.
|
||||
|
||||
## Rule evaluation order
|
||||
|
||||
1. `strip_audio_by_title` - runs first, removes matched tracks
|
||||
2. `keep_audio_languages` - runs on the remaining tracks
|
||||
3. `keep_only_default_audio` - runs last on the remaining tracks
|
||||
4. Fallback: if no tracks remain, the original default track
|
||||
is kept
|
||||
|
||||
## Example: lean English-only output
|
||||
|
||||
```toml
|
||||
[transcode.stream_rules]
|
||||
strip_audio_by_title = ["commentary", "description", "ad"]
|
||||
keep_audio_languages = ["eng"]
|
||||
```
|
||||
|
||||
## Configuring in the UI
|
||||
|
||||
Stream rules are set in **Settings -> Transcoding -> Stream
|
||||
Rules**. Changes take effect for jobs queued after the save.
|
||||
Active jobs continue with the rules they were planned with.
|
||||
@@ -1,86 +0,0 @@
|
||||
# Web Interface
|
||||
|
||||
Overview of the Alchemist dashboard and what each section does.
|
||||
|
||||
The Alchemist web interface is a single-page app served from
|
||||
the same binary as the backend. No separate web server needed.
|
||||
|
||||
## Dashboard
|
||||
|
||||
The first page you see after setup. Shows:
|
||||
|
||||
- **Engine state** - whether the engine is running, paused,
|
||||
or draining, with Start/Pause/Stop controls in the header
|
||||
- **Stat row** - active jobs, completed, failed, total
|
||||
processed (compact, updated in real time via SSE)
|
||||
- **Recent Activity** - the last five jobs with status dots
|
||||
and timestamps
|
||||
- **Configuration summary** - library roots, notification
|
||||
targets, schedule windows
|
||||
- **Quick Start tips** - only shown when there's something
|
||||
actionable (failures, no library configured)
|
||||
- **Resource Monitor** - CPU usage, memory, and GPU metrics
|
||||
|
||||
## Jobs
|
||||
|
||||
The main job management interface.
|
||||
|
||||
**Tabs:** All / Active / Queued / Completed / Failed /
|
||||
Skipped / Archived
|
||||
|
||||
Each row shows filename, status badge, progress bar (for
|
||||
active jobs), and last updated time. Click any row to open
|
||||
the detail panel showing:
|
||||
|
||||
- Input metadata (codec, resolution, bitrate, duration)
|
||||
- Output stats (result size, compression ratio, VMAF score)
|
||||
- Skip or failure reason with plain-English explanation
|
||||
- Full FFmpeg log for the job
|
||||
|
||||
**Bulk actions:** Select multiple jobs with the checkboxes
|
||||
to restart, cancel, or delete in one operation.
|
||||
|
||||
## Logs
|
||||
|
||||
Real-time log viewer fed by SSE. Entries are grouped by job
|
||||
- click a job header to expand its log lines. System logs
|
||||
appear at the top. Filterable by level (info/warn/error)
|
||||
with text search.
|
||||
|
||||
## Statistics
|
||||
|
||||
Space savings over time as an area chart, per-codec
|
||||
breakdown, and aggregate totals. Data comes from completed
|
||||
jobs - the chart fills in as jobs complete.
|
||||
|
||||
## Settings
|
||||
|
||||
Ten tabs covering every configurable aspect of Alchemist:
|
||||
|
||||
| Tab | What it controls |
|
||||
|-----|-----------------|
|
||||
| Library | Watch folders, scan trigger |
|
||||
| Watch Folders | Extra directories to monitor |
|
||||
| Transcoding | Codec, quality, thresholds, stream rules |
|
||||
| Hardware | GPU vendor, device path, fallback behavior |
|
||||
| File Settings | Output extension, suffix, output root, replace strategy |
|
||||
| Quality | VMAF scoring, minimum score, revert on failure |
|
||||
| Notifications | Discord, Gotify, webhook targets and events |
|
||||
| Schedule | Time windows when encoding is allowed |
|
||||
| Runtime | Engine mode (Background/Balanced/Throughput), Library Doctor |
|
||||
| Appearance | Color theme selection (35+ themes) |
|
||||
|
||||
## Appearance
|
||||
|
||||
35+ color themes selectable from the Appearance settings.
|
||||
Themes range from warm darks (Helios Orange, Ember, Sunset)
|
||||
to cool darks (Ocean, Glacier, Nocturne) to light modes
|
||||
(Ivory, Cloud, Linen). The selected theme persists across
|
||||
sessions.
|
||||
|
||||
## Engine control header
|
||||
|
||||
Visible on every page. Shows the current engine state and
|
||||
provides Start, Pause, and Stop buttons. Stop puts the engine
|
||||
into **drain** mode - active jobs finish normally, no new
|
||||
jobs start. Cancel the drain to resume normal operation.
|
||||
@@ -1,370 +0,0 @@
|
||||
# AMD GPU Setup (VAAPI/AMF)
|
||||
|
||||
Complete guide to setting up AMD hardware acceleration using VAAPI (Linux) and AMF (Windows).
|
||||
|
||||
# AMD GPU Setup (VAAPI/AMF)
|
||||
|
||||
AMD GPUs support hardware-accelerated encoding through VAAPI on Linux and AMF on Windows. This guide covers setup and optimization for AMD Radeon graphics cards.
|
||||
|
||||
## Supported Hardware
|
||||
|
||||
Hardware encoding support varies by AMD GPU generation:
|
||||
|
||||
| Generation | Codecs | Linux (VAAPI) | Windows (AMF) |
|
||||
|------------|---------|---------------|---------------|
|
||||
| **GCN 1.0 (HD 7000)** | H.264 | Limited | Limited |
|
||||
| **GCN 2.0 (R7/R9 200)** | H.264 | Yes | Yes |
|
||||
| **GCN 3.0/4.0 (RX 400/500)** | H.264, HEVC | Yes | Yes |
|
||||
| **RDNA 1 (RX 5000)** | H.264, HEVC | Yes | Yes |
|
||||
| **RDNA 2 (RX 6000)** | H.264, HEVC | Yes | Yes |
|
||||
| **RDNA 3 (RX 7000)** | H.264, HEVC, AV1 | Yes | Yes |
|
||||
|
||||
### Checking Your Hardware
|
||||
|
||||
**Linux (VAAPI):**
|
||||
```bash
|
||||
# Check for AMD GPU
|
||||
lspci | grep -i amd
|
||||
|
||||
# Verify VAAPI support
|
||||
vainfo --display drm --device /dev/dri/renderD128
|
||||
|
||||
# Check available encoders
|
||||
ffmpeg -encoders | grep vaapi
|
||||
```
|
||||
|
||||
**Windows (AMF):**
|
||||
```bash
|
||||
# Check FFmpeg AMF encoders
|
||||
ffmpeg -encoders | grep amf
|
||||
```
|
||||
|
||||
Expected output (Linux):
|
||||
```
|
||||
V....D h264_vaapi H.264/AVC (VAAPI) (codec h264)
|
||||
V....D hevc_vaapi H.265/HEVC (VAAPI) (codec hevc)
|
||||
```
|
||||
|
||||
Expected output (Windows):
|
||||
```
|
||||
V....D h264_amf AMD AMF H.264 Encoder (codec h264)
|
||||
V....D hevc_amf AMD AMF HEVC encoder (codec hevc)
|
||||
```
|
||||
|
||||
## Linux Setup (VAAPI)
|
||||
|
||||
### Docker Installation
|
||||
|
||||
1. **Pass GPU devices:**
|
||||
```yaml
|
||||
services:
|
||||
alchemist:
|
||||
image: ghcr.io/bybrooklyn/alchemist:latest
|
||||
devices:
|
||||
- /dev/dri:/dev/dri
|
||||
group_add:
|
||||
- video
|
||||
- render
|
||||
```
|
||||
|
||||
2. **Verify GPU access:**
|
||||
```bash
|
||||
docker exec -it alchemist ls -la /dev/dri/
|
||||
# Should show renderD128 or similar
|
||||
```
|
||||
|
||||
### Binary Installation
|
||||
|
||||
1. **Install AMD drivers:**
|
||||
|
||||
**Ubuntu/Debian:**
|
||||
```bash
|
||||
# Add AMD GPU repository
|
||||
wget -q -O - https://repo.radeon.com/rocm/rocm.gpg.key | sudo apt-key add -
|
||||
echo 'deb [arch=amd64] https://repo.radeon.com/rocm/apt/debian/ focal main' | sudo tee /etc/apt/sources.list.d/rocm.list
|
||||
sudo apt update
|
||||
|
||||
# Install drivers
|
||||
sudo apt install rocm-dkms
|
||||
sudo apt install mesa-va-drivers
|
||||
```
|
||||
|
||||
**Fedora/RHEL:**
|
||||
```bash
|
||||
sudo dnf install mesa-va-drivers
|
||||
sudo dnf install libva-utils
|
||||
```
|
||||
|
||||
**Arch Linux:**
|
||||
```bash
|
||||
sudo pacman -S mesa-va-drivers
|
||||
sudo pacman -S libva-utils
|
||||
```
|
||||
|
||||
2. **Verify VAAPI:**
|
||||
```bash
|
||||
vainfo --display drm --device /dev/dri/renderD128
|
||||
```
|
||||
|
||||
3. **User permissions:**
|
||||
```bash
|
||||
sudo usermod -a -G video $USER
|
||||
sudo usermod -a -G render $USER
|
||||
# Log out and back in
|
||||
```
|
||||
|
||||
## Windows Setup (AMF)
|
||||
|
||||
### Requirements
|
||||
|
||||
1. **AMD Adrenalin drivers** (latest version recommended)
|
||||
2. **AMD AMF SDK** (included with drivers)
|
||||
3. **FFmpeg with AMF support**
|
||||
|
||||
### Installation
|
||||
|
||||
1. **Download AMD drivers:**
|
||||
- Visit [amd.com/support](https://amd.com/support)
|
||||
- Download latest Adrenalin drivers
|
||||
- Install with "Standard" or "Custom" installation
|
||||
|
||||
2. **Verify AMF support:**
|
||||
```cmd
|
||||
ffmpeg -encoders | findstr amf
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### In Alchemist
|
||||
|
||||
**Linux (VAAPI):**
|
||||
1. Navigate to **Settings** → **Hardware**
|
||||
2. Set **Preferred Vendor** to `amd`
|
||||
3. Set **Device Path** to `/dev/dri/renderD128`
|
||||
4. Verify "AMD VAAPI" appears in hardware status
|
||||
|
||||
**Windows (AMF):**
|
||||
1. Navigate to **Settings** → **Hardware**
|
||||
2. Set **Preferred Vendor** to `amd`
|
||||
3. Leave **Device Path** empty
|
||||
4. Verify "AMD AMF" appears in hardware status
|
||||
|
||||
### Quality Settings
|
||||
|
||||
AMD encoding quality varies by implementation:
|
||||
|
||||
**VAAPI Quality (Linux):**
|
||||
| Profile | Quality Level | Use Case |
|
||||
|---------|--------------|----------|
|
||||
| **Quality** | High | Best quality, slower |
|
||||
| **Balanced** | Medium | Good balance |
|
||||
| **Speed** | Fast | Faster encoding |
|
||||
|
||||
**AMF Quality (Windows):**
|
||||
| Profile | CRF/Quality | Use Case |
|
||||
|---------|-------------|----------|
|
||||
| **Quality** | 20-24 | Archive quality |
|
||||
| **Balanced** | 25-28 | General use |
|
||||
| **Speed** | 29-32 | Quick turnaround |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Linux (VAAPI)
|
||||
|
||||
#### "No VAAPI device found"
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Check GPU detection:**
|
||||
```bash
|
||||
lspci | grep -i vga
|
||||
dmesg | grep amdgpu
|
||||
```
|
||||
|
||||
2. **Verify device nodes:**
|
||||
```bash
|
||||
ls -la /dev/dri/
|
||||
# Should show renderD128, card0, etc.
|
||||
```
|
||||
|
||||
3. **Test VAAPI directly:**
|
||||
```bash
|
||||
vainfo --display drm --device /dev/dri/renderD128
|
||||
```
|
||||
|
||||
#### "VAAPI initialization failed"
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Install mesa drivers:**
|
||||
```bash
|
||||
sudo apt install mesa-va-drivers libva-dev
|
||||
```
|
||||
|
||||
2. **Set environment variables:**
|
||||
```bash
|
||||
export LIBVA_DRIVER_NAME=radeonsi
|
||||
export LIBVA_DRIVERS_PATH=/usr/lib/x86_64-linux-gnu/dri
|
||||
```
|
||||
|
||||
3. **Check user groups:**
|
||||
```bash
|
||||
groups $USER
|
||||
# Should include 'video' and 'render'
|
||||
```
|
||||
|
||||
### Windows (AMF)
|
||||
|
||||
#### "AMF encoder not available"
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Update AMD drivers:**
|
||||
- Download latest Adrenalin drivers
|
||||
- Use DDU (Display Driver Uninstaller) if needed
|
||||
|
||||
2. **Verify GPU detection:**
|
||||
```cmd
|
||||
dxdiag
|
||||
# Check Display tab for AMD GPU
|
||||
```
|
||||
|
||||
3. **Check Windows version:**
|
||||
- AMF requires Windows 10 or later
|
||||
- Update Windows if necessary
|
||||
|
||||
#### Poor quality output
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Adjust quality settings:**
|
||||
```toml
|
||||
[transcode]
|
||||
quality_profile = "quality"
|
||||
```
|
||||
|
||||
2. **Use constant quality mode:**
|
||||
```toml
|
||||
[transcode.encoder_args]
|
||||
extra_args = ["-rc", "cqp", "-qp_i", "22", "-qp_p", "24"]
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Linux Optimization
|
||||
|
||||
1. **Enable GPU scheduler:**
|
||||
```bash
|
||||
echo 'KERNEL=="card*", SUBSYSTEM=="drm", DRIVERS=="amdgpu", ATTR{device/power_dpm_force_performance_level}="high"' | sudo tee /etc/udev/rules.d/30-amdgpu-pm.rules
|
||||
sudo udevadm control --reload-rules
|
||||
```
|
||||
|
||||
2. **Optimize for encoding:**
|
||||
```bash
|
||||
echo high | sudo tee /sys/class/drm/card*/device/power_dpm_force_performance_level
|
||||
```
|
||||
|
||||
### Windows Optimization
|
||||
|
||||
1. **AMD Adrenalin settings:**
|
||||
- Open AMD Software
|
||||
- Graphics → Advanced → GPU Workload → "Compute"
|
||||
- Set Power Limit to maximum
|
||||
|
||||
2. **Registry optimizations:**
|
||||
```reg
|
||||
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\0000]
|
||||
"PP_ThermalAutoThrottlingEnable"=dword:00000000
|
||||
```
|
||||
|
||||
### Concurrent Encoding
|
||||
|
||||
AMD GPUs generally support fewer concurrent streams than NVIDIA:
|
||||
|
||||
```toml
|
||||
[transcode]
|
||||
concurrent_jobs = 1 # Start with 1, test higher values
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Codec Selection
|
||||
|
||||
#### HEVC (Recommended)
|
||||
- Best quality/size ratio
|
||||
- Good AMD hardware support
|
||||
- Wide compatibility
|
||||
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "hevc"
|
||||
quality_profile = "balanced"
|
||||
```
|
||||
|
||||
#### H.264 (Maximum compatibility)
|
||||
- Universal playback support
|
||||
- Fastest encoding
|
||||
- Larger file sizes
|
||||
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "h264"
|
||||
quality_profile = "speed"
|
||||
```
|
||||
|
||||
### Quality Settings
|
||||
|
||||
For best results with AMD encoding:
|
||||
|
||||
**Linux (VAAPI):**
|
||||
```toml
|
||||
[transcode.encoder_args]
|
||||
extra_args = ["-vaapi_device", "/dev/dri/renderD128", "-qp", "24"]
|
||||
```
|
||||
|
||||
**Windows (AMF):**
|
||||
```toml
|
||||
[transcode.encoder_args]
|
||||
extra_args = ["-usage", "transcoding", "-rc", "cqp", "-qp", "24"]
|
||||
```
|
||||
|
||||
### Thermal Management
|
||||
|
||||
AMD GPUs can run hot during extended encoding:
|
||||
|
||||
1. **Monitor temperatures:**
|
||||
```bash
|
||||
# Linux
|
||||
sensors
|
||||
|
||||
# Windows - Use MSI Afterburner or AMD Software
|
||||
```
|
||||
|
||||
2. **Adjust fan curves** in AMD Software
|
||||
|
||||
3. **Consider undervolting** for 24/7 operation
|
||||
|
||||
### Power Efficiency
|
||||
|
||||
For always-on systems:
|
||||
- Lower power limits in AMD Software
|
||||
- Use "Balanced" or "Speed" quality profiles
|
||||
- Enable power management features
|
||||
- Consider concurrent job limits
|
||||
|
||||
## Hardware-Specific Notes
|
||||
|
||||
### Older AMD Cards (Pre-RDNA)
|
||||
- Limited to H.264 encoding
|
||||
- Quality may be lower than modern cards
|
||||
- Consider CPU fallback for critical content
|
||||
|
||||
### APUs (Integrated Graphics)
|
||||
- Share system memory
|
||||
- Thermal constraints in compact systems
|
||||
- Good for low-power applications
|
||||
|
||||
### High-end Cards (RX 6000/7000)
|
||||
- Excellent encoding performance
|
||||
- Support for modern codecs
|
||||
- May require adequate cooling
|
||||
@@ -1,370 +0,0 @@
|
||||
# Apple VideoToolbox Setup
|
||||
|
||||
Complete guide to setting up Apple VideoToolbox hardware acceleration on macOS.
|
||||
|
||||
# Apple VideoToolbox Setup
|
||||
|
||||
Apple VideoToolbox provides hardware-accelerated encoding on macOS using built-in media engines in Apple Silicon and Intel Macs. This is the most efficient option for macOS users.
|
||||
|
||||
## Supported Hardware
|
||||
|
||||
VideoToolbox support varies by Mac model and codec:
|
||||
|
||||
| Hardware | H.264 | HEVC | AV1 | Notes |
|
||||
|----------|-------|------|-----|-------|
|
||||
| **Intel Macs (2016+)** | ✅ | ✅ | ❌ | Requires T2 chip for HEVC |
|
||||
| **Apple Silicon M1** | ✅ | ✅ | ❌ | Dedicated media engines |
|
||||
| **Apple Silicon M2** | ✅ | ✅ | ❌ | Enhanced media engines |
|
||||
| **Apple Silicon M3** | ✅ | ✅ | ✅ | AV1 encode/decode support |
|
||||
|
||||
### Checking Your Hardware
|
||||
|
||||
Verify VideoToolbox support:
|
||||
```bash
|
||||
# Check available encoders
|
||||
ffmpeg -encoders | grep videotoolbox
|
||||
|
||||
# System information
|
||||
system_profiler SPHardwareDataType
|
||||
```
|
||||
|
||||
Expected output:
|
||||
```
|
||||
V....D h264_videotoolbox VideoToolbox H.264 Encoder (codec h264)
|
||||
V....D hevc_videotoolbox VideoToolbox H.265 Encoder (codec hevc)
|
||||
```
|
||||
|
||||
On M3 Macs:
|
||||
```
|
||||
V....D av1_videotoolbox VideoToolbox AV1 Encoder (codec av1)
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
### Docker Setup
|
||||
|
||||
Running Docker on macOS with VideoToolbox requires special configuration:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
services:
|
||||
alchemist:
|
||||
image: ghcr.io/bybrooklyn/alchemist:latest
|
||||
container_name: alchemist
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- ./config:/app/config
|
||||
- ./data:/app/data
|
||||
- /path/to/media:/media
|
||||
environment:
|
||||
- ALCHEMIST_CONFIG_PATH=/app/config/config.toml
|
||||
- ALCHEMIST_DB_PATH=/app/data/alchemist.db
|
||||
# VideoToolbox access from container is limited
|
||||
# Binary installation recommended for best results
|
||||
```
|
||||
|
||||
⚠️ **Note**: Docker containers on macOS have limited access to VideoToolbox. Binary installation is recommended for optimal performance.
|
||||
|
||||
### Binary Installation (Recommended)
|
||||
|
||||
1. **Download Alchemist binary** for macOS from [GitHub Releases](https://github.com/bybrooklyn/alchemist/releases)
|
||||
|
||||
2. **Install FFmpeg with VideoToolbox:**
|
||||
```bash
|
||||
# Using Homebrew (recommended)
|
||||
brew install ffmpeg
|
||||
|
||||
# Verify VideoToolbox support
|
||||
ffmpeg -encoders | grep videotoolbox
|
||||
```
|
||||
|
||||
3. **Run Alchemist:**
|
||||
```bash
|
||||
chmod +x alchemist-macos
|
||||
./alchemist-macos
|
||||
```
|
||||
|
||||
### Build from Source
|
||||
|
||||
For the latest features:
|
||||
```bash
|
||||
# Install Rust
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
|
||||
# Clone and build
|
||||
git clone https://github.com/bybrooklyn/alchemist.git
|
||||
cd alchemist
|
||||
cargo build --release
|
||||
|
||||
./target/release/alchemist
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### In Alchemist
|
||||
|
||||
1. Navigate to **Settings** → **Hardware**
|
||||
2. Set **Preferred Vendor** to `apple`
|
||||
3. Leave **Device Path** empty (not applicable)
|
||||
4. Verify "Apple VideoToolbox" appears in hardware status
|
||||
|
||||
### Quality Settings
|
||||
|
||||
VideoToolbox uses quality values (higher = better quality):
|
||||
|
||||
| Profile | Quality Value | Use Case |
|
||||
|---------|--------------|----------|
|
||||
| **Quality** | 55 | Best quality, larger files |
|
||||
| **Balanced** | 65 | Good balance |
|
||||
| **Speed** | 75 | Faster encoding, smaller quality |
|
||||
|
||||
### Codec-Specific Configuration
|
||||
|
||||
#### HEVC (Recommended)
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "hevc"
|
||||
quality_profile = "balanced"
|
||||
|
||||
[hardware]
|
||||
preferred_vendor = "apple"
|
||||
```
|
||||
|
||||
#### H.264 (Maximum compatibility)
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "h264"
|
||||
quality_profile = "speed" # H.264 encodes quickly
|
||||
```
|
||||
|
||||
#### AV1 (M3 only)
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "av1"
|
||||
quality_profile = "quality" # AV1 benefits from higher quality
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "VideoToolbox encoder not available"
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Check macOS version:**
|
||||
- macOS 10.13+ required for HEVC
|
||||
- macOS 14+ required for AV1 (M3 only)
|
||||
|
||||
2. **Verify hardware support:**
|
||||
```bash
|
||||
system_profiler SPHardwareDataType | grep "Model Identifier"
|
||||
```
|
||||
|
||||
3. **Test FFmpeg directly:**
|
||||
```bash
|
||||
ffmpeg -f lavfi -i color=c=black:s=64x64:d=0.1 \
|
||||
-vf format=yuv420p \
|
||||
-c:v hevc_videotoolbox \
|
||||
-allow_sw 1 \
|
||||
-frames:v 1 -f null -
|
||||
```
|
||||
|
||||
### Poor quality output
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Adjust quality settings:**
|
||||
```toml
|
||||
[transcode]
|
||||
quality_profile = "quality"
|
||||
```
|
||||
|
||||
2. **Use lower quality values (better quality):**
|
||||
```toml
|
||||
[transcode.encoder_args]
|
||||
extra_args = ["-q:v", "50"] # Lower = better quality
|
||||
```
|
||||
|
||||
3. **Enable constant quality mode:**
|
||||
```toml
|
||||
[transcode.encoder_args]
|
||||
extra_args = ["-b:v", "0"] # Forces constant quality
|
||||
```
|
||||
|
||||
### Slow encoding performance
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Check thermal throttling:**
|
||||
```bash
|
||||
# Monitor CPU temperature
|
||||
sudo powermetrics --samplers smc -n 1
|
||||
```
|
||||
|
||||
2. **Adjust concurrent jobs:**
|
||||
```toml
|
||||
[transcode]
|
||||
concurrent_jobs = 1 # Start with 1 on MacBooks
|
||||
```
|
||||
|
||||
3. **Optimize for battery/thermal:**
|
||||
```toml
|
||||
[transcode]
|
||||
quality_profile = "speed"
|
||||
threads = 4 # Limit CPU usage
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Apple Silicon Optimization
|
||||
|
||||
Apple Silicon Macs have dedicated media engines:
|
||||
|
||||
```toml
|
||||
[transcode]
|
||||
concurrent_jobs = 2 # M1/M2 can handle 2 concurrent streams
|
||||
quality_profile = "balanced"
|
||||
```
|
||||
|
||||
**M3 Macs** with enhanced engines:
|
||||
```toml
|
||||
[transcode]
|
||||
concurrent_jobs = 3 # M3 Pro/Max can handle more
|
||||
output_codec = "av1" # Take advantage of AV1 support
|
||||
```
|
||||
|
||||
### Intel Mac Optimization
|
||||
|
||||
Intel Macs rely on CPU + T2 chip:
|
||||
|
||||
```toml
|
||||
[transcode]
|
||||
concurrent_jobs = 1 # Conservative for thermal management
|
||||
threads = 8 # Use available CPU cores
|
||||
quality_profile = "balanced"
|
||||
```
|
||||
|
||||
### Battery Life (MacBooks)
|
||||
|
||||
For better battery life during encoding:
|
||||
|
||||
```toml
|
||||
[transcode]
|
||||
quality_profile = "speed"
|
||||
concurrent_jobs = 1
|
||||
threads = 4
|
||||
|
||||
[schedule]
|
||||
# Only encode when plugged in
|
||||
[[schedule.windows]]
|
||||
start_time = "22:00"
|
||||
end_time = "06:00"
|
||||
enabled = true
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Thermal Management
|
||||
|
||||
**MacBooks** (especially Intel models) can throttle during extended encoding:
|
||||
|
||||
1. **Monitor temperatures:**
|
||||
```bash
|
||||
# Install temperature monitoring
|
||||
brew install stats
|
||||
```
|
||||
|
||||
2. **Use clamshell mode** when possible (better cooling)
|
||||
|
||||
3. **External cooling** for extended sessions
|
||||
|
||||
4. **Lower quality profiles** for bulk operations
|
||||
|
||||
### Power Management
|
||||
|
||||
**Battery considerations:**
|
||||
- Use "Speed" profile on battery
|
||||
- Schedule encoding for AC power
|
||||
- Monitor battery usage in Activity Monitor
|
||||
|
||||
**Desktop Macs:**
|
||||
- Can sustain higher workloads
|
||||
- Better thermal management
|
||||
- Support for longer concurrent jobs
|
||||
|
||||
### Codec Selection
|
||||
|
||||
#### For M3 Macs (AV1 support)
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "av1"
|
||||
quality_profile = "quality"
|
||||
# Best compression, future-proof
|
||||
```
|
||||
|
||||
#### For M1/M2 Macs
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "hevc"
|
||||
quality_profile = "balanced"
|
||||
# Excellent efficiency, wide support
|
||||
```
|
||||
|
||||
#### For older Intel Macs
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "h264"
|
||||
quality_profile = "speed"
|
||||
# Most compatible, least thermal stress
|
||||
```
|
||||
|
||||
### Quality vs. Speed
|
||||
|
||||
**Archive quality** (slow but excellent):
|
||||
```toml
|
||||
[transcode]
|
||||
quality_profile = "quality"
|
||||
concurrent_jobs = 1
|
||||
|
||||
[transcode.encoder_args]
|
||||
extra_args = ["-q:v", "45"]
|
||||
```
|
||||
|
||||
**Balanced performance** (recommended):
|
||||
```toml
|
||||
[transcode]
|
||||
quality_profile = "balanced"
|
||||
concurrent_jobs = 2 # Apple Silicon only
|
||||
```
|
||||
|
||||
**Fast turnaround** (quick results):
|
||||
```toml
|
||||
[transcode]
|
||||
quality_profile = "speed"
|
||||
concurrent_jobs = 1
|
||||
|
||||
[transcode.encoder_args]
|
||||
extra_args = ["-q:v", "75"]
|
||||
```
|
||||
|
||||
## Hardware-Specific Notes
|
||||
|
||||
### MacBook Air
|
||||
- **Fanless design** limits sustained performance
|
||||
- Use conservative settings for long encodes
|
||||
- Monitor thermal throttling
|
||||
|
||||
### MacBook Pro
|
||||
- **Better cooling** supports higher workloads
|
||||
- 14"/16" models handle concurrent jobs better
|
||||
- Intel models may need thermal management
|
||||
|
||||
### Mac Studio/Pro
|
||||
- **Excellent cooling** for sustained workloads
|
||||
- Can handle maximum concurrent jobs
|
||||
- Ideal for bulk transcoding operations
|
||||
|
||||
### Mac mini
|
||||
- **Good performance** but compact thermal design
|
||||
- Monitor temperatures during heavy use
|
||||
- Balance between performance and heat
|
||||
@@ -1,377 +0,0 @@
|
||||
# CPU Encoding (Software Fallback)
|
||||
|
||||
Guide to CPU-based software encoding when hardware acceleration is unavailable.
|
||||
|
||||
# CPU Encoding (Software Fallback)
|
||||
|
||||
When hardware acceleration isn't available or enabled, Alchemist falls back to CPU-based software encoding. While slower than GPU acceleration, modern CPUs can produce excellent quality results.
|
||||
|
||||
## Supported Encoders
|
||||
|
||||
Alchemist uses these high-quality software encoders:
|
||||
|
||||
| Codec | Encoder | Quality | Speed | Use Case |
|
||||
|-------|---------|---------|-------|----------|
|
||||
| **AV1** | SVT-AV1 | Excellent | Medium | Future-proof archival |
|
||||
| **AV1** | libaom-av1 | Best | Slow | Maximum quality |
|
||||
| **HEVC** | x265 | Excellent | Medium | General purpose |
|
||||
| **H.264** | x264 | Very Good | Fast | Compatibility |
|
||||
|
||||
### Checking CPU Encoders
|
||||
|
||||
Verify available software encoders:
|
||||
```bash
|
||||
ffmpeg -encoders | grep -E "libsvtav1|libaom|libx265|libx264"
|
||||
```
|
||||
|
||||
Expected output:
|
||||
```
|
||||
V....D libsvtav1 SVT-AV1(Scalable Video Technology for AV1) encoder (codec av1)
|
||||
V....D libaom-av1 libaom AV1 (codec av1)
|
||||
V....D libx265 libx265 H.265 / HEVC (codec hevc)
|
||||
V....D libx264 libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (codec h264)
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Enabling CPU Encoding
|
||||
|
||||
```toml
|
||||
[hardware]
|
||||
preferred_vendor = "cpu" # Force CPU encoding
|
||||
allow_cpu_encoding = true
|
||||
cpu_preset = "medium"
|
||||
|
||||
[transcode]
|
||||
output_codec = "av1" # Recommended for CPU encoding
|
||||
quality_profile = "balanced"
|
||||
```
|
||||
|
||||
### CPU Presets
|
||||
|
||||
CPU presets balance encoding speed vs. quality:
|
||||
|
||||
| Preset | SVT-AV1 | x265 | x264 | Use Case |
|
||||
|--------|---------|------|------|----------|
|
||||
| **Slow** | 4 | slow | slow | Maximum quality, archival |
|
||||
| **Medium** | 8 | medium | medium | Balanced performance |
|
||||
| **Fast** | 12 | fast | fast | Quick turnaround |
|
||||
| **Faster** | 13 | faster | faster | Speed priority |
|
||||
|
||||
### Quality Settings
|
||||
|
||||
Quality profiles adjust CRF (Constant Rate Factor) values:
|
||||
|
||||
| Profile | AV1 CRF | HEVC CRF | H.264 CRF | File Size | Quality |
|
||||
|---------|---------|----------|-----------|-----------|---------|
|
||||
| **Quality** | 24 | 22 | 20 | Larger | Best |
|
||||
| **Balanced** | 28 | 26 | 23 | Medium | Good |
|
||||
| **Speed** | 32 | 30 | 26 | Smaller | Acceptable |
|
||||
|
||||
### Thread Configuration
|
||||
|
||||
Optimize CPU thread usage:
|
||||
|
||||
```toml
|
||||
[transcode]
|
||||
threads = 0 # Auto-detect (recommended)
|
||||
# Or set manually:
|
||||
# threads = 8 # Use 8 threads per job
|
||||
|
||||
concurrent_jobs = 1 # Start with 1, increase carefully
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Thread Allocation
|
||||
|
||||
**Rule of thumb**: Total threads = cores × concurrent_jobs
|
||||
|
||||
| CPU Cores | Suggested Config |
|
||||
|-----------|------------------|
|
||||
| **4 cores** | 1 job, 4 threads |
|
||||
| **8 cores** | 1 job, 8 threads or 2 jobs, 4 threads each |
|
||||
| **16 cores** | 2 jobs, 8 threads each |
|
||||
| **32+ cores** | 4 jobs, 8 threads each |
|
||||
|
||||
```toml
|
||||
# Example: 16-core CPU
|
||||
[transcode]
|
||||
concurrent_jobs = 2
|
||||
threads = 8
|
||||
```
|
||||
|
||||
### Memory Considerations
|
||||
|
||||
Software encoding is memory-intensive:
|
||||
|
||||
| Resolution | Recommended RAM per Job |
|
||||
|------------|------------------------|
|
||||
| **1080p** | 4-6 GB |
|
||||
| **1440p** | 6-8 GB |
|
||||
| **4K** | 8-12 GB |
|
||||
|
||||
```toml
|
||||
# Adjust jobs based on available RAM
|
||||
[transcode]
|
||||
concurrent_jobs = 1 # Conservative for 16GB systems
|
||||
```
|
||||
|
||||
### Codec-Specific Optimization
|
||||
|
||||
#### AV1 (SVT-AV1) - Recommended
|
||||
Best compression efficiency for CPU encoding:
|
||||
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "av1"
|
||||
quality_profile = "balanced"
|
||||
|
||||
[transcode.encoder_args]
|
||||
extra_args = [
|
||||
"-preset", "8", # Good speed/quality balance
|
||||
"-crf", "28", # Quality level
|
||||
"-svtav1-params", "tune=0:enable-overlays=1"
|
||||
]
|
||||
```
|
||||
|
||||
#### HEVC (x265)
|
||||
Good balance of quality and compatibility:
|
||||
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "hevc"
|
||||
quality_profile = "balanced"
|
||||
|
||||
[transcode.encoder_args]
|
||||
extra_args = [
|
||||
"-preset", "medium",
|
||||
"-crf", "26",
|
||||
"-x265-params", "log-level=error"
|
||||
]
|
||||
```
|
||||
|
||||
#### H.264 (x264)
|
||||
Fastest software encoding:
|
||||
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "h264"
|
||||
quality_profile = "speed"
|
||||
|
||||
[transcode.encoder_args]
|
||||
extra_args = [
|
||||
"-preset", "fast",
|
||||
"-crf", "23"
|
||||
]
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Two-Pass Encoding
|
||||
|
||||
For maximum quality (much slower):
|
||||
|
||||
```toml
|
||||
[transcode.encoder_args]
|
||||
# AV1 two-pass
|
||||
extra_args = [
|
||||
"-pass", "1", "-an", "-f", "null", "/dev/null", "&&",
|
||||
"-pass", "2"
|
||||
]
|
||||
```
|
||||
|
||||
### Quality-Based Encoding
|
||||
|
||||
Use different quality for different content:
|
||||
|
||||
```toml
|
||||
# High quality for movies
|
||||
[profiles.movies]
|
||||
quality_profile = "quality"
|
||||
output_codec = "av1"
|
||||
|
||||
# Faster for TV shows
|
||||
[profiles.tv]
|
||||
quality_profile = "speed"
|
||||
output_codec = "hevc"
|
||||
```
|
||||
|
||||
### Grain Synthesis (AV1)
|
||||
|
||||
Preserve film grain efficiently:
|
||||
|
||||
```toml
|
||||
[transcode.encoder_args]
|
||||
extra_args = ["-svtav1-params", "film-grain=50"]
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### High CPU Usage
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Reduce concurrent jobs:**
|
||||
```toml
|
||||
[transcode]
|
||||
concurrent_jobs = 1
|
||||
```
|
||||
|
||||
2. **Lower thread count:**
|
||||
```toml
|
||||
[transcode]
|
||||
threads = 4 # Use fewer threads
|
||||
```
|
||||
|
||||
3. **Use faster presets:**
|
||||
```toml
|
||||
[hardware]
|
||||
cpu_preset = "fast"
|
||||
```
|
||||
|
||||
### Out of Memory Errors
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Reduce concurrent jobs:**
|
||||
```toml
|
||||
[transcode]
|
||||
concurrent_jobs = 1
|
||||
```
|
||||
|
||||
2. **Close other applications** during encoding
|
||||
|
||||
3. **Use H.264** instead of AV1/HEVC:
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "h264"
|
||||
```
|
||||
|
||||
### Slow Encoding Speed
|
||||
|
||||
**Expected encoding speeds** (1080p content):
|
||||
|
||||
| Codec | Preset | Typical Speed |
|
||||
|-------|--------|---------------|
|
||||
| **AV1** | Medium | 0.5-1.5x realtime |
|
||||
| **HEVC** | Medium | 1-3x realtime |
|
||||
| **H.264** | Medium | 3-8x realtime |
|
||||
|
||||
**Solutions for slow speeds:**
|
||||
|
||||
1. **Use faster presets:**
|
||||
```toml
|
||||
[hardware]
|
||||
cpu_preset = "fast"
|
||||
```
|
||||
|
||||
2. **Switch codecs:**
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "h264" # Fastest
|
||||
```
|
||||
|
||||
3. **Verify CPU boost** is working:
|
||||
```bash
|
||||
# Linux
|
||||
cat /proc/cpuinfo | grep MHz
|
||||
|
||||
# macOS
|
||||
sysctl -a | grep freq
|
||||
```
|
||||
|
||||
### Quality Issues
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Lower CRF values** (better quality):
|
||||
```toml
|
||||
[transcode.encoder_args]
|
||||
extra_args = ["-crf", "24"] # Lower = better quality
|
||||
```
|
||||
|
||||
2. **Use slower presets:**
|
||||
```toml
|
||||
[hardware]
|
||||
cpu_preset = "slow"
|
||||
```
|
||||
|
||||
3. **Enable quality features:**
|
||||
```toml
|
||||
# x265 example
|
||||
[transcode.encoder_args]
|
||||
extra_args = ["-x265-params", "aq-mode=3:aq-strength=1.0"]
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### When to Use CPU Encoding
|
||||
|
||||
**Ideal scenarios:**
|
||||
- No compatible GPU available
|
||||
- Maximum quality requirements
|
||||
- Small batch processing
|
||||
- Development/testing
|
||||
|
||||
**Consider GPU instead when:**
|
||||
- Processing large libraries
|
||||
- Speed is priority
|
||||
- Running 24/7 operations
|
||||
- High resolution content (4K+)
|
||||
|
||||
### Quality vs. Speed Trade-offs
|
||||
|
||||
**Maximum quality** (archival):
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "av1"
|
||||
quality_profile = "quality"
|
||||
concurrent_jobs = 1
|
||||
|
||||
[hardware]
|
||||
cpu_preset = "slow"
|
||||
```
|
||||
|
||||
**Balanced performance** (recommended):
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "hevc"
|
||||
quality_profile = "balanced"
|
||||
concurrent_jobs = 2 # Adjust for your CPU
|
||||
|
||||
[hardware]
|
||||
cpu_preset = "medium"
|
||||
```
|
||||
|
||||
**Speed priority** (quick results):
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "h264"
|
||||
quality_profile = "speed"
|
||||
concurrent_jobs = 4 # More jobs, fewer threads each
|
||||
|
||||
[hardware]
|
||||
cpu_preset = "fast"
|
||||
```
|
||||
|
||||
### System Optimization
|
||||
|
||||
**Linux optimizations:**
|
||||
```bash
|
||||
# Set CPU governor to performance
|
||||
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
|
||||
|
||||
# Disable CPU frequency scaling
|
||||
echo 1 | sudo tee /sys/devices/system/cpu/intel_pstate/no_turbo
|
||||
```
|
||||
|
||||
**Windows optimizations:**
|
||||
- Set power plan to "High Performance"
|
||||
- Disable CPU parking in registry
|
||||
- Close unnecessary background apps
|
||||
|
||||
**macOS optimizations:**
|
||||
- Use Activity Monitor to verify CPU usage
|
||||
- Close other intensive applications
|
||||
- Consider thermal throttling on laptops
|
||||
@@ -1,315 +0,0 @@
|
||||
# Intel QSV Setup
|
||||
|
||||
Complete guide to setting up Intel Quick Sync Video (QSV) hardware acceleration.
|
||||
|
||||
# Intel Quick Sync Video (QSV) Setup
|
||||
|
||||
Intel Quick Sync Video provides excellent hardware acceleration with low power consumption. Available on most Intel CPUs with integrated graphics since Sandy Bridge (2011).
|
||||
|
||||
## Supported Hardware
|
||||
|
||||
QSV is available on Intel processors with integrated graphics:
|
||||
|
||||
| Generation | Codecs | Performance |
|
||||
|------------|---------|------------|
|
||||
| **Sandy Bridge (2nd gen)** | H.264 | Basic support |
|
||||
| **Ivy Bridge (3rd gen)** | H.264 | Improved quality |
|
||||
| **Haswell (4th gen)** | H.264 | Better efficiency |
|
||||
| **Broadwell (5th gen)** | H.264, HEVC (decode only) | Low power |
|
||||
| **Skylake (6th gen)** | H.264, HEVC | HEVC encoding support |
|
||||
| **Kaby Lake (7th gen)** | H.264, HEVC | Enhanced quality |
|
||||
| **Coffee Lake (8th-10th gen)** | H.264, HEVC | Improved performance |
|
||||
| **Tiger Lake (11th gen)** | H.264, HEVC, AV1 (decode) | AV1 hardware decode |
|
||||
| **Alder Lake (12th gen)** | H.264, HEVC, AV1 | Full AV1 encode/decode |
|
||||
| **Raptor Lake (13th gen)** | H.264, HEVC, AV1 | Enhanced AV1 performance |
|
||||
|
||||
### Checking Your Hardware
|
||||
|
||||
Verify QSV support:
|
||||
```bash
|
||||
# Check for Intel GPU
|
||||
lspci | grep -i intel
|
||||
|
||||
# Look for iGPU device files
|
||||
ls -la /dev/dri/
|
||||
|
||||
# Check FFmpeg QSV encoders
|
||||
ffmpeg -encoders | grep qsv
|
||||
```
|
||||
|
||||
Expected output:
|
||||
```
|
||||
V....D av1_qsv Intel AV1 encoder (Intel Quick Sync Video acceleration) (codec av1)
|
||||
V....D h264_qsv Intel H.264 encoder (Intel Quick Sync Video acceleration) (codec h264)
|
||||
V....D hevc_qsv Intel HEVC encoder (Intel Quick Sync Video acceleration) (codec hevc)
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
### Docker Setup (Recommended)
|
||||
|
||||
1. **Pass GPU devices to container:**
|
||||
```yaml
|
||||
services:
|
||||
alchemist:
|
||||
image: ghcr.io/bybrooklyn/alchemist:latest
|
||||
devices:
|
||||
- /dev/dri:/dev/dri
|
||||
group_add:
|
||||
- video # or render group
|
||||
```
|
||||
|
||||
2. **Verify access inside container:**
|
||||
```bash
|
||||
docker exec -it alchemist ls -la /dev/dri/
|
||||
```
|
||||
|
||||
Should show devices like:
|
||||
```
|
||||
renderD128
|
||||
card0
|
||||
```
|
||||
|
||||
### Binary Installation
|
||||
|
||||
1. **Install Intel GPU drivers:**
|
||||
|
||||
**Ubuntu/Debian:**
|
||||
```bash
|
||||
# Intel GPU drivers
|
||||
sudo apt install intel-media-va-driver-non-free
|
||||
sudo apt install vainfo
|
||||
|
||||
# Verify VAAPI support
|
||||
vainfo
|
||||
```
|
||||
|
||||
**Fedora/RHEL:**
|
||||
```bash
|
||||
sudo dnf install intel-media-driver
|
||||
sudo dnf install libva-utils
|
||||
vainfo
|
||||
```
|
||||
|
||||
**Arch Linux:**
|
||||
```bash
|
||||
sudo pacman -S intel-media-driver
|
||||
sudo pacman -S libva-utils
|
||||
vainfo
|
||||
```
|
||||
|
||||
2. **Install FFmpeg with QSV:**
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt install ffmpeg
|
||||
|
||||
# Verify QSV support
|
||||
ffmpeg -encoders | grep qsv
|
||||
```
|
||||
|
||||
3. **User permissions:**
|
||||
```bash
|
||||
# Add user to video/render group
|
||||
sudo usermod -a -G video $USER
|
||||
sudo usermod -a -G render $USER
|
||||
# Log out and back in
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### In Alchemist
|
||||
|
||||
1. Navigate to **Settings** → **Hardware**
|
||||
2. Set **Preferred Vendor** to `intel`
|
||||
3. Set **Device Path** to `/dev/dri/renderD128` (or auto-detect)
|
||||
4. Verify detection shows "Intel QSV"
|
||||
|
||||
### Quality Settings
|
||||
|
||||
QSV uses global quality values (lower = better quality):
|
||||
|
||||
| Profile | Quality Value | Use Case |
|
||||
|---------|--------------|----------|
|
||||
| **Quality** | 20 | Best quality, slower |
|
||||
| **Balanced** | 25 | Good balance |
|
||||
| **Speed** | 30 | Faster encoding |
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
```toml
|
||||
[hardware]
|
||||
preferred_vendor = "intel"
|
||||
device_path = "/dev/dri/renderD128"
|
||||
|
||||
[transcode]
|
||||
quality_profile = "balanced"
|
||||
output_codec = "hevc"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "No QSV capable devices found"
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Check iGPU is enabled in BIOS:**
|
||||
- Enable "Intel Graphics" or "Internal Graphics"
|
||||
- Set "Primary Display" to "Auto" or "Intel"
|
||||
|
||||
2. **Verify device nodes:**
|
||||
```bash
|
||||
ls -la /dev/dri/
|
||||
stat /dev/dri/renderD128
|
||||
```
|
||||
|
||||
3. **Check user permissions:**
|
||||
```bash
|
||||
groups $USER
|
||||
# Should include 'video' or 'render'
|
||||
```
|
||||
|
||||
### "VAAPI initialization failed"
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Install VAAPI drivers:**
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt install i965-va-driver intel-media-va-driver-non-free
|
||||
|
||||
# Test VAAPI
|
||||
vainfo --display drm --device /dev/dri/renderD128
|
||||
```
|
||||
|
||||
2. **Check environment variables:**
|
||||
```bash
|
||||
export LIBVA_DRIVER_NAME=iHD # or i965 for older hardware
|
||||
export LIBVA_DRIVERS_PATH=/usr/lib/x86_64-linux-gnu/dri
|
||||
```
|
||||
|
||||
### Poor Performance
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Enable look-ahead:**
|
||||
```toml
|
||||
[transcode.encoder_args]
|
||||
extra_args = ["-look_ahead", "1"]
|
||||
```
|
||||
|
||||
2. **Adjust quality:**
|
||||
```toml
|
||||
[transcode.encoder_args]
|
||||
global_quality = "23" # Lower for better quality
|
||||
```
|
||||
|
||||
3. **Check thermal throttling:**
|
||||
```bash
|
||||
# Monitor CPU/GPU temperatures
|
||||
sensors
|
||||
```
|
||||
|
||||
### Quality Issues
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Use higher quality settings:**
|
||||
```toml
|
||||
[transcode]
|
||||
quality_profile = "quality"
|
||||
```
|
||||
|
||||
2. **Enable B-frames:**
|
||||
```toml
|
||||
[transcode.encoder_args]
|
||||
extra_args = ["-bf", "3", "-b_strategy", "1"]
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Power Efficiency
|
||||
|
||||
Intel QSV excels at power-efficient encoding:
|
||||
|
||||
- **Ultra-low power**: Perfect for NAS/always-on systems
|
||||
- **Thermal management**: Runs cooler than dedicated GPUs
|
||||
- **Concurrent streams**: Most iGPUs support 2-3 simultaneous encodes
|
||||
|
||||
### Memory Usage
|
||||
|
||||
Intel iGPU shares system RAM:
|
||||
|
||||
```toml
|
||||
[transcode]
|
||||
concurrent_jobs = 2 # Safe for most systems
|
||||
threads = 4 # Reasonable CPU usage
|
||||
```
|
||||
|
||||
### Quality Tuning
|
||||
|
||||
For best quality with QSV:
|
||||
|
||||
```toml
|
||||
[transcode.encoder_args]
|
||||
# HEVC-specific optimizations
|
||||
extra_args = [
|
||||
"-global_quality", "22",
|
||||
"-look_ahead", "1",
|
||||
"-bf", "3",
|
||||
"-refs", "3"
|
||||
]
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Hardware Selection
|
||||
|
||||
- **Dedicated GPU slot**: Keep iGPU enabled even with dedicated GPU
|
||||
- **Memory allocation**: Ensure adequate RAM for shared graphics
|
||||
- **BIOS settings**: Enable iGPU for maximum compatibility
|
||||
|
||||
### Operating System
|
||||
|
||||
- **Linux**: Best support, low overhead
|
||||
- **Windows**: Good support with Intel drivers
|
||||
- **Headless operation**: Works without monitor connected
|
||||
|
||||
### Codec Selection
|
||||
|
||||
#### AV1 (12th gen+)
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "av1"
|
||||
quality_profile = "quality" # AV1 benefits from higher quality settings
|
||||
```
|
||||
|
||||
#### HEVC (6th gen+)
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "hevc"
|
||||
quality_profile = "balanced" # Good balance of speed/quality
|
||||
```
|
||||
|
||||
#### H.264 (All generations)
|
||||
```toml
|
||||
[transcode]
|
||||
output_codec = "h264"
|
||||
quality_profile = "speed" # H.264 encodes quickly
|
||||
```
|
||||
|
||||
## Hardware-Specific Notes
|
||||
|
||||
### NUCs and Mini PCs
|
||||
- Excellent for dedicated transcoding appliances
|
||||
- Low power consumption
|
||||
- Passive cooling options available
|
||||
|
||||
### Server CPUs
|
||||
- Xeon processors often lack iGPU
|
||||
- Check specifications before purchase
|
||||
- Consider discrete GPU for servers
|
||||
|
||||
### Laptops
|
||||
- May have power/thermal limitations
|
||||
- Consider reducing concurrent jobs
|
||||
- Monitor temperatures during extended use
|
||||
@@ -1,194 +0,0 @@
|
||||
# NVIDIA (NVENC) Setup
|
||||
|
||||
Complete guide to setting up NVIDIA NVENC hardware acceleration with Alchemist.
|
||||
|
||||
# NVIDIA NVENC Setup
|
||||
|
||||
NVIDIA GPUs provide excellent hardware-accelerated encoding via NVENC. This guide covers setup, troubleshooting, and optimization for NVIDIA graphics cards.
|
||||
|
||||
## Supported Hardware
|
||||
|
||||
NVENC is available on most modern NVIDIA GPUs:
|
||||
|
||||
| Generation | Codecs | Notes |
|
||||
|------------|---------|-------|
|
||||
| **Pascal (GTX 10-series)** | H.264, HEVC | 2 concurrent streams max |
|
||||
| **Turing (GTX 16/RTX 20-series)** | H.264, HEVC | 3 concurrent streams, improved quality |
|
||||
| **Ampere (RTX 30-series)** | H.264, HEVC, AV1 | Best performance, AV1 support |
|
||||
| **Ada Lovelace (RTX 40-series)** | H.264, HEVC, AV1 | Dual AV1 encoders, best efficiency |
|
||||
|
||||
### Checking Your Hardware
|
||||
|
||||
Verify NVENC support:
|
||||
```bash
|
||||
nvidia-smi
|
||||
```
|
||||
|
||||
Check available encoders in FFmpeg:
|
||||
```bash
|
||||
ffmpeg -encoders | grep nvenc
|
||||
```
|
||||
|
||||
Expected output:
|
||||
```
|
||||
V....D av1_nvenc NVIDIA NVENC av1 encoder (codec av1)
|
||||
V....D h264_nvenc NVIDIA NVENC H.264 encoder (codec h264)
|
||||
V....D hevc_nvenc NVIDIA NVENC hevc encoder (codec hevc)
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
### Docker Setup (Recommended)
|
||||
|
||||
1. **Install NVIDIA Container Toolkit** on your host:
|
||||
|
||||
**Ubuntu/Debian:**
|
||||
```bash
|
||||
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
|
||||
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
|
||||
curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
|
||||
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
|
||||
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
|
||||
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
|
||||
sudo systemctl restart docker
|
||||
```
|
||||
|
||||
**RHEL/CentOS/Fedora:**
|
||||
```bash
|
||||
curl -s -L https://nvidia.github.io/nvidia-docker/centos7/nvidia-docker.repo | \
|
||||
sudo tee /etc/yum.repos.d/nvidia-docker.repo
|
||||
sudo yum install -y nvidia-container-toolkit
|
||||
sudo systemctl restart docker
|
||||
```
|
||||
|
||||
2. **Update Docker Compose:**
|
||||
```yaml
|
||||
services:
|
||||
alchemist:
|
||||
image: ghcr.io/bybrooklyn/alchemist:latest
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: 1
|
||||
capabilities: [gpu]
|
||||
```
|
||||
|
||||
3. **Test GPU Access:**
|
||||
```bash
|
||||
docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi
|
||||
```
|
||||
|
||||
### Binary Installation
|
||||
|
||||
For binary installations, ensure:
|
||||
1. **NVIDIA drivers** are installed and up-to-date
|
||||
2. **CUDA toolkit** (optional, for development)
|
||||
3. **FFmpeg with NVENC support**
|
||||
|
||||
#### Installing FFmpeg with NVENC
|
||||
|
||||
**Ubuntu/Debian:**
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install ffmpeg
|
||||
# Verify NVENC support
|
||||
ffmpeg -encoders | grep nvenc
|
||||
```
|
||||
|
||||
**From Source:**
|
||||
```bash
|
||||
git clone https://git.ffmpeg.org/ffmpeg.git
|
||||
cd ffmpeg
|
||||
./configure --enable-cuda --enable-nvenc --enable-nonfree
|
||||
make -j$(nproc)
|
||||
sudo make install
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### In Alchemist
|
||||
|
||||
1. Navigate to **Settings** → **Hardware**
|
||||
2. Set **Preferred Vendor** to `nvidia`
|
||||
3. Leave **Device Path** empty (auto-detect)
|
||||
4. Verify detection in the hardware status section
|
||||
|
||||
### Quality Settings
|
||||
|
||||
NVENC quality is controlled by presets and CQ (Constant Quality) values:
|
||||
|
||||
| Profile | NVENC Preset | CQ Value | Use Case |
|
||||
|---------|-------------|----------|----------|
|
||||
| **Quality** | `p7` | 20-24 | Archival, slow encodes |
|
||||
| **Balanced** | `p4` | 25-28 | General purpose |
|
||||
| **Speed** | `p1` | 30-35 | Fast turnaround |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "No NVENC capable devices found"
|
||||
|
||||
**Causes:**
|
||||
- GPU drivers not installed
|
||||
- Container can't access GPU
|
||||
- Unsupported GPU model
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Check drivers:**
|
||||
```bash
|
||||
nvidia-smi
|
||||
```
|
||||
|
||||
2. **Verify container access:**
|
||||
```bash
|
||||
docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi
|
||||
```
|
||||
|
||||
### "NVENC encoder failed to initialize"
|
||||
|
||||
**Common causes:**
|
||||
- All encode sessions in use
|
||||
- Insufficient GPU memory
|
||||
- Driver version mismatch
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Reduce concurrent jobs:**
|
||||
```toml
|
||||
[transcode]
|
||||
concurrent_jobs = 1
|
||||
```
|
||||
|
||||
2. **Check GPU memory:**
|
||||
```bash
|
||||
nvidia-smi
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Quality Testing**: Always test quality before bulk transcoding
|
||||
2. **Temperature Monitoring**: Keep GPU temperatures under 83°C
|
||||
3. **Driver Updates**: Update drivers regularly for bug fixes
|
||||
4. **Backup Strategy**: Keep originals until quality is verified
|
||||
|
||||
## Codec Recommendations
|
||||
|
||||
### AV1 (RTX 30/40 series)
|
||||
- Best compression
|
||||
- Slower encoding
|
||||
- Future-proof format
|
||||
- Ideal for archival
|
||||
|
||||
### HEVC
|
||||
- Excellent compression
|
||||
- Wide compatibility
|
||||
- Good encoding speed
|
||||
- Recommended for most users
|
||||
|
||||
### H.264
|
||||
- Universal compatibility
|
||||
- Fast encoding
|
||||
- Larger file sizes
|
||||
- Good for compatibility requirements
|
||||
@@ -1,86 +0,0 @@
|
||||
# Alchemist
|
||||
|
||||
Point it at your media library. Walk away. Come back to a smaller, better-encoded collection.
|
||||
|
||||
## Start Here
|
||||
|
||||
- [Get Started](getting-started/installation.md)
|
||||
- [View on GitHub](https://github.com/bybrooklyn/alchemist)
|
||||
|
||||
## What Alchemist does
|
||||
|
||||
Alchemist scans your media library, analyzes every file, and
|
||||
decides whether transcoding it would actually save meaningful
|
||||
space. If the file is already efficiently compressed, it skips
|
||||
it and tells you exactly why in plain English. If it can save
|
||||
space without hurting quality, it encodes it - automatically,
|
||||
using whatever hardware you have.
|
||||
|
||||
Your originals are never touched until the new file passes
|
||||
quality validation. Nothing is deleted until you say so.
|
||||
|
||||
### Hardware acceleration
|
||||
|
||||
NVIDIA NVENC, Intel QSV, AMD VAAPI/AMF, and Apple
|
||||
VideoToolbox detected and used automatically. CPU fallback
|
||||
when no GPU is available - no manual setup required.
|
||||
|
||||
### Intelligent skipping
|
||||
|
||||
Bits-per-pixel analysis, size reduction thresholds, and
|
||||
codec-awareness mean Alchemist only encodes files that will
|
||||
actually get meaningfully smaller. Every skip is explained.
|
||||
|
||||
### Per-library profiles
|
||||
|
||||
Different rules for movies, TV shows, and home videos.
|
||||
Four built-in presets - Space Saver, Balanced, Quality
|
||||
First, Streaming - fully customizable.
|
||||
|
||||
### Single binary
|
||||
|
||||
One file. No services to install, no plugin stacks, no
|
||||
databases to manage separately. Docker image bundles
|
||||
everything including FFmpeg.
|
||||
|
||||
## Who this is for
|
||||
|
||||
Alchemist is built for self-hosters who run Plex, Jellyfin,
|
||||
or Emby and want to reclaim storage without babysitting shell
|
||||
commands. If you have a media library measured in terabytes
|
||||
and you want it to get smaller on its own while you sleep, this
|
||||
is the tool.
|
||||
|
||||
It is not a Tdarr replacement with flow editors and plugins.
|
||||
It is not a commercial service. It is a GPLv3 open source tool
|
||||
that does one thing - and does it without asking you to become
|
||||
an FFmpeg expert.
|
||||
|
||||
## Where to start
|
||||
|
||||
- [Docker install](getting-started/installation.md): The fastest path to a running instance.
|
||||
- [Hardware setup](guides/hardware.md): Get NVIDIA, Intel, AMD, or Apple acceleration working.
|
||||
- [Library profiles](guides/profiles.md): Different rules for different folders.
|
||||
- [Why did it skip my file?](reference/skip-decisions.md): Understand every skip decision Alchemist makes.
|
||||
|
||||
## Hardware at a glance
|
||||
|
||||
| Vendor | Encoders | Notes |
|
||||
|--------|----------|-------|
|
||||
| NVIDIA | AV1, HEVC, H.264 (NVENC) | RTX 30/40 for AV1 |
|
||||
| Intel | AV1, HEVC, H.264 (QSV) | 12th gen+ for AV1 |
|
||||
| AMD | HEVC, H.264 (VAAPI/AMF) | RDNA 2+ for AV1 |
|
||||
| Apple | HEVC, H.264 (VideoToolbox) | M3+ for AV1 |
|
||||
| CPU | AV1 (SVT-AV1), HEVC (x265), H.264 (x264) | Always available |
|
||||
|
||||
## Nightly builds
|
||||
|
||||
Nightly builds are published automatically on every push to
|
||||
`main` after Rust checks pass.
|
||||
|
||||
```bash
|
||||
docker pull ghcr.io/bybrooklyn/alchemist:nightly
|
||||
```
|
||||
|
||||
Stable releases are tagged `vX.Y.Z`. See the
|
||||
[Changelog](reference/changelog.md) for what changed.
|
||||
@@ -1,180 +0,0 @@
|
||||
# API Reference
|
||||
|
||||
Detailed reference for the Alchemist REST API.
|
||||
|
||||
All API endpoints require authentication via Bearer token, except for:
|
||||
- `/api/setup/*` - Setup wizard endpoints
|
||||
- `/api/auth/login` - Login endpoint
|
||||
- `/api/health` - Health check (returns status, version, uptime)
|
||||
- `/api/ready` - Readiness check (returns database status)
|
||||
|
||||
Most browser clients use the session cookie returned by `/api/auth/login`.
|
||||
Bearer auth is still accepted by the backend, but the web UI authenticates with the session cookie automatically.
|
||||
|
||||
## Authentication
|
||||
|
||||
To use the API, you first need to log in to get a token.
|
||||
|
||||
```bash
|
||||
# Login
|
||||
POST /api/auth/login
|
||||
Content-Type: application/json
|
||||
{
|
||||
"username": "admin",
|
||||
"password": "secret"
|
||||
}
|
||||
|
||||
# Response: 200 OK + Set-Cookie: alchemist_session=...
|
||||
```
|
||||
|
||||
## Jobs
|
||||
|
||||
Endpoints for managing transcoding jobs.
|
||||
|
||||
```bash
|
||||
# Get all jobs (canonical endpoint)
|
||||
GET /api/jobs
|
||||
|
||||
# Legacy alias
|
||||
GET /api/jobs/table
|
||||
|
||||
# Get job stats
|
||||
GET /api/stats
|
||||
|
||||
# Cancel job
|
||||
POST /api/jobs/:id/cancel
|
||||
|
||||
# Restart job
|
||||
POST /api/jobs/:id/restart
|
||||
|
||||
# Restart all failed
|
||||
POST /api/jobs/restart-failed
|
||||
|
||||
# Clear completed
|
||||
POST /api/jobs/clear-completed
|
||||
```
|
||||
|
||||
## Statistics
|
||||
|
||||
Endpoints for retrieving performance and space savings data.
|
||||
|
||||
```bash
|
||||
# Aggregated stats (totals)
|
||||
GET /api/stats/aggregated
|
||||
# Response: {total_input_bytes, total_output_bytes, total_savings_bytes,
|
||||
# total_time_seconds, total_jobs, avg_vmaf}
|
||||
|
||||
# Daily stats (last 30 days)
|
||||
GET /api/stats/daily
|
||||
# Response: [{date, jobs_completed, bytes_saved, total_input_bytes,
|
||||
# total_output_bytes}, ...]
|
||||
|
||||
# Detailed per-job stats
|
||||
GET /api/stats/detailed
|
||||
# Response: [{job_id, input_path, input_size_bytes, output_size_bytes,
|
||||
# compression_ratio, encode_time_seconds, encode_speed,
|
||||
# avg_bitrate_kbps, vmaf_score, created_at}, ...]
|
||||
```
|
||||
|
||||
## Engine Control
|
||||
|
||||
Endpoints for controlling the background processing engine.
|
||||
|
||||
```bash
|
||||
# Pause processing
|
||||
POST /api/engine/pause
|
||||
|
||||
# Resume processing
|
||||
POST /api/engine/resume
|
||||
|
||||
# Drain processing (finish active jobs, stop starting new ones)
|
||||
POST /api/engine/drain
|
||||
|
||||
# Cancel drain and resume normal scheduling
|
||||
POST /api/engine/stop-drain
|
||||
|
||||
# Get engine status
|
||||
GET /api/engine/status
|
||||
|
||||
# Inspect engine mode and computed concurrency limits
|
||||
GET /api/engine/mode
|
||||
|
||||
# Set engine mode and optional overrides
|
||||
POST /api/engine/mode
|
||||
Content-Type: application/json
|
||||
{
|
||||
"mode": "balanced",
|
||||
"concurrent_jobs_override": 2,
|
||||
"threads_override": 0
|
||||
}
|
||||
```
|
||||
|
||||
`/api/engine/status` now returns richer runtime state including:
|
||||
- `status`: `running`, `paused`, or `draining`
|
||||
- `manual_paused`
|
||||
- `scheduler_paused`
|
||||
- `draining`
|
||||
- `mode`
|
||||
- `concurrent_limit`
|
||||
- `is_manual_override`
|
||||
|
||||
## Settings
|
||||
|
||||
Endpoints for managing application configuration.
|
||||
|
||||
```bash
|
||||
# Get transcode settings
|
||||
GET /api/settings/transcode
|
||||
|
||||
# Update transcode settings
|
||||
POST /api/settings/transcode
|
||||
Content-Type: application/json
|
||||
{
|
||||
"concurrent_jobs": 2,
|
||||
"size_reduction_threshold": 0.3,
|
||||
"min_bpp_threshold": 0.1,
|
||||
"min_file_size_mb": 50,
|
||||
"output_codec": "av1",
|
||||
"allow_fallback": true,
|
||||
"quality_profile": "balanced",
|
||||
"threads": 0,
|
||||
"hdr_mode": "preserve",
|
||||
"tonemap_algorithm": "hable",
|
||||
"tonemap_peak": 100,
|
||||
"tonemap_desat": 0.2
|
||||
}
|
||||
```
|
||||
|
||||
Additional operational endpoints worth knowing:
|
||||
|
||||
```bash
|
||||
# Runtime hardware details
|
||||
GET /api/system/hardware
|
||||
|
||||
# Hardware probe log
|
||||
GET /api/system/hardware/probe-log
|
||||
|
||||
# Library health overview
|
||||
GET /api/library/health
|
||||
|
||||
# Start a library health scan
|
||||
POST /api/library/health/scan
|
||||
|
||||
# List detected health issues
|
||||
GET /api/library/health/issues
|
||||
```
|
||||
|
||||
## Server-Sent Events
|
||||
|
||||
Real-time updates are provided via a Server-Sent Events (SSE) stream.
|
||||
|
||||
```bash
|
||||
# Real-time event stream
|
||||
GET /api/events?token=<auth_token>
|
||||
|
||||
# Event types:
|
||||
# - JobStateChanged: {job_id, status}
|
||||
# - Progress: {job_id, percentage, time}
|
||||
# - Decision: {job_id, action, reason}
|
||||
# - Log: {job_id, message}
|
||||
```
|
||||
@@ -1,103 +0,0 @@
|
||||
# Architecture
|
||||
|
||||
How Alchemist is structured internally.
|
||||
|
||||
## Pipeline overview
|
||||
|
||||
Every file Alchemist processes goes through this sequence:
|
||||
|
||||
```text
|
||||
Scanner -> jobs table (queued)
|
||||
↓
|
||||
Agent::run_loop() - picks next job, acquires semaphore permit
|
||||
↓
|
||||
FfmpegAnalyzer::analyze() - ffprobe -> MediaMetadata
|
||||
↓
|
||||
BasicPlanner::plan() - should_transcode() -> Skip / Remux / Transcode
|
||||
↓
|
||||
Skip -> decision stored, done
|
||||
Remux -> ffmpeg -c copy (MP4->MKV, lossless)
|
||||
Transcode -> FfmpegExecutor::execute()
|
||||
↓
|
||||
Post-encode: optional VMAF, promote temp file, update stats
|
||||
↓
|
||||
DB updated: completed / failed / skipped
|
||||
```
|
||||
|
||||
## Source layout
|
||||
|
||||
```text
|
||||
src/
|
||||
├── main.rs Boot, CLI args, config reload watcher
|
||||
├── config.rs TOML config structs and validation
|
||||
├── db.rs SQLite - all queries (~2400 lines)
|
||||
├── orchestrator.rs FFmpeg subprocess wrapper
|
||||
├── scheduler.rs Schedule window enforcement
|
||||
├── notifications.rs Discord, Gotify, webhook dispatch
|
||||
├── media/
|
||||
│ ├── pipeline.rs Core interfaces, TranscodePlan structs
|
||||
│ ├── planner.rs Decision engine (BasicPlanner)
|
||||
│ ├── analyzer.rs ffprobe wrapper with 120s timeout
|
||||
│ ├── executor.rs Plan -> FFmpeg execution
|
||||
│ ├── processor.rs Agent - job loop + engine state machine
|
||||
│ ├── scanner.rs Filesystem walker
|
||||
│ ├── health.rs Library Doctor health checker
|
||||
│ └── ffmpeg/ FFmpeg arg builders per encoder type
|
||||
│ ├── mod.rs Main builder
|
||||
│ ├── vaapi.rs Intel/AMD Linux
|
||||
│ ├── qsv.rs Intel QSV (deprecated for Arc)
|
||||
│ ├── nvenc.rs NVIDIA
|
||||
│ ├── amf.rs AMD Windows
|
||||
│ ├── videotoolbox.rs Apple Silicon
|
||||
│ └── cpu.rs SVT-AV1, x265, x264
|
||||
└── server/ HTTP layer (10 modules)
|
||||
├── mod.rs AppState, run_server, route table
|
||||
├── auth.rs Login, logout, sessions (Argon2)
|
||||
├── jobs.rs Job queue API
|
||||
├── scan.rs Library scan endpoints
|
||||
├── settings.rs Config read/write
|
||||
├── stats.rs Aggregate stats and savings
|
||||
├── system.rs Hardware detection, resource monitor
|
||||
├── sse.rs Server-Sent Events stream
|
||||
├── middleware.rs Rate limiting, auth middleware
|
||||
└── wizard.rs First-run setup API
|
||||
```
|
||||
|
||||
## Engine state machine
|
||||
|
||||
The `Agent` in `src/media/processor.rs` controls when jobs run:
|
||||
|
||||
| State | Behavior |
|
||||
|-------|----------|
|
||||
| Running | Normal - jobs start as permits become available |
|
||||
| Paused | No new jobs start; active jobs freeze mid-encode |
|
||||
| Draining | No new jobs start; active jobs finish normally |
|
||||
| Scheduler paused | Same as Paused but triggered by schedule windows |
|
||||
|
||||
Engine always starts paused on boot. Users must explicitly
|
||||
click **Start**.
|
||||
|
||||
## Engine modes
|
||||
|
||||
Engine modes auto-compute the concurrent job limit from
|
||||
CPU count:
|
||||
|
||||
| Mode | Concurrent jobs |
|
||||
|------|----------------|
|
||||
| Background | 1 |
|
||||
| Balanced | floor(cpu_count / 2), min 1, max 4 (default) |
|
||||
| Throughput | floor(cpu_count / 2), min 1, uncapped |
|
||||
|
||||
Users can override the computed limit via Settings -> Runtime.
|
||||
|
||||
## Technology stack
|
||||
|
||||
| Layer | Technology |
|
||||
|-------|------------|
|
||||
| Runtime | Rust 2024 edition, Tokio, MSRV 1.85 |
|
||||
| Web framework | Axum 0.7 |
|
||||
| Database | SQLite via sqlx 0.8, WAL mode |
|
||||
| Frontend | Astro + React + TypeScript + Tailwind CSS |
|
||||
| Build | Bun (frontend), Cargo (Rust) |
|
||||
| Media | FFmpeg (external) + FFprobe |
|
||||
| Packaging | rust-embed (single binary) |
|
||||
@@ -1,138 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
Release history for Alchemist.
|
||||
|
||||
## [0.3.0] - 2026-03-28
|
||||
|
||||
### Rust & Backend
|
||||
- Upgraded from Rust 2021 to 2024, set the MSRV to 1.85, upgraded `sqlx` to `0.8` with `runtime-tokio-rustls`, and upgraded `rand` to `0.9`.
|
||||
- Removed `async-trait`, adopted native `async fn` in traits, and added `trait-variant` so `ExecutionObserver` remained object-safe behind `Arc<dyn ...>`.
|
||||
- Fixed the Apple VideoToolbox probe by using synthetic `lavfi` frames with `format=yuv420p` and `-allow_sw 1`, allowing HEVC and AV1 detection to succeed on Apple Silicon.
|
||||
- Split `server.rs` into `src/server/` submodules for auth, jobs, scan, settings, stats, system, SSE, middleware, wizard, and tests.
|
||||
- Moved `ffprobe` execution to `tokio::process::Command` with a 120-second timeout.
|
||||
- Added poisoned cancellation lock recovery in the orchestrator and truncated oversized FFmpeg stderr lines before logging.
|
||||
- Invalid notification event JSON now warned instead of silently disabling the target, and invalid schedule day JSON now warned instead of being treated as empty.
|
||||
|
||||
### UI & Frontend
|
||||
- Reworked the app shell by removing page `h1` headers, replacing the old header block with a thin engine control strip, and dropping the sidebar icon container for wordmark-only branding.
|
||||
- Flattened engine controls into one horizontal row with the status dot, Start/Pause/Stop actions, a divider, About, and Logout.
|
||||
- Moved the Background, Balanced, and Throughput mode pills into Settings -> Runtime and wired them to the engine mode API.
|
||||
- Rebuilt the setup wizard inside the main app shell with a grayed sidebar, removed the centered card layout, and replaced progress with a 2px solar line at the top of the content area.
|
||||
- Setup wizard errors now surfaced as toast notifications instead of an inline error block below the content.
|
||||
- Redesigned library selection around a flat recommendation list with Add buttons, selected-folder chips, and equal Browse/manual path entry; the preview panel was removed.
|
||||
- Restructured the dashboard around a compact stat row, a savings summary, and a larger Recent Activity panel.
|
||||
- Updated the log viewer to group entries by `job_id` into collapsible job sections while rendering system logs inline.
|
||||
- Normalized job status badges to sentence case without letter spacing, aligned table column headers, and standardized the job detail modal radius and section headers.
|
||||
- Cleaned banned CSS patterns from `ServerDirectoryPicker`, `ToastRegion`, and `SavingsOverview`, and modernized the login page with wordmark-only branding and tighter field styling.
|
||||
- Darkened the global background gradient slightly, reduced scrollbar width to 6px, increased border radius one step across cards and buttons, and gave inputs more contrast against the page.
|
||||
|
||||
### CI/CD
|
||||
- Added a nightly workflow that runs on every push to `main` after Rust checks pass, builds all platforms, publishes `ghcr.io/bybrooklyn/alchemist:nightly`, and replaces the previous nightly pre-release with `{VERSION}-nightly+{short-sha}`.
|
||||
- Extracted a shared reusable `build.yml` workflow so nightly and release builds use the same pipeline.
|
||||
- Simplified `docker.yml` to PR preview builds only, removed the `workflow_run` trigger, and removed the `main` branch trigger from `ci.yml`.
|
||||
- Frontend validation in CI now runs the e2e reliability suite after the frontend check passes.
|
||||
|
||||
### Docs & Tooling
|
||||
- Added `CLAUDE.md` and `GEMINI.md` as agent context files, added `CONTRIBUTING.md` with GPL-3.0 CLA terms, and started `CHANGELOG.md`.
|
||||
- Hardened the `justfile` with safer process cleanup, a stronger `db-reset`, and `--frozen-lockfile` docs installation.
|
||||
|
||||
## [v0.2.10-rc.5] - 2026-03-22
|
||||
|
||||
### Runtime & Queue Control
|
||||
- Engine runtime modes now support `background`, `balanced`, and `throughput`, with manual concurrency overrides and drain/resume controls exposed through the API and dashboard header.
|
||||
- Engine status reporting now includes pause source, drain state, concurrent-limit metadata, and mode visibility for troubleshooting.
|
||||
- Queue management continued to harden with safer active-job controls, clearer failure surfacing, and better per-job operational feedback.
|
||||
|
||||
### Media Processing & Library Health
|
||||
- VAAPI-first Intel handling, remux planning, subtitle sidecars, and library health issue reporting were expanded across the planner, FFmpeg integration, and dashboard.
|
||||
- Hardware detection and probe logging were improved to make CPU/GPU backend selection and diagnostics easier to understand.
|
||||
- Stream rules landed for commentary stripping, audio-language filtering, and keeping only the default audio track when needed.
|
||||
|
||||
### Paths, Setup & Docs
|
||||
- Default config and database paths were normalized around the `alchemist` runtime home, and the repo now ships a `justfile` for common dev, release, Docker, and database workflows.
|
||||
- The docs site moved onto Starlight and now builds locally with a proper content config, localized collection wiring, and a corrected splash-page schema.
|
||||
- Release automation now bumps repo-wide version manifests, supports checkpoint commits before release validation, and isolates web-e2e onto a separate port so a local server on `3000` does not block release verification.
|
||||
|
||||
### CI/CD & Release Tooling
|
||||
- Docker publishing is now gated behind successful validation, and local release verification covers Rust checks/tests, frontend verification, docs build, `actionlint`, and the reliability Playwright suite.
|
||||
- `just update` does not create the release commit, git tag, or push until the full validation gate passes.
|
||||
|
||||
## [v0.2.10-rc.2] - 2026-03-21
|
||||
|
||||
### Stability & Reliability
|
||||
- VMAF quality gating: encodes falling below a configurable minimum score are now rejected rather than silently promoted.
|
||||
- Exponential retry backoff for failed jobs: 5 / 15 / 60 / 360 minute delays based on attempt count prevent tight failure loops.
|
||||
- Orphaned temp file cleanup on startup: interrupted encodes no longer leave `.alchemist.tmp` files on disk indefinitely.
|
||||
- Log table pruning: configurable retention period (default 30 days) prevents unbounded log growth on busy servers.
|
||||
- Auth session cleanup: expired sessions are pruned on startup and every 24 hours.
|
||||
- Resource endpoint caching: `/api/system/resources` is cached for 500ms to prevent redundant OS probes from multiple open browser tabs.
|
||||
|
||||
### New Features
|
||||
- Per-library profiles: each watch folder can have its own transcoding profile, with four built-in presets (Space Saver, Quality First, Balanced, Streaming) usable as starting points.
|
||||
- Storage savings dashboard: the Stats page now shows total space recovered, average reduction percentage, a savings-over-time chart, and per-codec breakdowns.
|
||||
- Library Doctor: scan your library for corrupt or broken files directly from System Settings.
|
||||
- `/api/jobs` added as a canonical alias for `/api/jobs/table`.
|
||||
|
||||
### Beginner Experience
|
||||
- Plain-English skip reasons: skipped jobs now show a human-readable explanation with technical detail available in an expandable section.
|
||||
- Auto-redirect to the setup wizard for first-time users with no watch directories configured.
|
||||
- Setup wizard field descriptions: CRF, BPP, concurrent jobs, and CPU preset now include plain-English explanations inline.
|
||||
- Telemetry is now opt-in by default, with a detailed explanation of exactly what is collected.
|
||||
|
||||
### Job Management
|
||||
- Skipped tab: dedicated tab in the Job Manager for skipped jobs.
|
||||
- Archived tab: cleared completed jobs are now visible in an Archived tab rather than disappearing permanently.
|
||||
- Sort controls: the job list can now be sorted by last updated, date added, file name, or file size.
|
||||
|
||||
### UI & Design
|
||||
- Font updated from Space Grotesk to DM Sans.
|
||||
- Sidebar active state redesigned: a left accent bar replaces the filled background.
|
||||
- Border radius tightened throughout with a more consistent scale across cards, buttons, and badges.
|
||||
- Setup wizard refactored into composable step components.
|
||||
|
||||
### Infrastructure
|
||||
- CI/CD workflows fully rewritten: Rust caching, TypeScript typechecking, and a frontend build shared across all platforms.
|
||||
- Multi-arch Docker images are now published for `linux/amd64` and `linux/arm64`.
|
||||
- Release binaries now ship as `.tar.gz` archives with SHA256 checksums; AppImage and `.app` bundles were removed.
|
||||
- Dockerfile now uses the stable Rust image with pinned FFmpeg checksums.
|
||||
- E2E test coverage added for all new features.
|
||||
|
||||
## [v0.2.10-rc.1] - 2026-03-07
|
||||
- Job lifecycle safety hardening: queued vs active cancel handling, active-job delete/restart blocking, batch-action conflict reporting, and stricter status/stat persistence.
|
||||
- Output handling now supports mirrored `output_root` destinations plus temp-file promotion so replace mode preserves the last good artifact until encode, size, and quality gates pass.
|
||||
- Scheduler, setup, and watch-folder parity updates shipped together: immediate schedule reevaluation, Intel Arc H.264 detection fix, H.264 setup option, canonicalized watch folders, and recursive watch configuration in the UI.
|
||||
- Jobs and settings UX now expose per-job priority controls, output-root file settings, active-job-safe actions, and the Astro router deprecation cleanup.
|
||||
- CI/CD rewrite for `0.2.10-rc.1`: cached Rust checks, frontend typecheck/build validation, multi-arch Docker publishing, and unified prerelease metadata handling across workflows.
|
||||
- Release packaging cleanup: Linux and macOS now ship plain `.tar.gz` binaries, Windows ships `.exe`, and every release asset includes a SHA256 checksum file.
|
||||
|
||||
## [v0.2.9] - 2026-03-06
|
||||
- Runtime reliability pass: watcher/scanner hardening, resilient event consumers, config reload improvements, and live hardware refresh.
|
||||
- Admin UX refresh across dashboard, settings, setup, logs, jobs, charts, and system status with stronger error handling and feedback.
|
||||
- Frontend workflow standardized on Bun, Playwright reliability coverage added under `web-e2e`, and deploy/docs/container updates shipped together.
|
||||
|
||||
## [v0.2.8] - 2026-01-12
|
||||
- Setup wizard auth fixes, scheduler time validation, and watcher reliability improvements.
|
||||
- DB stability pass (WAL, FK enforcement, indexes, session cleanup, legacy watch_dirs compatibility).
|
||||
- Build pipeline updates (rustls for reqwest, cross-platform build script, WiX workflow fix).
|
||||
- Documentation and design philosophy updates.
|
||||
- More themes!!
|
||||
|
||||
## [v0.2.5] - 2026-01-11
|
||||
|
||||
### Fixes
|
||||
- **Dashboard Crash**: Fixed a critical bug where the dashboard would render as a blank screen if GPU utilization was `null`. Added strict null checks before `toFixed()` calls in `ResourceMonitor.tsx`.
|
||||
- **Animation Glitch**: Resolved an issue where the "Engine Status" button would fly in from the top-left corner on page navigation. Implemented unique `layoutId` generation using `useId()` to maintain the morph animation while preventing cross-page artifacts.
|
||||
- **Migration Checksum**: Fixed a startup error caused by a modified migration file. Reverted the original migration to restore checksum integrity and created a new migration for the version bump.
|
||||
|
||||
### Improvements
|
||||
- **Resource Monitor Layout**: Repositioned the GPU Usage section to appear between "Active Jobs" and "Uptime" for better logical flow.
|
||||
- **Animation Timing**: Adjusted staggered animation delays in the Resource Monitor to match the new layout order.
|
||||
|
||||
### Documentation
|
||||
- **Codebase Overview**: Added `codebase_overview.md` explaining the monolith architecture (Rust + API + Frontend) and directory structure.
|
||||
- **Migration Policy**: Updated `MIGRATIONS.md` to explicitly forbid modifying existing migration files to prevent checksum errors.
|
||||
- **Walkthrough**: Updated `walkthrough.md` with detailed debugging logs and verification steps for all recent changes.
|
||||
|
||||
### Infrastructure
|
||||
- **Version Bump**: Updated project version to `0.2.5` in `Cargo.toml`, `web/package.json`, and `VERSION`.
|
||||
- **Database**: Established `0.2.5` as the new minimum compatible version schema baseline.
|
||||
@@ -1,55 +0,0 @@
|
||||
# Video Codecs
|
||||
|
||||
Understanding the different video formats supported by Alchemist.
|
||||
|
||||
This page explains the different video formats (codecs) Alchemist uses to shrink your files. Choosing the right one depends on whether you care more about saving space or making sure your videos play on older devices.
|
||||
|
||||
## What is a Codec?
|
||||
|
||||
A "codec" is the technology used to compress video so it doesn't take up massive amounts of storage. Alchemist supports three main codecs, each with its own pros and cons.
|
||||
|
||||
## AV1 (The Modern King)
|
||||
|
||||
AV1 is the newest and most efficient video format. It can make files much smaller than older formats while keeping the picture looking great.
|
||||
|
||||
- **Pros**: Smallest file sizes, best quality per megabyte, free to use.
|
||||
- **Cons**: Requires very new hardware to play smoothly (like 40-series NVIDIA cards or Apple M3 chips). Older devices will struggle and use a lot of battery.
|
||||
- **Best for**: Future-proofing your library and saving the most space.
|
||||
|
||||
## HEVC / H.265 (The Current Standard)
|
||||
|
||||
HEVC is the format used by almost all 4K Blu-rays and streaming services today. It's much more efficient than the older H.264.
|
||||
|
||||
- **Pros**: Excellent balance of small size and high quality. Works on most modern TVs, phones, and tablets.
|
||||
- **Cons**: Some older computers or cheap streaming sticks might not play it.
|
||||
- **Best for**: A great balance of space savings and compatibility.
|
||||
|
||||
## H.264 / AVC (The Old Reliable)
|
||||
|
||||
H.264 is the most compatible video format in the world. Almost anything with a screen can play it.
|
||||
|
||||
- **Pros**: Plays everywhere. Even a 15-year-old computer can handle it.
|
||||
- **Cons**: Files are much larger than AV1 or HEVC for the same quality.
|
||||
- **Best for**: If you need your videos to play on *every* device you own, no matter how old.
|
||||
|
||||
---
|
||||
|
||||
## Comparison Table
|
||||
|
||||
| Feature | H.264 | HEVC | AV1 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **File Size** | Large | Medium | Smallest |
|
||||
| **Quality** | Good | Great | Best |
|
||||
| **Compatibility** | Universal | Very Good | Growing |
|
||||
| **Encoding Speed** | Fastest | Fast | Slower |
|
||||
|
||||
---
|
||||
|
||||
## What is BPP (Bits Per Pixel)?
|
||||
|
||||
You'll see "BPP" mentioned in Alchemist. It's a simple way to measure how "squished" a video is.
|
||||
- **High BPP (0.15+)**: Very high quality, but larger file size.
|
||||
- **Medium BPP (0.10)**: Great balance, looks like a high-quality stream.
|
||||
- **Low BPP (0.05-)**: Might start looking "blocky" or blurry.
|
||||
|
||||
Alchemist uses BPP to make sure it doesn't try to shrink a video that is already as small as it can be without losing quality.
|
||||
@@ -1,110 +0,0 @@
|
||||
# Configuration Reference
|
||||
|
||||
Detailed reference for Alchemist configuration settings.
|
||||
|
||||
This page explains all the settings available in Alchemist. You can change these to control how Alchemist handles your video files and how it uses your computer's hardware.
|
||||
|
||||
Alchemist uses a TOML configuration file, usually `config.toml`. On Linux and macOS the default path is `~/.config/alchemist/config.toml` unless you override it with `ALCHEMIST_CONFIG_PATH`.
|
||||
|
||||
## Transcoding Settings (`transcode`)
|
||||
|
||||
Settings that control the actual video conversion process.
|
||||
|
||||
| Field | Type | Default | Description | Example |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| `size_reduction_threshold` | float | `0.3` | The minimum expected size reduction to proceed with a transcode. | `0.2` (20%) |
|
||||
| `min_bpp_threshold` | float | `0.1` | The minimum bits-per-pixel (BPP) for a source to be considered "good quality". | `0.08` |
|
||||
| `min_file_size_mb` | integer | `50` | Smallest file size Alchemist will bother to process. | `100` |
|
||||
| `concurrent_jobs` | integer | `1` | How many transcodes to run at once. | `2` |
|
||||
| `threads` | integer | `0` | CPU threads per job. `0` means automatic. | `4` |
|
||||
| `quality_profile` | string | `Balanced` | Speed vs. Quality tradeoff. | `Quality`, `Balanced`, `Speed` |
|
||||
| `output_codec` | string | `av1` | The target video format. | `av1`, `hevc`, `h264` |
|
||||
| `allow_fallback` | boolean | `true` | If hardware encoding fails, fall back to software. | `false` |
|
||||
| `hdr_mode` | string | `preserve` | How to handle HDR video. | `preserve`, `tonemap` |
|
||||
| `tonemap_algorithm` | string | `hable` | Algorithm for HDR to SDR conversion. | `mobius`, `reinhard`, `clip` |
|
||||
| `tonemap_peak` | float | `100.0` | Target peak luminance for tonemapping. | `150.0` |
|
||||
| `tonemap_desat` | float | `0.2` | Desaturation factor for tonemapping. | `0.1` |
|
||||
| `subtitle_mode` | string | `copy` | How to handle subtitles. | `copy`, `burn`, `none`, `extract` |
|
||||
| `vmaf_min_score` | float | (Optional) | Minimum VMAF score to accept a transcode. | `93.0` |
|
||||
|
||||
### Stream Rules (`transcode.stream_rules`)
|
||||
|
||||
Rules for pruning or keeping audio tracks before the output is written.
|
||||
|
||||
| Field | Type | Default | Description | Example |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| `strip_audio_by_title` | list | `[]` | Remove audio tracks whose title contains one of these strings. | `["commentary", "director"]` |
|
||||
| `keep_audio_languages` | list | `[]` | Keep only audio tracks whose language tag matches these ISO 639-2 codes. | `["eng", "jpn"]` |
|
||||
| `keep_only_default_audio` | boolean | `false` | Keep only the default audio track unless language rules override it. | `true` |
|
||||
|
||||
## Hardware Settings (`hardware`)
|
||||
|
||||
Settings for graphics cards and CPU encoding.
|
||||
|
||||
| Field | Type | Default | Description | Example |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| `preferred_vendor` | string | (Auto) | Preferred hardware backend if you want to pin one. | `nvidia`, `intel`, `amd`, `apple`, `cpu` |
|
||||
| `device_path` | string | (Optional) | Path to the GPU device file. | `/dev/dri/renderD128` |
|
||||
| `allow_cpu_fallback` | boolean | `true` | Fall back to CPU if no GPU is found. | `false` |
|
||||
| `cpu_preset` | string | `medium` | Software encoding speed/quality preset. | `slow`, `fast`, `faster` |
|
||||
| `allow_cpu_encoding` | boolean | `true` | Whether to allow CPU encoding at all. | `false` |
|
||||
|
||||
## Scanner Settings (`scanner`)
|
||||
|
||||
Settings for finding and watching your video files.
|
||||
|
||||
| Field | Type | Default | Description | Example |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| `directories` | list | `[]` | List of folders to scan for videos. | `["/media/movies", "/media/tv"]` |
|
||||
| `watch_enabled` | boolean | `false` | Watch configured library directories in real-time. | `true` |
|
||||
| `extra_watch_dirs` | list | `[]` | Additional folders to watch with options. | `[{ "path": "/media/downloads", "is_recursive": true }]` |
|
||||
|
||||
## Notification Settings (`notifications`)
|
||||
|
||||
Settings for keeping you informed.
|
||||
|
||||
| Field | Type | Default | Description | Example |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| `enabled` | boolean | `false` | Enable or disable all notifications. | `true` |
|
||||
| `targets` | list | `[]` | Notification destinations (Discord, etc.). | See [Notifications Guide](../guides/notifications.md) |
|
||||
|
||||
## File Settings (`files`)
|
||||
|
||||
Settings for how files are saved.
|
||||
|
||||
| Field | Type | Default | Description | Example |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| `delete_source` | boolean | `false` | Delete the original file after success. | `true` |
|
||||
| `output_extension` | string | `"mkv"` | The file extension for the output file. | `"mp4"` |
|
||||
| `output_suffix` | string | `"-alchemist"` | Suffix to add to the new file name. | `"-small"` |
|
||||
| `replace_strategy` | string | `"keep"` | What to do if the file already exists. | `"replace"`, `"skip"` |
|
||||
| `output_root` | string | (Optional) | A different folder to save all new files in. | `"/media/encoded"` |
|
||||
|
||||
## Schedule Settings (`schedule`)
|
||||
|
||||
Settings for when Alchemist is allowed to work.
|
||||
|
||||
| Field | Type | Default | Description | Example |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| `windows` | list | `[]` | Time windows when Alchemist can run. | `[{ "start_time": "22:00", "end_time": "06:00", "days_of_week": [0,1,2,3,4,5,6] }]` |
|
||||
|
||||
## Quality Settings (`quality`)
|
||||
|
||||
Settings for measuring and ensuring video quality.
|
||||
|
||||
| Field | Type | Default | Description | Example |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| `enable_vmaf` | boolean | `false` | Run VMAF quality checks after transcoding. | `true` |
|
||||
| `min_vmaf_score` | float | `90.0` | Acceptable VMAF score (0-100). | `95.0` |
|
||||
| `revert_on_low_quality` | boolean | `true` | Delete the transcode if it's bad quality. | `false` |
|
||||
|
||||
## System Settings (`system`)
|
||||
|
||||
General application settings.
|
||||
|
||||
| Field | Type | Default | Description | Example |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| `monitoring_poll_interval` | float | `2.0` | How often to refresh system stats (sec). | `5.0` |
|
||||
| `enable_telemetry` | boolean | `false` | Send anonymous usage data to help us. | `true` |
|
||||
| `log_retention_days` | integer | `30` | How long to keep log files on disk. | `7` |
|
||||
| `engine_mode` | string | `balanced` | Runtime engine mode used by the dashboard/API controls. | `background`, `balanced`, `throughput` |
|
||||
@@ -1,95 +0,0 @@
|
||||
# Database Schema
|
||||
|
||||
Internal database structure and migration policy for Alchemist.
|
||||
|
||||
Alchemist uses SQLite for persistence. The database file is located at `data/alchemist.db`.
|
||||
|
||||
## Tables
|
||||
|
||||
The database is composed of several tables to track jobs, statistics, and user sessions.
|
||||
|
||||
### `jobs`
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `id` | INTEGER | Primary key |
|
||||
| `input_path` | TEXT | Source file path (unique) |
|
||||
| `output_path` | TEXT | Destination file path |
|
||||
| `status` | TEXT | Job state (queued/encoding/completed/failed/etc) |
|
||||
| `mtime_hash` | TEXT | File modification time hash |
|
||||
| `priority` | INTEGER | Job priority (higher = first) |
|
||||
| `progress` | REAL | Encoding progress 0-100 |
|
||||
| `attempt_count` | INTEGER | Retry count |
|
||||
| `created_at` | DATETIME | Job creation time |
|
||||
| `updated_at` | DATETIME | Last status update |
|
||||
|
||||
### `encode_stats`
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `id` | INTEGER | Primary key |
|
||||
| `job_id` | INTEGER | Foreign key to jobs |
|
||||
| `input_size_bytes` | INTEGER | Original file size |
|
||||
| `output_size_bytes` | INTEGER | Encoded file size |
|
||||
| `compression_ratio` | REAL | input/output ratio |
|
||||
| `encode_time_seconds` | REAL | Total encoding time |
|
||||
| `encode_speed` | REAL | Frames per second |
|
||||
| `avg_bitrate_kbps` | REAL | Output bitrate |
|
||||
| `vmaf_score` | REAL | Quality score (0-100) |
|
||||
| `created_at` | DATETIME | Completion time |
|
||||
|
||||
### `decisions`
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `id` | INTEGER | Primary key |
|
||||
| `job_id` | INTEGER | Foreign key to jobs |
|
||||
| `action` | TEXT | Action taken (encode/skip/revert) |
|
||||
| `reason` | TEXT | Human-readable explanation |
|
||||
| `created_at` | DATETIME | Decision time |
|
||||
|
||||
### `users`
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `id` | INTEGER | Primary key |
|
||||
| `username` | TEXT | Unique username |
|
||||
| `password_hash` | TEXT | Argon2 password hash |
|
||||
| `created_at` | DATETIME | Account creation time |
|
||||
|
||||
### `sessions`
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `id` | INTEGER | Primary key |
|
||||
| `user_id` | INTEGER | Foreign key to users |
|
||||
| `token` | TEXT | Session token (unique) |
|
||||
| `created_at` | DATETIME | Session start |
|
||||
| `expires_at` | DATETIME | Session expiration |
|
||||
|
||||
## Database Migration Policy
|
||||
|
||||
> **Baseline Version: 0.2.5**
|
||||
|
||||
All database migrations maintain **backwards compatibility** with the v0.2.5 schema. This means newer app versions will work with older database files, and no data is lost during upgrades.
|
||||
|
||||
### Migration Rules
|
||||
|
||||
To ensure stability, we follow strict rules for modifying the database schema:
|
||||
|
||||
#### Allowed Operations
|
||||
- Add new tables with `CREATE TABLE IF NOT EXISTS`
|
||||
- Add new columns with `NULL` or `DEFAULT` values
|
||||
- Add new indexes with `CREATE INDEX IF NOT EXISTS`
|
||||
- Insert new configuration rows
|
||||
|
||||
#### Forbidden Operations
|
||||
- Never remove columns
|
||||
- Never rename columns
|
||||
- Never change column types
|
||||
- Never remove tables
|
||||
- Never add `NOT NULL` columns without defaults
|
||||
|
||||
### Schema Version Tracking
|
||||
|
||||
The `schema_info` table tracks compatibility:
|
||||
|
||||
```sql
|
||||
SELECT value FROM schema_info WHERE key = 'min_compatible_version';
|
||||
-- Returns: "0.2.5"
|
||||
```
|
||||
@@ -1,65 +0,0 @@
|
||||
# Engine Modes
|
||||
|
||||
Background, Balanced, and Throughput - what they mean and when to use each.
|
||||
|
||||
Engine modes control how aggressively Alchemist uses your
|
||||
system's resources. The mode determines the **concurrent job
|
||||
limit** - how many files can be encoded at the same time.
|
||||
|
||||
## Modes
|
||||
|
||||
### Background
|
||||
|
||||
**1 concurrent job, always.**
|
||||
|
||||
Use this when the server is in active use - gaming, Plex
|
||||
streaming, browsing - and you want Alchemist to make progress
|
||||
without noticably impacting anything else.
|
||||
|
||||
### Balanced (default)
|
||||
|
||||
**floor(cpu_count / 2), minimum 1, maximum 4.**
|
||||
|
||||
The default. On a 4-core machine this is 2 jobs. On an 8-core
|
||||
machine this is 4 jobs. Good for most setups where the server
|
||||
is shared with other workloads.
|
||||
|
||||
### Throughput
|
||||
|
||||
**floor(cpu_count / 2), minimum 1, no cap.**
|
||||
|
||||
Same formula as Balanced but without the maximum of 4. On a
|
||||
32-core machine this could mean 16 concurrent jobs. Use this
|
||||
when you want to clear a large backlog as fast as possible and
|
||||
the server is dedicated to transcoding.
|
||||
|
||||
## Manual override
|
||||
|
||||
You can override the computed limit from Settings -> Runtime.
|
||||
The override takes effect immediately without restarting.
|
||||
The "manual" label appears in the engine status display when
|
||||
an override is active. Switching modes clears the override
|
||||
and returns to auto-computed limits.
|
||||
|
||||
## Engine states vs. modes
|
||||
|
||||
Modes are separate from engine states:
|
||||
|
||||
- **Mode** determines how many jobs run concurrently
|
||||
- **State** determines whether jobs run at all
|
||||
|
||||
You can be in Throughput mode while the engine is Paused -
|
||||
no jobs will run. When you Resume, jobs will run at the
|
||||
Throughput concurrent limit.
|
||||
|
||||
| State | Behavior |
|
||||
|-------|----------|
|
||||
| Running | Jobs start normally up to the mode's limit |
|
||||
| Paused | No jobs start; active jobs freeze |
|
||||
| Draining | Active jobs finish; no new jobs start |
|
||||
| Scheduler paused | Paused by a schedule window |
|
||||
|
||||
## Changing modes
|
||||
|
||||
Modes are set in **Settings -> Runtime**. The change takes
|
||||
effect immediately - in-progress jobs are not cancelled.
|
||||
@@ -1,40 +0,0 @@
|
||||
# Environment Variables
|
||||
|
||||
All environment variables Alchemist reads at startup.
|
||||
|
||||
Alchemist reads these environment variables at startup.
|
||||
All are optional - sensible defaults apply when not set.
|
||||
|
||||
## Path configuration
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `ALCHEMIST_CONFIG_PATH` | `~/.config/alchemist/config.toml` | Path to the TOML config file |
|
||||
| `ALCHEMIST_CONFIG` | (alias) | Alias for `ALCHEMIST_CONFIG_PATH` |
|
||||
| `ALCHEMIST_DB_PATH` | `~/.config/alchemist/alchemist.db` | Path to the SQLite database |
|
||||
| `ALCHEMIST_DATA_DIR` | (none) | Sets the data directory; `alchemist.db` is placed here |
|
||||
| `ALCHEMIST_CONFIG_MUTABLE` | `true` | Set to `false` to block all runtime config writes |
|
||||
|
||||
Default paths follow XDG on Linux and macOS
|
||||
(`$XDG_CONFIG_HOME/alchemist/` or `~/.config/alchemist/`)
|
||||
and `%APPDATA%\\Alchemist\\` on Windows.
|
||||
|
||||
## Logging
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `RUST_LOG` | `info` | Log level filter. Examples: `info`, `debug`, `alchemist=trace,info` |
|
||||
|
||||
## Docker-specific notes
|
||||
|
||||
In Docker, always set both `ALCHEMIST_CONFIG_PATH` and
|
||||
`ALCHEMIST_DB_PATH` explicitly to paths inside your mounted
|
||||
volumes. If you don't, Alchemist will write config and
|
||||
database files inside the container, which are lost when
|
||||
the container is removed.
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- ALCHEMIST_CONFIG_PATH=/app/config/config.toml
|
||||
- ALCHEMIST_DB_PATH=/app/data/alchemist.db
|
||||
```
|
||||
@@ -1,60 +0,0 @@
|
||||
# FAQ
|
||||
|
||||
Frequently asked questions about Alchemist.
|
||||
|
||||
This page answers the most common questions people have about Alchemist. Whether you're wondering if it's free or how it handles your 4K movies, you'll find the answers here in plain English.
|
||||
|
||||
## General Questions
|
||||
|
||||
### 1. What exactly does Alchemist do?
|
||||
Think of Alchemist as a "garbage compactor" for your video files. It takes large, older video files and converts them into modern formats (like HEVC or AV1) that take up much less space while keeping the same picture quality.
|
||||
|
||||
### 2. Is Alchemist free?
|
||||
Yes! Alchemist is completely free and open-source. It is released under the GPLv3 license, which means the code is public and belongs to the community.
|
||||
|
||||
### 3. Will Alchemist ruin my video quality?
|
||||
No. Alchemist is designed with "Intelligent Analysis." Before it even starts, it checks if the video is already "small enough." If it thinks a transcode would make the video look bad (what we call "quality murder"), it will skip that file automatically.
|
||||
|
||||
### 4. How much space will I actually save?
|
||||
On average, users see between 30% and 70% savings. For example, a 10GB movie could shrink to 4GB or 5GB without any noticeable change in how it looks on your TV.
|
||||
|
||||
### 5. Does it work on Windows, Mac, and Linux?
|
||||
Yes. Since Alchemist runs inside Docker, it works on almost any computer. We recommend Linux for the best performance with graphics cards, but it works great on Windows and Mac too.
|
||||
|
||||
### 6. Do I need a powerful graphics card?
|
||||
You don't *need* one, but it helps a lot. A graphics card (GPU) can shrink a movie in 20 minutes, while a standard processor (CPU) might take 5 hours. Alchemist works with NVIDIA, Intel, AMD, and Apple Silicon.
|
||||
|
||||
### 7. What is the "Library Doctor"?
|
||||
The Library Doctor is a feature that scans your existing movies to see if any of them are "broken" or corrupt. If it finds a file that won't play correctly, it can alert you or try to fix it.
|
||||
|
||||
### 8. Can I limit when Alchemist runs?
|
||||
Yes. You can set a "Schedule" so Alchemist only works at night or when you aren't using your computer for gaming or work.
|
||||
|
||||
### 9. What happens to my original files?
|
||||
By default, Alchemist keeps your original file and creates a new one with "-alchemist" in the name. You can change the settings to automatically delete the original file once the new one is verified to be good.
|
||||
|
||||
### 10. Does Alchemist support 4K and HDR?
|
||||
Yes. Alchemist can handle 4K videos and preserves HDR (High Dynamic Range) metadata so your colors stay vibrant and bright on compatible TVs.
|
||||
|
||||
## Advanced Questions
|
||||
|
||||
### 11. What is "BPP" and why should I care?
|
||||
BPP stands for "Bits Per Pixel." It's a math formula Alchemist uses to measure how much data is being used for every pixel of the video. It's the most reliable way to tell if a video is "high quality" or "highly compressed."
|
||||
|
||||
### 12. Can I use more than one graphics card?
|
||||
Currently, Alchemist uses one primary graphics card for transcoding. You can select which one to use in the settings if you have multiple cards.
|
||||
|
||||
### 13. What is VMAF and should I enable it?
|
||||
VMAF is a high-end tool developed by Netflix to "score" how a video looks compared to the original. It's very accurate but very slow. Only enable it if you are a "quality enthusiast" and don't mind transcodes taking much longer.
|
||||
|
||||
### 14. Can Alchemist handle subtitles?
|
||||
Yes. You can choose to copy all subtitles to the new file, "burn" them into the video (so they are always visible), or ignore them entirely.
|
||||
|
||||
### 15. How do I update Alchemist?
|
||||
If you are using Docker Compose, just run `docker compose pull` and then `docker compose up -d`. Your settings and history will be preserved.
|
||||
|
||||
### 16. What if my hardware isn't supported?
|
||||
Alchemist will automatically "fall back" to using your CPU (Software Encoding). It will still work and produce great quality, it will just be much slower and make your computer fans spin fast!
|
||||
|
||||
### 17. Can I use Alchemist with Plex, Jellyfin, or Emby?
|
||||
Absolutely. Alchemist is designed to work alongside your favorite media server. Just point Alchemist at your media folders, and it will update the files in place.
|
||||
@@ -1,59 +0,0 @@
|
||||
# Hardware Vendors
|
||||
|
||||
Detailed support information for all supported hardware vendors.
|
||||
|
||||
This page is a technical breakdown of which video formats each brand of graphics card supports. It helps you understand exactly what your NVIDIA, Intel, AMD, or Apple hardware can do.
|
||||
|
||||
Alchemist supports hardware-accelerated transcoding across all major GPU vendors. Below is a detailed list of what each vendor can handle.
|
||||
|
||||
## NVIDIA (NVENC)
|
||||
|
||||
NVIDIA cards are the "gold standard" for home transcoding. They are fast and produce very high-quality files.
|
||||
|
||||
| Feature | Supported? | Notes |
|
||||
| :--- | :--- | :--- |
|
||||
| **H.264** | Yes | Works on almost all NVIDIA cards from the last 10 years. |
|
||||
| **HEVC (H.265)** | Yes | Supported on "Maxwell" (900-series) and newer. |
|
||||
| **AV1** | Yes | Requires the latest 40-series cards or newer. |
|
||||
| **10-bit Color** | Yes | Great for high-quality HDR movies. |
|
||||
|
||||
## Intel (QSV)
|
||||
|
||||
Intel's "QuickSync" technology is built into most of their processors. It's incredibly power-efficient.
|
||||
|
||||
| Feature | Supported? | Notes |
|
||||
| :--- | :--- | :--- |
|
||||
| **H.264** | Yes | Supported on almost all Intel chips. |
|
||||
| **HEVC (H.265)** | Yes | Requires 6th Gen "Skylake" or newer. |
|
||||
| **AV1** | Yes | Requires 11th Gen "Tiger Lake" or newer. |
|
||||
| **10-bit Color** | Yes | Requires 7th Gen "Kaby Lake" or newer. |
|
||||
|
||||
## AMD (VAAPI / AMF)
|
||||
|
||||
AMD cards work great on Linux and Windows. They are a solid choice for high-speed transcoding.
|
||||
|
||||
| Feature | Supported? | Notes |
|
||||
| :--- | :--- | :--- |
|
||||
| **H.264** | Yes | Supported on almost all modern AMD cards. |
|
||||
| **HEVC (H.265)** | Yes | Requires "Polaris" (RX 400 series) or newer. |
|
||||
| **AV1** | Yes | Requires "RDNA 2" (RX 6000 series) or newer. |
|
||||
| **10-bit Color** | Yes | Requires "Vega" or newer. |
|
||||
|
||||
## Apple (VideoToolbox)
|
||||
|
||||
If you are using a Mac, Alchemist can use the specialized "Media Engine" built into Apple Silicon.
|
||||
|
||||
| Feature | Supported? | Notes |
|
||||
| :--- | :--- | :--- |
|
||||
| **H.264** | Yes | Works on all modern Macs. |
|
||||
| **HEVC (H.265)** | Yes | Requires a Mac with a T2 chip or Apple Silicon (M1/M2/M3). |
|
||||
| **AV1** | Yes | Requires Apple Silicon M3 or newer. |
|
||||
| **10-bit Color** | Yes | Works best on Apple Silicon Macs. |
|
||||
|
||||
## CPU (Software Encoding)
|
||||
|
||||
If you don't have a supported graphics card, Alchemist uses your computer's main processor.
|
||||
|
||||
- **Compatibility:** Works on 100% of computers.
|
||||
- **Quality:** Often the best quality possible, but very, very slow.
|
||||
- **AV1 Support:** Supported on all CPUs via the `libsvtav1` engine.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,93 +0,0 @@
|
||||
# Skip Decisions
|
||||
|
||||
Why Alchemist skipped a file and what each skip reason means.
|
||||
|
||||
When Alchemist skips a file it always records a machine-readable
|
||||
reason string. In the web interface this appears as a
|
||||
plain-English explanation in the job detail panel. This page
|
||||
documents every possible skip reason and what to do about it.
|
||||
|
||||
## Skip reasons
|
||||
|
||||
### `already_target_codec`
|
||||
|
||||
The file is already encoded in the target codec (e.g. AV1)
|
||||
and already in 10-bit color depth. Re-encoding it would not
|
||||
save meaningful space and could reduce quality.
|
||||
|
||||
**What to do:** Nothing. This is the correct outcome.
|
||||
|
||||
### `already_target_codec_wrong_container`
|
||||
|
||||
The file is already in the target codec but is wrapped in an
|
||||
MP4/M4V container and you've configured MKV as the output
|
||||
extension. Alchemist will **remux** it (fast, lossless
|
||||
container conversion) rather than skip it.
|
||||
|
||||
**What to do:** Nothing - Alchemist handles this automatically.
|
||||
|
||||
### `bpp_below_threshold`
|
||||
|
||||
Bits-per-pixel is below the configured minimum threshold.
|
||||
The file is already efficiently compressed; transcoding it
|
||||
would consume significant CPU/GPU time for minimal savings
|
||||
and could introduce quality loss.
|
||||
|
||||
Technical detail: `bpp={value},threshold={value}` in the
|
||||
raw reason string. The threshold is resolution-adjusted
|
||||
(4K content has a lower effective threshold) and
|
||||
confidence-adjusted based on how reliable the bitrate
|
||||
measurement is.
|
||||
|
||||
**What to do:** If you believe the file should be transcoded,
|
||||
lower `min_bpp_threshold` in Settings -> Transcoding. The
|
||||
default is 0.10.
|
||||
|
||||
### `below_min_file_size`
|
||||
|
||||
The file is smaller than `min_file_size_mb`. Transcoding
|
||||
very small files is usually not worth the time.
|
||||
|
||||
**What to do:** Lower `min_file_size_mb` in Settings ->
|
||||
Transcoding if you want small files processed. Default is 50 MB.
|
||||
|
||||
### `size_reduction_insufficient`
|
||||
|
||||
The predicted output size is not meaningfully smaller than
|
||||
the input. Alchemist estimated the output would be less than
|
||||
`size_reduction_threshold` smaller.
|
||||
|
||||
**What to do:** Lower `size_reduction_threshold` in Settings
|
||||
-> Transcoding if you want more aggressive transcoding.
|
||||
Default is 0.30 (30% reduction required).
|
||||
|
||||
### `no_suitable_encoder`
|
||||
|
||||
No encoder is available for the target codec on this machine.
|
||||
This usually means hardware detection failed and CPU fallback
|
||||
is disabled.
|
||||
|
||||
**What to do:** Check Settings -> Hardware. Enable CPU fallback,
|
||||
or fix hardware detection. See the Hardware guides for your
|
||||
GPU vendor.
|
||||
|
||||
### `incomplete_metadata`
|
||||
|
||||
FFprobe could not determine resolution, duration, or bitrate
|
||||
for this file. Without reliable metadata Alchemist cannot
|
||||
make a valid transcoding decision.
|
||||
|
||||
**What to do:** Check if the file is corrupt using Library
|
||||
Doctor. Try playing it in a media player to confirm it works.
|
||||
|
||||
## Why so many skips is a good sign
|
||||
|
||||
A high skip rate means Alchemist is protecting you from
|
||||
pointless re-encodes. Files get skipped when they are already
|
||||
efficiently compressed - the work has already been done,
|
||||
either by whoever encoded them originally or by a previous
|
||||
Alchemist run.
|
||||
|
||||
A library where 80% of files are skipped and 20% are transcoded
|
||||
is normal for a library that already has a mix of well-encoded
|
||||
and poorly-encoded content.
|
||||
@@ -1,84 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
Solutions for common issues and how to diagnose problems with Alchemist.
|
||||
|
||||
This page provides answers to the most common problems users face when using Alchemist.
|
||||
|
||||
## Common Issues
|
||||
|
||||
### "Failed to load settings" / 401 Unauthorized
|
||||
|
||||
**Cause**: Your session has expired, or the authentication token is no longer being sent correctly.
|
||||
|
||||
**Solution**: Clear your browser's local storage and re-login:
|
||||
```javascript
|
||||
localStorage.removeItem('alchemist_token');
|
||||
window.location.href = '/login';
|
||||
```
|
||||
|
||||
### "No hardware encoder detected"
|
||||
|
||||
**Cause**: The necessary GPU drivers are missing, or the container is not configured to see your graphics card.
|
||||
|
||||
**Solution**:
|
||||
1. **Check FFmpeg**: Run `ffmpeg -encoders | grep -E "nvenc|qsv|vaapi"` inside your container to see if hardware support is enabled.
|
||||
2. **Verify Drivers**: For NVIDIA, ensure the **NVIDIA Container Toolkit** is installed on your host.
|
||||
3. **Check Permissions**: On Linux, ensure the user has access to `/dev/dri` (usually by adding them to the `render` or `video` groups).
|
||||
|
||||
### Jobs stuck in "queued" state
|
||||
|
||||
**Cause**: The engine might be paused, or there are no available slots in the scheduler.
|
||||
|
||||
**Solution**:
|
||||
1. **Check Status**: Go to the **Dashboard** and look for a "Resume" button.
|
||||
2. **Check Logs**: Visit the `/logs` page to see if any errors are being reported by the scheduler.
|
||||
|
||||
### High CPU usage during encoding
|
||||
|
||||
**Cause**: Alchemist is falling back to your CPU (Software Encoding) instead of using your graphics card.
|
||||
|
||||
**Solution**:
|
||||
1. **Verify Hardware**: Check the **Hardware Settings** to ensure your GPU is selected.
|
||||
2. **Reduce Jobs**: Lower the `concurrent_jobs` setting (try setting it to `1`).
|
||||
3. **Use Speed Profile**: Switch to the "Speed" quality profile in **Settings**.
|
||||
|
||||
### Database locked errors
|
||||
|
||||
**Cause**: Multiple processes are trying to write to the SQLite database at the same time.
|
||||
|
||||
**Solution**:
|
||||
1. **Single Instance**: Ensure you aren't running more than one Alchemist container at once.
|
||||
2. **Zombie Processes**: If you aren't using Docker, check for any old Alchemist processes running in the background.
|
||||
3. **Check Locks**: If it persists, you may need to manually delete the lock file in your `data/` folder.
|
||||
|
||||
### Files being skipped unexpectedly
|
||||
|
||||
**Cause**: The Alchemist analysis has determined that a transcode wouldn't actually save any space or would ruin the quality.
|
||||
|
||||
**Solution**:
|
||||
1. **Check the Logs**: Look at the "Decision Log" in `/logs` to see the reason for skipping.
|
||||
2. **Adjust Thresholds**: You might have a high `min_file_size_mb` or a strict `size_reduction_threshold`. Adjust these in **Settings**.
|
||||
|
||||
### VMAF scores not appearing
|
||||
|
||||
**Cause**: The version of FFmpeg you are using might not have `libvmaf` support.
|
||||
|
||||
**Solution**:
|
||||
1. **Check FFmpeg Filters**: Run `ffmpeg -filters | grep vmaf`.
|
||||
2. **VMAF is Optional**: Don't worry, transcoding will still work perfectly even without quality scoring.
|
||||
|
||||
## Log Locations
|
||||
|
||||
If you're still stuck, checking the logs is the best way to find out what's going wrong.
|
||||
|
||||
| Environment | Command to View Logs |
|
||||
| :--- | :--- |
|
||||
| **Docker** | `docker logs -f alchemist` |
|
||||
| **Binary** | View standard output (or redirect to a file) |
|
||||
| **Systemd** | `journalctl -u alchemist -f` |
|
||||
|
||||
## Getting More Help
|
||||
|
||||
If your issue isn't listed here, you can:
|
||||
- **Check GitHub Issues**: [Browse existing reports or create a new one](https://github.com/bybrooklyn/alchemist/issues).
|
||||
- **Review the Live Logs**: Use the `/logs` page in the Alchemist web interface for real-time diagnostics.
|
||||
@@ -1,749 +0,0 @@
|
||||
# Troubleshooting Guide
|
||||
|
||||
Comprehensive guide to diagnosing and solving common Alchemist issues.
|
||||
|
||||
# Troubleshooting Guide
|
||||
|
||||
This comprehensive guide helps you diagnose and resolve common issues with Alchemist. Issues are organized by category with step-by-step solutions.
|
||||
|
||||
## General Diagnostics
|
||||
|
||||
### Log Locations
|
||||
|
||||
**Default log locations:**
|
||||
- **Linux/macOS**: `~/.config/alchemist/logs/`
|
||||
- **Windows**: `%APPDATA%\alchemist\logs\`
|
||||
- **Docker**: `/app/data/logs/` (if mounted)
|
||||
|
||||
**View recent logs:**
|
||||
```bash
|
||||
# Real-time log monitoring
|
||||
tail -f ~/.config/alchemist/logs/alchemist.log
|
||||
|
||||
# Last 100 lines
|
||||
tail -100 ~/.config/alchemist/logs/alchemist.log
|
||||
|
||||
# Search for errors
|
||||
grep -i error ~/.config/alchemist/logs/alchemist.log
|
||||
```
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable detailed logging:
|
||||
```bash
|
||||
# Environment variable
|
||||
RUST_LOG=debug ./alchemist
|
||||
|
||||
# Or in Docker
|
||||
docker run -e RUST_LOG=debug ghcr.io/bybrooklyn/alchemist:latest
|
||||
```
|
||||
|
||||
### System Health Check
|
||||
|
||||
Verify your setup:
|
||||
```bash
|
||||
# Check FFmpeg
|
||||
ffmpeg -version
|
||||
|
||||
# Test hardware encoders
|
||||
ffmpeg -encoders | grep -E "nvenc|qsv|vaapi|amf|videotoolbox"
|
||||
|
||||
# Check disk space
|
||||
df -h
|
||||
|
||||
# Monitor system resources
|
||||
htop # or top on basic systems
|
||||
```
|
||||
|
||||
## Authentication & Access Issues
|
||||
|
||||
### "Failed to load settings" / 401 Unauthorized
|
||||
|
||||
**Symptoms:**
|
||||
- Can't access web interface
|
||||
- "Authentication failed" messages
|
||||
- Redirected to login repeatedly
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Clear browser storage:**
|
||||
```javascript
|
||||
// Open browser dev tools (F12), then Console tab
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
location.reload();
|
||||
```
|
||||
|
||||
2. **Reset admin password:**
|
||||
```bash
|
||||
# Stop Alchemist, then reset database auth
|
||||
sqlite3 ~/.config/alchemist/alchemist.db "DELETE FROM user_sessions;"
|
||||
sqlite3 ~/.config/alchemist/alchemist.db "UPDATE users SET password_hash = '' WHERE username = 'admin';"
|
||||
```
|
||||
|
||||
3. **Check configuration:**
|
||||
```toml
|
||||
[system]
|
||||
https_only = false # Ensure this is false unless using HTTPS
|
||||
```
|
||||
|
||||
### Can't Access Web Interface
|
||||
|
||||
**Symptoms:**
|
||||
- Browser shows "connection refused"
|
||||
- Timeout errors
|
||||
- Blank page loads
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Verify Alchemist is running:**
|
||||
```bash
|
||||
# Check process
|
||||
ps aux | grep alchemist
|
||||
|
||||
# Check port binding
|
||||
netstat -tlnp | grep 3000
|
||||
```
|
||||
|
||||
2. **Check firewall settings:**
|
||||
```bash
|
||||
# Linux (ufw)
|
||||
sudo ufw allow 3000
|
||||
|
||||
# Linux (firewall-cmd)
|
||||
sudo firewall-cmd --add-port=3000/tcp --permanent
|
||||
sudo firewall-cmd --reload
|
||||
```
|
||||
|
||||
3. **Try different browsers/incognito mode**
|
||||
|
||||
4. **Check Docker port mapping:**
|
||||
```yaml
|
||||
# Ensure correct port mapping in docker-compose.yml
|
||||
ports:
|
||||
- "3000:3000" # Host:Container
|
||||
```
|
||||
|
||||
## Hardware Detection Issues
|
||||
|
||||
### "No hardware encoder detected"
|
||||
|
||||
**Symptoms:**
|
||||
- Only CPU encoding available
|
||||
- Hardware shows as "Not detected"
|
||||
- Slow transcoding speeds
|
||||
|
||||
**Diagnosis steps:**
|
||||
|
||||
1. **Check hardware detection:**
|
||||
```bash
|
||||
# NVIDIA
|
||||
nvidia-smi
|
||||
|
||||
# Intel
|
||||
ls -la /dev/dri/
|
||||
|
||||
# AMD
|
||||
lspci | grep -i amd
|
||||
|
||||
# Apple (macOS)
|
||||
system_profiler SPHardwareDataType
|
||||
```
|
||||
|
||||
2. **Verify FFmpeg support:**
|
||||
```bash
|
||||
ffmpeg -encoders | grep -E "nvenc|qsv|vaapi|amf|videotoolbox"
|
||||
```
|
||||
|
||||
**Solutions by vendor:**
|
||||
|
||||
#### NVIDIA Issues
|
||||
```bash
|
||||
# Install NVIDIA Container Toolkit (Docker)
|
||||
# Ubuntu/Debian:
|
||||
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
|
||||
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
|
||||
curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
|
||||
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
|
||||
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
|
||||
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
|
||||
sudo systemctl restart docker
|
||||
|
||||
# Test GPU access in container
|
||||
docker run --rm --gpus all nvidia/cuda:12.0-base nvidia-smi
|
||||
```
|
||||
|
||||
#### Intel Issues
|
||||
```bash
|
||||
# Ensure iGPU is enabled in BIOS
|
||||
# Add user to video/render groups
|
||||
sudo usermod -a -G video,render $USER
|
||||
|
||||
# Install Intel media drivers (Ubuntu/Debian)
|
||||
sudo apt install intel-media-va-driver libva-utils
|
||||
|
||||
# Test VAAPI
|
||||
vainfo --display drm --device /dev/dri/renderD128
|
||||
```
|
||||
|
||||
#### AMD Issues
|
||||
```bash
|
||||
# Install Mesa drivers (Ubuntu/Debian)
|
||||
sudo apt install mesa-va-drivers libva-utils
|
||||
|
||||
# Add user to video/render groups
|
||||
sudo usermod -a -G video,render $USER
|
||||
|
||||
# Test VAAPI
|
||||
vainfo --display drm --device /dev/dri/renderD128
|
||||
```
|
||||
|
||||
### Hardware Detected But Encoding Fails
|
||||
|
||||
**Symptoms:**
|
||||
- Hardware shows as detected
|
||||
- Encoding jobs fail with GPU errors
|
||||
- Falls back to CPU
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Check GPU memory:**
|
||||
```bash
|
||||
# NVIDIA
|
||||
nvidia-smi
|
||||
|
||||
# Intel/AMD - check system memory if integrated
|
||||
free -h
|
||||
```
|
||||
|
||||
2. **Reduce concurrent jobs:**
|
||||
```toml
|
||||
[transcode]
|
||||
concurrent_jobs = 1 # Start with 1
|
||||
```
|
||||
|
||||
3. **Update drivers:**
|
||||
- NVIDIA: Download from nvidia.com
|
||||
- Intel: Update through Windows Update or Intel Driver Assistant
|
||||
- AMD: Download from amd.com/support
|
||||
|
||||
4. **Check for conflicting processes:**
|
||||
```bash
|
||||
# See what's using the GPU
|
||||
nvidia-smi # NVIDIA
|
||||
intel_gpu_top # Intel
|
||||
```
|
||||
|
||||
## Processing Issues
|
||||
|
||||
### Jobs Stuck in "Queued" State
|
||||
|
||||
**Symptoms:**
|
||||
- Jobs never start processing
|
||||
- Queue doesn't advance
|
||||
- Dashboard shows "paused" or "idle"
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Check engine status:**
|
||||
- Navigate to Dashboard
|
||||
- Look for "Paused" indicator
|
||||
- Click "Resume" if available
|
||||
|
||||
2. **Check system resources:**
|
||||
```bash
|
||||
# CPU usage
|
||||
top
|
||||
|
||||
# Memory usage
|
||||
free -h
|
||||
|
||||
# Disk space
|
||||
df -h
|
||||
```
|
||||
|
||||
3. **Restart the processor:**
|
||||
```bash
|
||||
# Binary installation
|
||||
pkill alchemist
|
||||
./alchemist
|
||||
|
||||
# Docker
|
||||
docker restart alchemist
|
||||
```
|
||||
|
||||
4. **Check scheduling windows:**
|
||||
```toml
|
||||
# Ensure schedule allows current time
|
||||
[schedule]
|
||||
[[schedule.windows]]
|
||||
start_time = "00:00" # 24/7 operation
|
||||
end_time = "23:59"
|
||||
enabled = true
|
||||
```
|
||||
|
||||
### Jobs Fail Immediately
|
||||
|
||||
**Symptoms:**
|
||||
- Jobs start but fail within seconds
|
||||
- "Encoding failed" messages in logs
|
||||
- No output files created
|
||||
|
||||
**Diagnosis:**
|
||||
|
||||
1. **Check specific error in logs:**
|
||||
```bash
|
||||
grep -A5 -B5 "failed" ~/.config/alchemist/logs/alchemist.log
|
||||
```
|
||||
|
||||
2. **Test FFmpeg command manually:**
|
||||
```bash
|
||||
# Extract the failed command from logs and test
|
||||
ffmpeg -i input.mkv -c:v libx264 -crf 23 test_output.mkv
|
||||
```
|
||||
|
||||
**Common solutions:**
|
||||
|
||||
1. **File permission issues:**
|
||||
```bash
|
||||
# Check file permissions
|
||||
ls -la /path/to/media/
|
||||
|
||||
# Fix permissions if needed
|
||||
chmod 644 /path/to/media/*
|
||||
```
|
||||
|
||||
2. **Corrupt source files:**
|
||||
```bash
|
||||
# Test source file
|
||||
ffmpeg -v error -i input.mkv -f null -
|
||||
```
|
||||
|
||||
3. **Insufficient disk space:**
|
||||
```bash
|
||||
# Check available space
|
||||
df -h
|
||||
|
||||
# Clean up if needed
|
||||
du -sh ~/.config/alchemist/logs/* | sort -h
|
||||
```
|
||||
|
||||
### Poor Quality Output
|
||||
|
||||
**Symptoms:**
|
||||
- Encoded files look worse than originals
|
||||
- Artifacts or blocking visible
|
||||
- Low VMAF scores
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Adjust quality settings:**
|
||||
```toml
|
||||
[transcode]
|
||||
quality_profile = "quality" # Use highest quality
|
||||
|
||||
# Or manually adjust CRF
|
||||
[transcode.encoder_args]
|
||||
extra_args = ["-crf", "20"] # Lower = better quality
|
||||
```
|
||||
|
||||
2. **Check source file quality:**
|
||||
```bash
|
||||
# Analyze source with ffprobe
|
||||
ffprobe -v quiet -show_format -show_streams input.mkv
|
||||
```
|
||||
|
||||
3. **Enable quality verification:**
|
||||
```toml
|
||||
[quality]
|
||||
enable_vmaf = true
|
||||
min_vmaf_score = 92.0 # Reject low quality transcodes
|
||||
revert_on_low_quality = true
|
||||
```
|
||||
|
||||
4. **Use appropriate codec:**
|
||||
```toml
|
||||
# For maximum quality
|
||||
[transcode]
|
||||
output_codec = "hevc" # Better than H.264
|
||||
quality_profile = "quality"
|
||||
```
|
||||
|
||||
## Performance Issues
|
||||
|
||||
### High CPU Usage During Encoding
|
||||
|
||||
**Symptoms:**
|
||||
- System becomes unresponsive
|
||||
- High CPU temperatures
|
||||
- Fan noise increases
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Verify hardware acceleration:**
|
||||
```bash
|
||||
# Check if GPU is being used
|
||||
nvidia-smi # Should show ffmpeg processes
|
||||
```
|
||||
|
||||
2. **Reduce CPU load:**
|
||||
```toml
|
||||
[transcode]
|
||||
concurrent_jobs = 1
|
||||
threads = 4 # Limit CPU threads
|
||||
|
||||
[system]
|
||||
engine_mode = "background" # Minimal resource usage
|
||||
```
|
||||
|
||||
3. **Enable hardware acceleration:**
|
||||
```toml
|
||||
[hardware]
|
||||
preferred_vendor = "nvidia" # or intel/amd/apple
|
||||
allow_cpu_fallback = false # Force hardware encoding
|
||||
```
|
||||
|
||||
### Slow Encoding Speeds
|
||||
|
||||
**Expected speeds** for reference:
|
||||
- **GPU encoding**: 1-5x realtime
|
||||
- **CPU encoding**: 0.1-2x realtime
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Check hardware utilization:**
|
||||
```bash
|
||||
# GPU usage
|
||||
nvidia-smi -l 1 # NVIDIA
|
||||
intel_gpu_top # Intel
|
||||
|
||||
# CPU usage
|
||||
htop
|
||||
```
|
||||
|
||||
2. **Optimize settings for speed:**
|
||||
```toml
|
||||
[transcode]
|
||||
quality_profile = "speed"
|
||||
output_codec = "h264" # Fastest encoding
|
||||
|
||||
[hardware]
|
||||
cpu_preset = "fast" # If using CPU fallback
|
||||
```
|
||||
|
||||
3. **Check thermal throttling:**
|
||||
```bash
|
||||
# Linux
|
||||
sensors
|
||||
|
||||
# macOS
|
||||
sudo powermetrics --samplers smc -n 1 | grep -i temp
|
||||
```
|
||||
|
||||
### High Memory Usage
|
||||
|
||||
**Symptoms:**
|
||||
- System uses excessive RAM
|
||||
- Out of memory errors
|
||||
- System becomes unstable
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Reduce memory usage:**
|
||||
```toml
|
||||
[transcode]
|
||||
concurrent_jobs = 1 # Reduce parallel processing
|
||||
threads = 4 # Lower thread count
|
||||
```
|
||||
|
||||
2. **Check for memory leaks:**
|
||||
```bash
|
||||
# Monitor Alchemist memory usage
|
||||
ps aux | grep alchemist
|
||||
|
||||
# Monitor over time
|
||||
while true; do ps -p $(pgrep alchemist) -o pid,ppid,cmd,%mem,%cpu; sleep 30; done
|
||||
```
|
||||
|
||||
3. **Restart periodically:**
|
||||
```bash
|
||||
# Set up log rotation and periodic restart
|
||||
# Add to crontab for daily restart
|
||||
0 6 * * * docker restart alchemist
|
||||
```
|
||||
|
||||
## Database Issues
|
||||
|
||||
### Database Locked Errors
|
||||
|
||||
**Symptoms:**
|
||||
- "Database is locked" in logs
|
||||
- Web interface becomes unresponsive
|
||||
- Jobs don't update status
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Stop all Alchemist processes:**
|
||||
```bash
|
||||
# Kill all instances
|
||||
pkill -f alchemist
|
||||
|
||||
# Or for Docker
|
||||
docker stop alchemist
|
||||
```
|
||||
|
||||
2. **Check for database corruption:**
|
||||
```bash
|
||||
# Test database integrity
|
||||
sqlite3 ~/.config/alchemist/alchemist.db "PRAGMA integrity_check;"
|
||||
```
|
||||
|
||||
3. **Backup and reset if needed:**
|
||||
```bash
|
||||
# Backup current database
|
||||
cp ~/.config/alchemist/alchemist.db ~/.config/alchemist/alchemist.db.backup
|
||||
|
||||
# If corrupted, reset (loses job history)
|
||||
rm ~/.config/alchemist/alchemist.db
|
||||
# Alchemist will recreate on next start
|
||||
```
|
||||
|
||||
### Migration Errors
|
||||
|
||||
**Symptoms:**
|
||||
- "Migration failed" on startup
|
||||
- Database version mismatch errors
|
||||
- Unable to start after update
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Backup database before fixes:**
|
||||
```bash
|
||||
cp ~/.config/alchemist/alchemist.db ~/.config/alchemist/alchemist.db.pre-fix
|
||||
```
|
||||
|
||||
2. **Check database version:**
|
||||
```bash
|
||||
sqlite3 ~/.config/alchemist/alchemist.db "PRAGMA user_version;"
|
||||
```
|
||||
|
||||
3. **Force migration recovery:**
|
||||
```bash
|
||||
# Stop Alchemist first
|
||||
# Then try manual schema fix (advanced users only)
|
||||
sqlite3 ~/.config/alchemist/alchemist.db
|
||||
# Run appropriate CREATE TABLE statements from migration files
|
||||
```
|
||||
|
||||
## Network & Connectivity
|
||||
|
||||
### API Timeout Errors
|
||||
|
||||
**Symptoms:**
|
||||
- Web interface loads slowly
|
||||
- "Request timeout" errors
|
||||
- Incomplete data loading
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Check system load:**
|
||||
```bash
|
||||
uptime
|
||||
htop
|
||||
```
|
||||
|
||||
2. **Increase timeout values:**
|
||||
```toml
|
||||
[system]
|
||||
monitoring_poll_interval = 5.0 # Slower polling
|
||||
```
|
||||
|
||||
3. **Optimize database:**
|
||||
```bash
|
||||
# Vacuum database
|
||||
sqlite3 ~/.config/alchemist/alchemist.db "VACUUM;"
|
||||
|
||||
# Reindex
|
||||
sqlite3 ~/.config/alchemist/alchemist.db "REINDEX;"
|
||||
```
|
||||
|
||||
### Notification Delivery Issues
|
||||
|
||||
**Symptoms:**
|
||||
- Discord/Gotify notifications not received
|
||||
- Webhook timeouts
|
||||
- "Failed to send notification" in logs
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Test webhook manually:**
|
||||
```bash
|
||||
# Test Discord webhook
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"content":"Test from Alchemist"}' \
|
||||
"YOUR_DISCORD_WEBHOOK_URL"
|
||||
```
|
||||
|
||||
2. **Check firewall/network:**
|
||||
```bash
|
||||
# Test external connectivity
|
||||
curl -I https://discord.com
|
||||
|
||||
# Check DNS resolution
|
||||
nslookup discord.com
|
||||
```
|
||||
|
||||
3. **Verify notification config:**
|
||||
```toml
|
||||
[[notifications.targets]]
|
||||
name = "discord"
|
||||
target_type = "discord"
|
||||
endpoint_url = "https://discord.com/api/webhooks/..."
|
||||
enabled = true
|
||||
events = ["job_complete", "job_failed"]
|
||||
```
|
||||
|
||||
## File System Issues
|
||||
|
||||
### Permission Denied Errors
|
||||
|
||||
**Symptoms:**
|
||||
- Can't read source files
|
||||
- Can't write output files
|
||||
- "Permission denied" in logs
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Check file ownership:**
|
||||
```bash
|
||||
ls -la /path/to/media/
|
||||
|
||||
# Fix ownership if needed
|
||||
sudo chown -R $USER:$USER /path/to/media/
|
||||
```
|
||||
|
||||
2. **Docker user mapping:**
|
||||
```yaml
|
||||
services:
|
||||
alchemist:
|
||||
user: "${UID}:${GID}" # Match host user
|
||||
```
|
||||
|
||||
3. **SELinux/AppArmor issues (Linux):**
|
||||
```bash
|
||||
# Check SELinux
|
||||
getenforce
|
||||
|
||||
# Temporarily disable for testing
|
||||
sudo setenforce 0
|
||||
|
||||
# Check AppArmor
|
||||
sudo aa-status
|
||||
```
|
||||
|
||||
### Files Not Found
|
||||
|
||||
**Symptoms:**
|
||||
- "File not found" despite file existing
|
||||
- Scan doesn't find media files
|
||||
- Empty libraries
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Verify paths in config:**
|
||||
```toml
|
||||
[scanner]
|
||||
directories = ["/correct/path/to/media"] # Check this path
|
||||
```
|
||||
|
||||
2. **Check file extensions:**
|
||||
```bash
|
||||
# See what files exist
|
||||
find /path/to/media -name "*.mkv" -o -name "*.mp4" -o -name "*.avi" | head -10
|
||||
```
|
||||
|
||||
3. **Test file access:**
|
||||
```bash
|
||||
# Can Alchemist user access the file?
|
||||
stat /path/to/media/movie.mkv
|
||||
```
|
||||
|
||||
## Recovery Procedures
|
||||
|
||||
### Complete Reset
|
||||
|
||||
If all else fails, reset Alchemist to fresh state:
|
||||
|
||||
1. **Backup important data:**
|
||||
```bash
|
||||
cp ~/.config/alchemist/config.toml ~/alchemist-config-backup.toml
|
||||
```
|
||||
|
||||
2. **Stop Alchemist:**
|
||||
```bash
|
||||
pkill -f alchemist
|
||||
# or
|
||||
docker stop alchemist
|
||||
```
|
||||
|
||||
3. **Reset database and config:**
|
||||
```bash
|
||||
rm -rf ~/.config/alchemist/
|
||||
# Alchemist will run setup wizard on next start
|
||||
```
|
||||
|
||||
### Partial Recovery
|
||||
|
||||
Keep configuration but reset job history:
|
||||
|
||||
```bash
|
||||
# Stop Alchemist
|
||||
pkill -f alchemist
|
||||
|
||||
# Reset only job-related tables
|
||||
sqlite3 ~/.config/alchemist/alchemist.db << EOF
|
||||
DELETE FROM jobs;
|
||||
DELETE FROM job_progress;
|
||||
DELETE FROM encoding_sessions;
|
||||
VACUUM;
|
||||
EOF
|
||||
```
|
||||
|
||||
## Getting Help
|
||||
|
||||
When seeking support:
|
||||
|
||||
1. **Gather system information:**
|
||||
```bash
|
||||
# Create debug info file
|
||||
{
|
||||
echo "=== System Info ==="
|
||||
uname -a
|
||||
echo ""
|
||||
echo "=== FFmpeg Version ==="
|
||||
ffmpeg -version
|
||||
echo ""
|
||||
echo "=== Hardware Info ==="
|
||||
lscpu
|
||||
lspci | grep -i vga
|
||||
echo ""
|
||||
echo "=== Recent Logs ==="
|
||||
tail -50 ~/.config/alchemist/logs/alchemist.log
|
||||
} > alchemist-debug.txt
|
||||
```
|
||||
|
||||
2. **Include configuration** (remove sensitive data):
|
||||
```bash
|
||||
# Sanitize config
|
||||
sed 's/password.*/password=REDACTED/' ~/.config/alchemist/config.toml > config-sanitized.toml
|
||||
```
|
||||
|
||||
3. **Describe the issue:**
|
||||
- What were you trying to do?
|
||||
- What happened instead?
|
||||
- When did it start happening?
|
||||
- What changed recently?
|
||||
|
||||
4. **Report issues at:**
|
||||
- GitHub: [github.com/bybrooklyn/alchemist/issues](https://github.com/bybrooklyn/alchemist/issues)
|
||||
- Include debug info and sanitized config
|
||||
@@ -70,7 +70,7 @@ PY
|
||||
|
||||
cat <<EOF
|
||||
Next steps:
|
||||
1. Update CHANGELOG.md and redoc/reference/changelog.md for v${VERSION}
|
||||
1. Update CHANGELOG.md for v${VERSION}
|
||||
2. Run cargo test --quiet
|
||||
3. Run bun run typecheck && bun run build (in web/)
|
||||
4. Run bun run test:reliability (in web-e2e/)
|
||||
|
||||
@@ -18,5 +18,4 @@ pub use db::AlchemistEvent;
|
||||
pub use media::ffmpeg::{EncodeStats, EncoderCapabilities, HardwareAccelerators};
|
||||
pub use media::processor::Agent;
|
||||
pub use orchestrator::Transcoder;
|
||||
// pub use system::notifications::NotificationService; // Deprecated user-facing export?
|
||||
pub use system::watcher::FileWatcher;
|
||||
|
||||
@@ -467,7 +467,10 @@ async fn run() -> Result<()> {
|
||||
info!("Starting web server...");
|
||||
|
||||
// Initialize File Watcher
|
||||
let file_watcher = Arc::new(alchemist::system::watcher::FileWatcher::new(db.clone()));
|
||||
let file_watcher = Arc::new(alchemist::system::watcher::FileWatcher::new(
|
||||
db.clone(),
|
||||
Some(agent.clone()),
|
||||
));
|
||||
|
||||
// Initialize Library Scanner (shared between boot task and server)
|
||||
let library_scanner = Arc::new(alchemist::system::scanner::LibraryScanner::new(
|
||||
|
||||
@@ -29,6 +29,7 @@ pub struct Agent {
|
||||
dry_run: bool,
|
||||
in_flight_jobs: Arc<AtomicUsize>,
|
||||
analyzing_boot: Arc<AtomicBool>,
|
||||
analysis_semaphore: Arc<tokio::sync::Semaphore>,
|
||||
}
|
||||
|
||||
impl Agent {
|
||||
@@ -65,6 +66,7 @@ impl Agent {
|
||||
dry_run,
|
||||
in_flight_jobs: Arc::new(AtomicUsize::new(0)),
|
||||
analyzing_boot: Arc::new(AtomicBool::new(false)),
|
||||
analysis_semaphore: Arc::new(tokio::sync::Semaphore::new(1)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,6 +180,19 @@ impl Agent {
|
||||
/// startup to populate the queue with decisions before the
|
||||
/// user starts the engine.
|
||||
pub async fn analyze_pending_jobs(&self) {
|
||||
// Serialize all analysis passes to prevent
|
||||
// concurrent runs from racing on job state
|
||||
let _permit = match self.analysis_semaphore.acquire().await {
|
||||
Ok(p) => p,
|
||||
Err(_) => {
|
||||
tracing::warn!(
|
||||
"Auto-analysis: semaphore closed, \
|
||||
skipping."
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
self.set_boot_analyzing(true);
|
||||
|
||||
info!("Auto-analysis: scanning and analyzing pending jobs...");
|
||||
|
||||
@@ -30,8 +30,20 @@ pub(crate) async fn scan_handler(State(state): State<Arc<AppState>>) -> impl Int
|
||||
}
|
||||
}
|
||||
|
||||
let _ = state.agent.scan_and_enqueue(dirs).await;
|
||||
StatusCode::OK
|
||||
if let Err(e) = state.agent.scan_and_enqueue(dirs).await {
|
||||
error!("Scan failed: {e}");
|
||||
return (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response();
|
||||
}
|
||||
|
||||
// Trigger analysis after scan completes so jobs
|
||||
// get skip/transcode decisions immediately, matching
|
||||
// boot and setup scan behavior
|
||||
let agent = state.agent.clone();
|
||||
tokio::spawn(async move {
|
||||
agent.analyze_pending_jobs().await;
|
||||
});
|
||||
|
||||
StatusCode::OK.into_response()
|
||||
}
|
||||
|
||||
pub(crate) async fn start_scan_handler(State(state): State<Arc<AppState>>) -> impl IntoResponse {
|
||||
|
||||
@@ -86,7 +86,7 @@ where
|
||||
.await,
|
||||
);
|
||||
let scheduler = crate::scheduler::Scheduler::new(db.clone(), agent.clone());
|
||||
let file_watcher = Arc::new(crate::system::watcher::FileWatcher::new(db.clone()));
|
||||
let file_watcher = Arc::new(crate::system::watcher::FileWatcher::new(db.clone(), None));
|
||||
|
||||
let mut sys = sysinfo::System::new();
|
||||
sys.refresh_cpu_usage();
|
||||
|
||||
@@ -1017,7 +1017,7 @@ fn discover_probe_candidates_with_runner<R: CommandRunner + ?Sized>(
|
||||
candidates
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[cfg(all(test, target_os = "linux"))]
|
||||
fn detect_explicit_device_path_with_runner<R: CommandRunner + ?Sized>(
|
||||
runner: &R,
|
||||
device_path: &str,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
pub mod fs_browser;
|
||||
pub mod hardware;
|
||||
pub mod notifications;
|
||||
pub mod scanner;
|
||||
pub mod watcher;
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
//! Notification system for job events
|
||||
//!
|
||||
//! Supports generic webhooks and Discord webhooks.
|
||||
|
||||
use crate::config::NotificationsConfig;
|
||||
use crate::db::Job;
|
||||
use crate::error::{AlchemistError, Result};
|
||||
use serde::Serialize;
|
||||
use tracing::debug;
|
||||
|
||||
/// Notification service for sending alerts
|
||||
pub struct NotificationService {
|
||||
config: NotificationsConfig,
|
||||
client: reqwest::Client,
|
||||
}
|
||||
|
||||
impl NotificationService {
|
||||
pub fn new(config: NotificationsConfig) -> Self {
|
||||
Self {
|
||||
config,
|
||||
client: reqwest::Client::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if notifications are enabled
|
||||
pub fn is_enabled(&self) -> bool {
|
||||
self.config.enabled
|
||||
&& (self.config.webhook_url.is_some() || self.config.discord_webhook.is_some())
|
||||
}
|
||||
|
||||
/// Send notification for job completion
|
||||
pub async fn notify_job_complete(&self, job: &Job, stats: Option<&str>) -> Result<()> {
|
||||
if !self.config.enabled || !self.config.notify_on_complete {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let message = format!(
|
||||
"✅ **Job #{} Completed**\n📁 {}\n{}",
|
||||
job.id,
|
||||
job.input_path,
|
||||
stats.unwrap_or("")
|
||||
);
|
||||
|
||||
self.send_all(&message, "Job Completed", 0x00FF00).await
|
||||
}
|
||||
|
||||
/// Send notification for job failure
|
||||
pub async fn notify_job_failed(&self, job: &Job, error: &str) -> Result<()> {
|
||||
if !self.config.enabled || !self.config.notify_on_failure {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let message = format!(
|
||||
"❌ **Job #{} Failed**\n📁 {}\n⚠️ Error: {}",
|
||||
job.id, job.input_path, error
|
||||
);
|
||||
|
||||
self.send_all(&message, "Job Failed", 0xFF0000).await
|
||||
}
|
||||
|
||||
/// Send to all configured endpoints
|
||||
async fn send_all(&self, message: &str, title: &str, color: u32) -> Result<()> {
|
||||
let mut errors = Vec::new();
|
||||
|
||||
// Send to generic webhook
|
||||
if let Some(ref url) = self.config.webhook_url {
|
||||
if let Err(e) = self.send_webhook(url, message).await {
|
||||
errors.push(format!("Webhook: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
// Send to Discord
|
||||
if let Some(ref url) = self.config.discord_webhook {
|
||||
if let Err(e) = self.send_discord(url, title, message, color).await {
|
||||
errors.push(format!("Discord: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
if errors.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(AlchemistError::Notification(errors.join(", ")))
|
||||
}
|
||||
}
|
||||
|
||||
/// Send to a generic webhook (POST with JSON body)
|
||||
async fn send_webhook(&self, url: &str, message: &str) -> Result<()> {
|
||||
#[derive(Serialize)]
|
||||
struct WebhookPayload<'a> {
|
||||
message: &'a str,
|
||||
source: &'a str,
|
||||
timestamp: String,
|
||||
}
|
||||
|
||||
let payload = WebhookPayload {
|
||||
message,
|
||||
source: "alchemist",
|
||||
timestamp: chrono::Utc::now().to_rfc3339(),
|
||||
};
|
||||
|
||||
let response = self
|
||||
.client
|
||||
.post(url)
|
||||
.json(&payload)
|
||||
.timeout(std::time::Duration::from_secs(10))
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| AlchemistError::Notification(format!("HTTP error: {}", e)))?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
return Err(AlchemistError::Notification(format!(
|
||||
"Webhook returned {}",
|
||||
response.status()
|
||||
)));
|
||||
}
|
||||
|
||||
debug!("Webhook notification sent successfully");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Send to Discord webhook with embed
|
||||
async fn send_discord(&self, url: &str, title: &str, message: &str, color: u32) -> Result<()> {
|
||||
#[derive(Serialize)]
|
||||
struct DiscordEmbed<'a> {
|
||||
title: &'a str,
|
||||
description: &'a str,
|
||||
color: u32,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct DiscordPayload<'a> {
|
||||
username: &'a str,
|
||||
embeds: Vec<DiscordEmbed<'a>>,
|
||||
}
|
||||
|
||||
let payload = DiscordPayload {
|
||||
username: "Alchemist",
|
||||
embeds: vec![DiscordEmbed {
|
||||
title,
|
||||
description: message,
|
||||
color,
|
||||
}],
|
||||
};
|
||||
|
||||
let response = self
|
||||
.client
|
||||
.post(url)
|
||||
.json(&payload)
|
||||
.timeout(std::time::Duration::from_secs(10))
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| AlchemistError::Notification(format!("HTTP error: {}", e)))?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
return Err(AlchemistError::Notification(format!(
|
||||
"Discord returned {}",
|
||||
response.status()
|
||||
)));
|
||||
}
|
||||
|
||||
debug!("Discord notification sent successfully");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper to format job stats for notifications
|
||||
pub fn format_job_stats(
|
||||
input_size_mb: u64,
|
||||
output_size_mb: u64,
|
||||
reduction_pct: f64,
|
||||
duration_secs: f64,
|
||||
) -> String {
|
||||
format!(
|
||||
"📊 {} MB → {} MB ({:.1}% reduction) in {:.1}s",
|
||||
input_size_mb, output_size_mb, reduction_pct, duration_secs
|
||||
)
|
||||
}
|
||||
@@ -96,13 +96,20 @@ impl PendingState {
|
||||
pub struct FileWatcher {
|
||||
inner: Arc<std::sync::Mutex<Option<RecommendedWatcher>>>,
|
||||
tx: mpsc::UnboundedSender<PendingEvent>,
|
||||
agent: Option<Arc<crate::media::processor::Agent>>,
|
||||
}
|
||||
|
||||
impl FileWatcher {
|
||||
pub fn new(db: Arc<Db>) -> Self {
|
||||
pub fn new(db: Arc<Db>, agent: Option<Arc<crate::media::processor::Agent>>) -> Self {
|
||||
let (tx, mut rx) = mpsc::unbounded_channel::<PendingEvent>();
|
||||
let poll_interval = Duration::from_secs(1);
|
||||
let db_clone = db.clone();
|
||||
let watcher = Self {
|
||||
inner: Arc::new(std::sync::Mutex::new(None)),
|
||||
tx,
|
||||
agent,
|
||||
};
|
||||
let agent_clone = watcher.agent.clone();
|
||||
|
||||
// Process filesystem events after the target file has stabilized.
|
||||
tokio::spawn(async move {
|
||||
@@ -150,7 +157,15 @@ impl FileWatcher {
|
||||
source_root: key.source_root.clone(),
|
||||
};
|
||||
match crate::media::pipeline::enqueue_discovered_with_db(&db_clone, discovered).await {
|
||||
Ok(true) => info!("Auto-enqueued: {:?}", key.path),
|
||||
Ok(true) => {
|
||||
info!("Auto-enqueued: {:?}", key.path);
|
||||
if let Some(agent) = &agent_clone {
|
||||
let agent = agent.clone();
|
||||
tokio::spawn(async move {
|
||||
agent.analyze_pending_jobs().await;
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(false) => debug!("No queue update needed for {:?}", key.path),
|
||||
Err(e) => error!("Failed to auto-enqueue {:?}: {}", key.path, e),
|
||||
}
|
||||
@@ -161,10 +176,7 @@ impl FileWatcher {
|
||||
}
|
||||
});
|
||||
|
||||
Self {
|
||||
inner: Arc::new(std::sync::Mutex::new(None)),
|
||||
tx,
|
||||
}
|
||||
watcher
|
||||
}
|
||||
|
||||
/// Update watched directories
|
||||
@@ -413,7 +425,7 @@ mod tests {
|
||||
std::fs::create_dir_all(&watch_dir)?;
|
||||
|
||||
let db = Arc::new(Db::new(db_path.to_string_lossy().as_ref()).await?);
|
||||
let watcher = FileWatcher::new(db.clone());
|
||||
let watcher = FileWatcher::new(db.clone(), None);
|
||||
watcher.watch(&[WatchPath {
|
||||
path: watch_dir.clone(),
|
||||
recursive: false,
|
||||
@@ -453,7 +465,7 @@ mod tests {
|
||||
std::fs::create_dir_all(&watch_dir)?;
|
||||
|
||||
let db = Arc::new(Db::new(db_path.to_string_lossy().as_ref()).await?);
|
||||
let watcher = FileWatcher::new(db.clone());
|
||||
let watcher = FileWatcher::new(db.clone(), None);
|
||||
watcher.watch(&[WatchPath {
|
||||
path: watch_dir.clone(),
|
||||
recursive: false,
|
||||
@@ -494,7 +506,7 @@ mod tests {
|
||||
std::fs::create_dir_all(&watch_dir)?;
|
||||
|
||||
let db = Arc::new(Db::new(db_path.to_string_lossy().as_ref()).await?);
|
||||
let watcher = FileWatcher::new(db.clone());
|
||||
let watcher = FileWatcher::new(db.clone(), None);
|
||||
watcher.watch(&[WatchPath {
|
||||
path: watch_dir.clone(),
|
||||
recursive: false,
|
||||
@@ -537,7 +549,7 @@ mod tests {
|
||||
std::fs::create_dir_all(&staging_root)?;
|
||||
|
||||
let db = Arc::new(Db::new(db_path.to_string_lossy().as_ref()).await?);
|
||||
let watcher = FileWatcher::new(db.clone());
|
||||
let watcher = FileWatcher::new(db.clone(), None);
|
||||
watcher.watch(&[WatchPath {
|
||||
path: watch_dir.clone(),
|
||||
recursive: false,
|
||||
|
||||
@@ -55,7 +55,7 @@ test("engine cycle: Start transitions to Running, Stop transitions to Stopping",
|
||||
|
||||
await page.getByRole("button", { name: "Start" }).click();
|
||||
await expect.poll(() => resumeCalls).toBe(1);
|
||||
await expect(page.getByText("Running", { exact: true })).toBeVisible();
|
||||
await expect(page.getByText("Idle", { exact: true })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Stop" })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Pause" })).not.toBeVisible();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user