fix: streamline UI, remove borders, fix tab navigation, add VAAPI AV1

This commit is contained in:
fiatcode 2026-02-28 09:28:35 +07:00
parent ce8288ca7a
commit a099e944c2
2 changed files with 178 additions and 53 deletions

View file

@ -36,9 +36,6 @@ class PathInput(Input):
if not current: if not current:
return return
event.prevent_default()
event.stop()
path = os.path.expanduser(current) path = os.path.expanduser(current)
matches = glob.glob(path + "*") matches = glob.glob(path + "*")
@ -47,6 +44,8 @@ class PathInput(Input):
if not matches: if not matches:
self.value = current + "/" self.value = current + "/"
self.cursor_position = len(self.value) self.cursor_position = len(self.value)
event.prevent_default()
event.stop()
return return
if not matches: if not matches:
@ -65,6 +64,8 @@ class PathInput(Input):
if match != current: if match != current:
self.value = match self.value = match
self.cursor_position = len(self.value) self.cursor_position = len(self.value)
event.prevent_default()
event.stop()
LOGO = r""" LOGO = r"""
@ -86,48 +87,27 @@ class WelcomeScreen(Screen):
} }
#app-container { #app-container {
width: 60; width: 50;
height: auto; height: auto;
padding: 1 2; padding: 1 2;
} }
#logo { #logo {
text-align: center;
color: $accent; color: $accent;
text-style: bold; text-style: bold;
margin-bottom: 2; margin-bottom: 2;
width: auto;
}
.form-row {
height: 3;
align: left middle;
margin-bottom: 1;
}
.form-label {
width: 16;
content-align: right middle;
margin-right: 1;
color: $text-muted;
}
#video-input {
width: 1fr;
}
#interval-input {
width: 10;
}
#button-container {
width: 100%; width: 100%;
align: center middle; }
margin-top: 1;
height: 3; .form-input {
margin-bottom: 1;
width: 100%;
} }
#start-btn { #start-btn {
min-width: 16; width: 100%;
margin-top: 1;
} }
#error-label { #error-label {
@ -143,28 +123,24 @@ class WelcomeScreen(Screen):
with Center(): with Center():
with Middle(): with Middle():
with Vertical(id="app-container"): with Vertical(id="app-container"):
with Center(): yield Label("PyFaceBlur", id="logo")
yield Label("PyFaceBlur", id="logo")
with Horizontal(classes="form-row"): yield PathInput(
yield Label("Video file:", classes="form-label") placeholder="Path to video file...",
yield PathInput( id="video-input",
placeholder="Enter path to video...", classes="form-input",
id="video-input", )
)
with Horizontal(classes="form-row"): yield Input(
yield Label("Frame interval:", classes="form-label") value="30",
yield Input( placeholder="Frame interval (default 30)",
value="30", id="interval-input",
id="interval-input", type="integer",
type="integer", classes="form-input",
) )
yield Label("", id="error-label") yield Label("", id="error-label")
yield Button("Start Processing", id="start-btn", variant="primary")
with Horizontal(id="button-container"):
yield Button("Start", id="start-btn", variant="primary")
def on_button_pressed(self, event: Button.Pressed) -> None: def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.id == "start-btn": if event.button.id == "start-btn":
@ -708,7 +684,6 @@ class PyFaceBlurApp(App):
CSS = """ CSS = """
Screen { Screen {
background: $surface; background: $surface;
border: heavy $accent;
padding: 1 2; padding: 1 2;
} }
""" """

View file

