fix: streamline UI, remove borders, fix tab navigation, add VAAPI AV1
This commit is contained in:
parent
ce8288ca7a
commit
a099e944c2
2 changed files with 178 additions and 53 deletions
|
|
@ -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 Label("Video file:", classes="form-label")
|
|
||||||
yield PathInput(
|
yield PathInput(
|
||||||
placeholder="Enter path to video...",
|
placeholder="Path to video file...",
|
||||||
id="video-input",
|
id="video-input",
|
||||||
|
classes="form-input",
|
||||||
)
|
)
|
||||||
|
|
||||||
with Horizontal(classes="form-row"):
|
|
||||||
yield Label("Frame interval:", classes="form-label")
|
|
||||||
yield Input(
|
yield Input(
|
||||||
value="30",
|
value="30",
|
||||||
|
placeholder="Frame interval (default 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;
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue