Progress bar beeps now work on ffmpeg output.
This commit is contained in:
@@ -117,7 +117,7 @@ class command:
|
||||
|
||||
has_percentage = re.search(r"(^|\s)\d+(?:\.\d+)?\s*%", text)
|
||||
if not has_percentage:
|
||||
return False
|
||||
return self.has_progress_status_fields(text)
|
||||
|
||||
return bool(
|
||||
re.search(
|
||||
@@ -240,8 +240,20 @@ class command:
|
||||
pacman_match = re.search(
|
||||
r"\d+(?:\.\d+)?\s+[kKmMgGtT]iB\s+\d+(?:\.\d+)?\s+[kKmMgGtT]iB/s\s+\d+:\d+", text
|
||||
)
|
||||
# Pattern 1g: Key/value status lines from ffmpeg-like terminal tools.
|
||||
# These do not expose a percentage in the status line, so treat them as
|
||||
# activity rather than guessing progress from elapsed time.
|
||||
status_fields_match = self.has_progress_status_fields(text)
|
||||
|
||||
if time_match or token_match or dd_match or curl_match or transfer_match or pacman_match:
|
||||
if (
|
||||
time_match
|
||||
or token_match
|
||||
or dd_match
|
||||
or curl_match
|
||||
or transfer_match
|
||||
or pacman_match
|
||||
or status_fields_match
|
||||
):
|
||||
# For non-percentage progress, use a single activity beep every 2
|
||||
# seconds
|
||||
if (
|
||||
@@ -577,5 +589,48 @@ class command:
|
||||
return True
|
||||
return False
|
||||
|
||||
def has_progress_status_fields(self, text):
|
||||
"""Recognize dense key=value status lines from terminal tools."""
|
||||
import re
|
||||
|
||||
if "\n" in text or self.contains_url(text):
|
||||
return False
|
||||
|
||||
fields = re.findall(r"\b([a-zA-Z][a-zA-Z0-9_-]*)=\s*\S+", text)
|
||||
if len(fields) < 3:
|
||||
return False
|
||||
|
||||
field_names = {field.lower() for field in fields}
|
||||
progress_fields = {
|
||||
"frame",
|
||||
"fps",
|
||||
"size",
|
||||
"time",
|
||||
"bitrate",
|
||||
"speed",
|
||||
"elapsed",
|
||||
"dup",
|
||||
"drop",
|
||||
}
|
||||
if len(field_names & progress_fields) < 3:
|
||||
return False
|
||||
|
||||
has_time_field = bool(
|
||||
re.search(
|
||||
r"\b(?:time|elapsed|eta)=\s*\d+(?::\d{2}){1,2}(?:\.\d+)?\b",
|
||||
text,
|
||||
re.IGNORECASE,
|
||||
)
|
||||
)
|
||||
has_rate_field = bool(
|
||||
re.search(
|
||||
r"\b(?:speed|fps|bitrate)=\s*[\d.]+[a-zA-Z/]*\b",
|
||||
text,
|
||||
re.IGNORECASE,
|
||||
)
|
||||
)
|
||||
|
||||
return has_time_field and has_rate_field
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributors.
|
||||
|
||||
version = "2026.06.27"
|
||||
version = "2026.07.12"
|
||||
code_name = "testing"
|
||||
|
||||
Reference in New Issue
Block a user