@ -106,7 +106,7 @@ def find_best_encoder() -> Tuple[str, List[str], List[str]]:
"-f", "-f",
"lavfi", "lavfi",
"-i", "-i",
"nullsrc=s=64x64:d=0.1", "nullsrc=s=1280x720:d=0.1",
"-c:v", "-c:v",
"h264_nvenc", "h264_nvenc",
"-f", "-f",
@ -116,6 +116,156 @@ def find_best_encoder() -> Tuple[str, List[str], List[str]]:
if subprocess.run(cmd, capture_output=True, timeout=5).returncode == 0: if subprocess.run(cmd, capture_output=True, timeout=5).returncode == 0:
return "h264_nvenc", [], [] return "h264_nvenc", [], []
# 2. Linux VA-API (AV1)
cmd = [
"ffmpeg",
"-v",
"quiet",
"-vaapi_device",
"/dev/dri/renderD128",
"-f",
"lavfi",
"-i",
"nullsrc=s=1280x720:d=0.1",
"-vf",
"format=nv12,hwupload",
"-c:v",
"av1_vaapi",
"-f",
"null",
"-",
]
if subprocess.run(cmd, capture_output=True, timeout=5).returncode == 0:
return (
"av1_vaapi",
["-vaapi_device", "/dev/dri/renderD128"],
["-vf", "format=nv12,hwupload"],
)
# 3. Linux VA-API (HEVC/H.265)
cmd = [
"ffmpeg",
"-v",
"quiet",
"-vaapi_device",
"/dev/dri/renderD128",
"-f",
"lavfi",
"-i",
"nullsrc=s=1280x720:d=0.1",
"-vf",
"format=nv12,hwupload",
"-c:v",
"hevc_vaapi",
"-f",
"null",
"-",
]
if subprocess.run(cmd, capture_output=True, timeout=5).returncode == 0:
return (
"hevc_vaapi",
["-vaapi_device", "/dev/dri/renderD128"],
["-vf", "format=nv12,hwupload"],
)
# 4. Linux VA-API (H.264)
cmd = [
"ffmpeg",
"-v",
"quiet",
"-vaapi_device",
"/dev/dri/renderD128",
"-f",
"lavfi",
"-i",
"nullsrc=s=1280x720:d=0.1",
"-vf",
"format=nv12,hwupload",
"-c:v",
"h264_vaapi",
"-f",
"null",
"-",
]
if subprocess.run(cmd, capture_output=True, timeout=5).returncode == 0:
return (
"h264_vaapi",
["-vaapi_device", "/dev/dri/renderD128"],
["-vf", "format=nv12,hwupload"],
)
# 5. AMD AMF (Windows/Proprietary Linux)
cmd = [
"ffmpeg",
"-v",
"quiet",
"-f",
"lavfi",
"-i",
"nullsrc=s=1280x720:d=0.1",
"-c:v",
"h264_amf",
"-f",
"null",
"-",
]
if subprocess.run(cmd, capture_output=True, timeout=5).returncode == 0:
return "h264_amf", [], []
# 6. Intel QSV
cmd = [
"ffmpeg",
"-v",
"quiet",
"-f",
"lavfi",
"-i",
"nullsrc=s=1280x720:d=0.1",
"-c:v",
"h264_qsv",
"-f",
"null",
"-",
]
if subprocess.run(cmd, capture_output=True, timeout=5).returncode == 0:
return "h264_qsv", [], []
# 7. Software fallback (libx264 if installed)
cmd = [
"ffmpeg",
"-v",
"quiet",
"-f",
"lavfi",
"-i",
"nullsrc=s=1280x720:d=0.1",
"-c:v",
"libx264",
"-f",
"null",
"-",
]
if subprocess.run(cmd, capture_output=True, timeout=5).returncode == 0:
return "libx264", [], []
# 8. Software fallback (libopenh264)
cmd = [
"ffmpeg",
"-v",
"quiet",
"-f",
"lavfi",
"-i",
"nullsrc=s=1280x720:d=0.1",
"-c:v",
"libopenh264",
"-f",
"null",
"-",
]
if subprocess.run(cmd, capture_output=True, timeout=5).returncode == 0:
return "h264_nvenc", [], []
# 2. Linux VA-API (AV1) # 2. Linux VA-API (AV1)
cmd = [ cmd = [
"ffmpeg", "ffmpeg",