Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion plugins/multiview/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Plugin configuration and field definitions for Dispatcharr Multiview."""

import datetime
import glob
import json
import os
import secrets
Expand Down Expand Up @@ -134,6 +135,31 @@ def _register_presets(encoder: str, fields_fn):
return


def _render_device_field() -> dict:
"""Render-device override for QSV/VAAPI, populated from detected DRM nodes.

Auto (the default) preserves the historic behavior of picking the first
/dev/dri/renderD* node. In a VM or container with multiple render nodes the
first one can be the wrong GPU, so the user can pin a specific node here.
Options are globbed on the host at field-build time, so both the native
Dispatcharr settings page and the web dashboard list the real nodes.
"""
devices = sorted(glob.glob("/dev/dri/render*"))
options = [{"value": "auto", "label": "Auto (first detected)"}]
options += [{"value": d, "label": d} for d in devices]
return {
"id": "render_device",
"label": "Render Device",
"type": "select",
"default": "auto",
"options": options,
"description": (
"GPU render node for QSV/VAAPI. Auto picks the first detected; "
"override if you have multiple GPUs."
),
}


def _x264_fields() -> list:
return [
{
Expand Down Expand Up @@ -189,11 +215,12 @@ def _qsv_fields() -> list:
],
"description": "QSV encode speed vs quality. Medium is recommended for live multiview.",
},
_render_device_field(),
]


def _vaapi_fields() -> list:
return []
return [_render_device_field()]


_ENCODER_EXTRA_FIELDS = {
Expand Down

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/multiview/dash/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<link rel="icon" type="image/png" href="./logo.png" />
<link rel="manifest" href="./manifest.json" />
<title>Multiview</title>
<script type="module" crossorigin src="./assets/index-D909_1-I.js"></script>
<script type="module" crossorigin src="./assets/index-C4ShuQoB.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-BHGMNXvw.css">
</head>
<body>
Expand Down
9 changes: 6 additions & 3 deletions plugins/multiview/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ def fps_fraction(fps: str) -> Fraction:
return Fraction(int(fps), 1)


def _find_dri_device() -> str:
def _find_dri_device(override: str = "") -> str:
if override and override != "auto":
return override
devices = sorted(glob.glob("/dev/dri/render*"))
return devices[0] if devices else "/dev/dri/renderD128"

Expand Down Expand Up @@ -60,14 +62,15 @@ def build_encoder_cmd(cfg, out_w, out_h, audio_read) -> list:
gop = max(2, round(float(fps_fraction(cfg["fps"])) * 2))
encoder = cfg.get("video_encoder", "libx264")
preset = resolve_preset(encoder, cfg.get("preset"))
render_device = cfg.get("render_device", "")

cmd = ["ffmpeg", "-hide_banner", "-loglevel", "error"]

# Hardware device init must precede inputs.
if encoder == "h264_vaapi":
cmd += ["-vaapi_device", _find_dri_device()]
cmd += ["-vaapi_device", _find_dri_device(render_device)]
elif encoder == "h264_qsv":
cmd += ["-init_hw_device", f"qsv=hw:{_find_dri_device()}", "-filter_hw_device", "hw"]
cmd += ["-init_hw_device", f"qsv=hw:{_find_dri_device(render_device)}", "-filter_hw_device", "hw"]

# Cap muxer/filter threads so it doesn't grab every core and starve
# the PyAV decoders (3x 1080p60 decode already loads the box).
Expand Down
2 changes: 1 addition & 1 deletion plugins/multiview/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Tile multiple Dispatcharr channel streams into multi-view outputs using FFmpeg",
"author": "sethwv",

"version": "0.4.1",
"version": "0.4.2",
"min_dispatcharr_version": "v0.27.0",

"discord_thread": "https://discord.com/channels/1340492560220684331/1509200002407465001",
Expand Down
1 change: 1 addition & 0 deletions plugins/multiview/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ def _worker_config(self, tiles, layout, audio_source, settings) -> dict:
"bitrate": int(settings.get("output_bitrate") or 8000),
"preset": preset,
"video_encoder": encoder,
"render_device": settings.get("render_device") or "auto",
"background": background,
"tiles": tile_cfg,
}
Expand Down
Loading