Compare commits

..

1 Commits

Author SHA1 Message Date
773c2f8ea8 checkMetadata: support WebM containers 2025-08-26 16:39:18 +02:00
2 changed files with 37 additions and 99 deletions

View File

@ -27,7 +27,7 @@ class MediaFile:
duration: int #in sec duration: int #in sec
def supported_file_extension(filename): def supported_file_extension(filename):
if filename.endswith('.mp4') or filename.endswith('.mkv') or filename.endswith('.m4v'): if filename.endswith('.mp4') or filename.endswith('.mkv') or filename.endswith('.webm') or filename.endswith('.m4v'):
return True return True
return False return False

View File

@ -8,81 +8,34 @@ import sys
from pathlib import Path from pathlib import Path
PROM_URL = "http://127.0.0.1:9104/metrics" PROM_URL = "http://127.0.0.1:9104/metrics"
MIN_SOC = 0.5 # 50%
MIN_SOLAR_POWER = 500 # 500W
def load_config(path): def load_config(path):
"""Load JSON configuration file.""" """Load JSON configuration file."""
with open(path, "r", encoding="utf-8") as f: with open(path, "r", encoding="utf-8") as f:
return json.load(f) return json.load(f)
import requests def wait_for_solar_power():
import time
def wait_for_solar_power(prom_url, check_interval=300, max_retries=None):
""" """
Wait until: Wait until the Prometheus metric `fronius_site_autonomy_ratio` equals 1.0.
- fronius_site_power_photovoltaic > 500 Check every 5 minutes if not available.
- fronius_inverter_soc{inverter="1"} > 0.5
Args:
prom_url (str): Prometheus metrics endpoint.
check_interval (int): Seconds between checks (default: 300).
max_retries (int or None): Optional limit on checks. If None, loop indefinitely.
Returns:
bool: True if conditions met, False if retries exhausted.
""" """
attempts = 0
while True: while True:
try: try:
r = requests.get(prom_url, timeout=5) r = requests.get(PROM_URL, timeout=5)
r.raise_for_status() if r.status_code == 200:
for line in r.text.splitlines():
pv_power = None if line.startswith("fronius_site_autonomy_ratio"):
inverter_soc = None try:
value = float(line.split()[-1])
for line in r.text.splitlines(): if value == 1.0:
if line.startswith("#"): # Skip comments and HELP/TYPE lines print("[INFO] Solar power available starting conversion.")
continue return
parts = line.split() except ValueError:
if len(parts) != 2: pass
continue print("[INFO] No solar power waiting 5 minutes...")
metric, value_str = parts
try:
value = float(value_str)
except ValueError:
continue
if metric == "fronius_site_power_photovoltaic":
pv_power = value
elif (
metric.startswith("fronius_inverter_soc")
and '{inverter="1"}' in metric
):
inverter_soc = value
if pv_power is not None and inverter_soc is not None:
if pv_power > MIN_SOLAR_POWER and inverter_soc > MIN_SOC:
print(
f"[INFO] Solar power available: PV={pv_power:.2f} W, SOC={inverter_soc:.2f} starting conversion."
)
return True
print(
f"[INFO] Conditions not met (PV={pv_power}, SOC={inverter_soc}). Waiting {check_interval} seconds..."
)
except requests.RequestException as e: except requests.RequestException as e:
print(f"[WARN] Could not reach Prometheus: {e}") print(f"[WARN] Could not reach Prometheus: {e}")
time.sleep(300) # Wait 5 minutes
attempts += 1
if max_retries is not None and attempts >= max_retries:
print("[ERROR] Max retries reached. Exiting without solar power.")
return False
time.sleep(check_interval)
def analyze_codecs(oldfile, newfile, dst_folder): def analyze_codecs(oldfile, newfile, dst_folder):
""" """
@ -106,7 +59,7 @@ def main():
if len(sys.argv) != 2: if len(sys.argv) != 2:
print("Give path to config file as argument.") print("Give path to config file as argument.")
sys.exit(1) sys.exit(1)
cfg = load_config(sys.argv[1]) cfg = load_config(sys.argv[1])
dst_folder = Path(cfg["dst_folder"]) dst_folder = Path(cfg["dst_folder"])
src_folder = Path(cfg["src_folder"]) src_folder = Path(cfg["src_folder"])
@ -123,52 +76,36 @@ def main():
print(f"Source: {src_file}") print(f"Source: {src_file}")
print(f"Temp name: {tmp_movie_name}") print(f"Temp name: {tmp_movie_name}")
print(f"Final name: {movie_name}") print(f"Final name: {movie_name}")
# Remove leftover temporary file # Remove leftover temporary file
if tmp_dst_file.exists(): if tmp_dst_file.exists():
print(f"[INFO] File {tmp_dst_file} already exists. --> Delete!") print(f"[INFO] File {tmp_dst_file} already exists. --> Delete!")
tmp_dst_file.unlink() tmp_dst_file.unlink()
# Skip if final file already exists # Skip if final file already exists
if dst_file.exists(): if dst_file.exists():
print(f"[INFO] Skip {dst_file}, already exists. --> Convert already done!") print(f"[INFO] Skip {dst_file}, already exists. --> Convert already done!")
continue continue
wait_for_solar_power(PROM_URL) wait_for_solar_power()
try: try:
cmd = [ cmd = [
"taskset", "taskset", "-c", "0,1,2,3", # limit to first 4 CPU cores
"-c", "ffmpeg", "-i", str(src_file),
"0,1,2,3", # limit to first 4 CPU cores "-c:v", "libaom-av1",
"ffmpeg", "-c:a", "libopus",
"-i", "-mapping_family", "1",
str(src_file), "-af", "aformat=channel_layouts=5.1",
"-c:v", "-c:s", "copy",
"libaom-av1", "-map", "0",
"-c:a", "-crf", "24",
"libopus", "-b:v", "0",
"-mapping_family", "-b:a", "128k",
"1", "-cpu-used", "4",
"-af", "-row-mt", "1",
"aformat=channel_layouts=5.1", "-tiles", "2x2",
"-c:s", str(tmp_dst_file)
"copy",
"-map",
"0",
"-crf",
"24",
"-b:v",
"0",
"-b:a",
"128k",
"-cpu-used",
"4",
"-row-mt",
"1",
"-tiles",
"2x2",
str(tmp_dst_file),
] ]
print(f"[CMD] {' '.join(cmd)}") print(f"[CMD] {' '.join(cmd)}")
subprocess.run(cmd, check=True) subprocess.run(cmd, check=True)
@ -181,6 +118,7 @@ def main():
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
print(f"[ERROR] Processing failed for {job}: {e}") print(f"[ERROR] Processing failed for {job}: {e}")
if __name__ == "__main__": if __name__ == "__main__":
main() main()