| Crates.io | direct_play_nice |
| lib.rs | direct_play_nice |
| version | 0.1.0-alpha.3 |
| created_at | 2025-10-05 12:26:10.536518+00 |
| updated_at | 2025-11-06 18:38:59.105472+00 |
| description | CLI program that converts video files to direct-play-compatible formats. |
| homepage | https://github.com/ns-mkusper/direct-play-nice |
| repository | https://github.com/ns-mkusper/direct-play-nice |
| max_upload_size | |
| id | 1868987 |
| size | 557,389 |
A CLI utility to convert video files to Direct-Play-compatible (the single best optimization for your home video streaming server) formats.
This tool was created to convert video files to formats that satisfy Direct Play requirements for all video files used by your video streaming server and their streaming devices (eg. Chromcast). It is intended to be added to a video-downloading service (ie. with Sonarr or Radarr) as an optimization feature and seamless to the end user (ie. Direct Play selected by default).
--streaming-devices.| Device Name | Release Year | Video Codecs | Audio Codecs | Resolution Support |
|---|---|---|---|---|
| Chromecast | 2013 | H.264, VP8 | HE-AAC, LC-AAC, MP3, Vorbis, WAV (LPCM) | Up to 1080p |
| Chromecast 2 | 2015 | H.264, VP8 | HE-AAC, LC-AAC, MP3, Vorbis, WAV (LPCM) | Up to 1080p |
| Chromecast Audio | 2015 | N/A | HE-AAC, LC-AAC, MP3, Vorbis, WAV (LPCM), FLAC | N/A |
| Chromecast Ultra | 2016 | H.264, VP8, VP9, HEVC | HE-AAC, LC-AAC, MP3, Vorbis, WAV (LPCM), FLAC | Up to 4K |
| Chromecast 3 | 2018 | H.264, VP8, VP9 | HE-AAC, LC-AAC, MP3, Vorbis, WAV (LPCM) | Up to 1080p |
| Chromecast with Google TV | 2020 | H.264, VP8, VP9, HEVC, Dolby Vision, HDR10, HDR10+ | HE-AAC, LC-AAC, MP3, Vorbis, WAV (LPCM), FLAC, Dolby Digital, Dolby Digital Plus, Dolby Atmos | Up to 4K HDR |
| Chromecast with Google TV (HD) | 2022 | H.264, VP8, VP9, HEVC, HDR10, HDR10+ | HE-AAC, LC-AAC, MP3, Vorbis, WAV (LPCM), FLAC, Dolby Digital, Dolby Digital Plus, Dolby Atmos | Up to 1080p HDR |
Each device above exposes a model identifier (e.g. chromecast_ultra). The CLI
assumes every device by default; supply
--streaming-devices chromecast_ultra,chromecast_1st_gen or
--streaming-devices all to override.
This program can be run standlone directly on the CLI or as a Custom Script Connection with Sonarr or Radarr.
Usage: direct_play_nice.exe [OPTIONS] <INPUT_FILE> <OUTPUT_FILE>
Arguments:
<INPUT_FILE> Video file to convert
<OUTPUT_FILE> Our output direct-play-compatible video file
Options:
-s, --streaming-devices <STREAMING_DEVICES>
Comma-separated device models or 'all'. When omitted or set to 'all',
assumes all known devices.
-c, --config-file <CONFIG_FILE>
Path to the configuration file
--video-quality <VIDEO_QUALITY>
Target video quality profile (defaults to match the source)
[default: match-source] [possible values: match-source, 360p, 480p,
720p, 1080p, 1440p, 2160p]
--audio-quality <AUDIO_QUALITY>
Target audio quality profile (defaults to match the source)
[default: match-source] [possible values: match-source, 320k, 256k,
224k, 192k, 160k, 128k, 96k]
--max-video-bitrate <MAX_VIDEO_BITRATE>
Maximum video bitrate (e.g. 8M, 4800k, 5.5mbps)
--max-audio-bitrate <MAX_AUDIO_BITRATE>
Maximum audio bitrate (e.g. 320k, 0.2M)
--unsupported-video-policy <POLICY>
How to handle unsupported/extra video streams: convert|ignore|fail
(default: ignore)
--primary-video-stream-index <INDEX>
Override auto selection of primary video stream (0-based)
--primary-video-criteria <CRITERIA>
Auto-pick criteria for primary video: resolution|bitrate|fps
(default: resolution)
--probe-streams
Print detailed info for all streams in the input and exit
--streams-filter <FILTER>
Filter streams in probe: all|video|audio|subtitle (default: all)
--output <FORMAT>
Output format for probe results: text|json (default: text)
--hw-accel <HW_ACCEL>
Hardware acceleration: auto|none|nvenc|vaapi|qsv|videotoolbox|amf
(default: auto)
--probe-hw
Print available HW devices/encoders and exit
--probe-codecs
Print all FFmpeg encoders/decoders and exit
--only-video
Probe filter: only show video codecs
--only-hw
Probe filter: only show hardware-capable codecs
--probe-json
Output probe results as JSON
-h, --help
Print help
-V, --version
Print version
Notes:
--probe-hw, --probe-codecs, --probe-streams), the
positional <INPUT_FILE> <OUTPUT_FILE> are not required (except
--probe-streams, which requires <INPUT_FILE>).-s all has the same effect as omitting -s: the tool computes a
direct-play profile compatible across all known devices.--servarr-output-extension and --servarr-output-suffix to control
how Sonarr/Radarr replacements are named. When run from Sonarr, the CLI
defaults to creating Episode.fixed.<ext> (with the extension derived from
the conversion output).--delete-source if you want the original input removed after a
successful conversion (ignored during Sonarr/Radarr runs because the tool
already swaps the file in place).DIRECT_PLAY_NICE_MAX_JOBS
for a global cap, or DIRECT_PLAY_NICE_JOBS_PER_GPU to control how many
simultaneous encodes run on each detected GPU (default: two per NVIDIA/AMD
device; NVIDIA is detected via nvidia-smi, AMD via rocm-smi on Linux or
PowerShell on Windows). Machines without supported detection fall back to a
single shared queue; set
DIRECT_PLAY_NICE_MAX_JOBS manually if you want more parallelism on AMD or
CPU-only hosts.-schromecast_1st_genchromecast_2nd_genchromecast_ultraYou can pass multiple, e.g. -s chromecast_1st_gen,chromecast_2nd_gen, or just
use -s all.
Convert for all devices (same as omitting -s):
direct_play_nice -s all input.mkv out.mp4
Convert for specific devices (intersection of capabilities):
direct_play_nice -s chromecast_1st_gen,chromecast_2nd_gen input.mkv out.mp4
Probe hardware and codec availability (JSON):
direct_play_nice --probe-hw --probe-codecs --only-video --only-hw --probe-json
Probe input streams (text and JSON):
direct_play_nice --probe-streams input.mkv
direct_play_nice --probe-streams --output json input.mkv
When running via Sonarr, Radarr, etc you can use this program to convert each
downloaded video file to a Direct-Play-compatible format by adding it as a
Custom Script Connection (Settings >> Connect >> Custom Script).
The binary now auto-detects Sonarr/Radarr custom-script invocations:
sonarr_eventtype=Download or radarr_eventtype=Download triggers an
in-place transcode of the file referenced by the corresponding
$sonarr_episodefile_path / $radarr_moviefile_path environment variable.Test, Grab, Rename, etc.) exit cleanly
without requiring any CLI arguments..mp4 beside the
original file (which is removed once the conversion completes). Override this
by passing --servarr-output-extension match-input to keep the original
container or any custom extension (e.g. --servarr-output-extension mkv).Example Sonarr command:
/path/to/direct_play_nice --video-quality match-source --audio-quality match-source
Example Radarr command keeping the source container:
/path/to/direct_play_nice --servarr-output-extension match-input
Example Sonarr command that keeps all defaults (resulting in
Episode.fixed.mp4 after conversion):
/path/to/direct_play_nice
Tip: Sonarr/Radarr will see the new filename on their next library scan. If you convert to
.mp4, Plex/Jellyfin can immediately direct play the result.
Avoid the “Plex dance” by letting direct_play_nice trigger a targeted Plex
library refresh after a successful conversion. Supply a Plex token (and
optionally a custom server URL) via CLI flags or environment variables:
--plex-refresh enables the behaviour for the current invocation. It is also
activated automatically when both a Plex URL and token are provided through
environment variables.--plex-token <TOKEN> or DIRECT_PLAY_NICE_PLEX_TOKEN / PLEX_TOKEN
authenticate the refresh request.--plex-url <http://host:port> or DIRECT_PLAY_NICE_PLEX_URL override the
Plex base URL (defaults to http://127.0.0.1:32400).DIRECT_PLAY_NICE_PLEX_REFRESH=true in the environment to make automatic
refreshes the default for CLI runs.config.toml under
$XDG_CONFIG_HOME/direct-play-nice (fallback ~/.config/direct-play-nice) or
point at a custom file with either --config-file or the
DIRECT_PLAY_NICE_CONFIG environment variable.X-Plex-Token in their
support article.The tool looks up the Plex library section that contains the converted file and invokes the server’s refresh endpoint for that directory, eliminating the need to manually move files in and out of the library.
Example ~/.config/direct-play-nice/config.toml (remember to quote strings):
streaming_devices = ["all"]
video_quality = "match-source"
audio_quality = "match-source"
max_video_bitrate = "2M"
max_audio_bitrate = "160k"
hw_accel = "auto"
unsupported_video_policy = "ignore"
servarr_output_extension = "mp4"
servarr_output_suffix = ".fixed"
delete_source = false
[plex]
refresh = true
url = "http://localhost:32400"
token = "PLEX-TOKEN-HERE"
Only the [plex] section is consumed today; the top-level keys mirror CLI
flags so you can keep preferred defaults documented alongside your Plex
credentials.

By default the CLI preserves source quality for both video and audio. To shrink files ahead of Plex / Jellyfin direct play, mix and match:
--video-quality match-source|360p|480p|720p|1080p|1440p|2160p applies
intuitive resolution caps and matching H.264 bitrate ceilings. For example,
--video-quality 720p clamps to 1280×720 and ~5 Mbps, while
--video-quality 2160p scales to 3840×2160 at ~35 Mbps.--audio-quality match-source|320k|256k|224k|192k|160k|128k|96k sets AAC
bitrate ceilings to well-known streaming tiers (e.g. --audio-quality 192k
for a "standard" profile).--video-quality 4k, --video-quality full-hd, or
--audio-quality high map onto the presets above.Need something custom? Use --max-video-bitrate and/or --max-audio-bitrate to
override the presets with any value such as 4800k, 6M, or 12.5mbps.
This project relies on FFmpeg and rsmpeg and builds on Mac, Linux and Windows:
cargo install cargo-vcpkg
cargo vcpkg build
cargo build
After running cargo vcpkg build once, point VCPKG_ROOT at the shared
installation so builds and CI reuse the same FFmpeg toolchain (this repo
defaults to /opt/vcpkg on Unix and C:\\src\\vcpkg on Windows):
export VCPKG_ROOT=/opt/vcpkg
The repo defaults to /opt/vcpkg on Unix-like platforms and C:\\src\\vcpkg on
Windows; override this environment variable if your setup differs. Our
Cargo.toml pins vcpkg to commit 21012a516c9e5fa547baf212f2d937cd8d15dcb5
which includes FFmpeg 8—if you reuse an existing checkout, make sure it is
checked out to that revision:
# Windows PowerShell
git -C $env:VCPKG_ROOT fetch https://github.com/cqundefine/vcpkg.git
git -C $env:VCPKG_ROOT checkout 21012a516c9e5fa547baf212f2d937cd8d15dcb5
# macOS/Linux
git -C "$VCPKG_ROOT" fetch https://github.com/cqundefine/vcpkg.git
git -C "$VCPKG_ROOT" checkout 21012a516c9e5fa547baf212f2d937cd8d15dcb5
# Builds assume `/opt/vcpkg`; override VCPKG_ROOT if you keep vcpkg elsewhere.
# export VCPKG_ROOT=/opt/vcpkg
cargo test
End‑to‑end conversion tests that synthesize media require the ffmpeg CLI and
are marked #[ignore]. To run them explicitly:
VCPKG_ROOT=/opt/vcpkg cargo test -- --ignored
The NVENC matrix exercises the hardware encoder across multiple device/bitrate
profiles. Because it depends on NVIDIA hardware (with working h264_nvenc
support) it is opt-in. Enable it with:
ENABLE_NVENC_TESTS=1 cargo test nvenc_matrix -- --test-threads=1
The existing single-case NVENC integration test also participates when the same environment variable is set.
If you use direnv, add the following to .envrc so shells pick up the shared
vcpkg install:
export VCPKG_ROOT=/opt/vcpkg
export RUST_LOG=${RUST_LOG:-WARN}
Then run direnv allow once in the repo.
If you run into any issues while using this software or want to add a feature or bug fix feel free to raise an issue.