saint-13 / Linux_Dynamic_Wallpapers

Dynamic Wallpapers for Linux
738 stars 61 forks source link

Support plasma5-wallpapers-dynamic #35

Open gurrgur opened 1 year ago

gurrgur commented 1 year ago

Currently the wallpapers from this repository cannot be used on KDE Plasma. There is a dynamic wallpaper plugin for KDE Plasma made by a major KWin contributor called plasma5-wallpapers-dynamic. Currently it only supports AVIF files rather than the xml + png/jpg approach used in gnome or HEIC from macos.

I made a python 3 script which, if run from the repository root, converts all wallpapers to AVIF by using kdynamicwallpaperbuilder.

While this essentially solves the compatibility problem, a major remaining problem is just how long the script takes to convert all wallpapers. For example, converting a single wallpaper with 8 6016x6016 images like Catalina took about 30-45 minutes on my Ryzen 3600 system with 16GB ram while completely hogging the CPU and using about 10GB of RAM.

The plasma5-wallpapers-dynamic README has the following note which is true indeed:

Note that encoding the dynamic wallpaper may take a lot of memory (AVIF encoders are very memory hungry) and time!

Therefore I'd like to use this issue to discuss how KDE Plasma/plasma5-wallpapers-dynamic support can be achieved in the most reasonable way. Personally I think the most reasonable option would be to run the conversion script once and readily provide the avif files as a separate release. Alternatively the avif files can be kept in a separate subdirectory in the main repository. However this would lead to larger download sizes when cloning the repository due to data duplication.

peterhoeg commented 1 year ago

How about a github action that runs the conversion when a new file is added? Alternatively, see if adding support for !avif to the plasma wallpaper plugin is an option.

eclipseo commented 2 months ago

Currently the wallpapers from this repository cannot be used on KDE Plasma. There is a dynamic wallpaper plugin for KDE Plasma made by a major KWin contributor called plasma5-wallpapers-dynamic. Currently it only supports AVIF files rather than the xml + png/jpg approach used in gnome or HEIC from macos.

I made a python 3 script which, if run from the repository root, converts all wallpapers to AVIF by using kdynamicwallpaperbuilder.

While this essentially solves the compatibility problem, a major remaining problem is just how long the script takes to convert all wallpapers. For example, converting a single wallpaper with 8 6016x6016 images like Catalina took about 30-45 minutes on my Ryzen 3600 systemh 16GB ram while completely hogging the CPU and using about 10GB of RAM.

The plasma5-wallpapers-dynamic README has the following note which is true indeed:

Note that encoding the dynamic wallpaper may take a lot of memory (AVIF encoders are very memory hungry) and time!

Therefore I'd like to use this issue to discuss how KDE Plasma/plasma5-wallpapers-dynamic support can be achieved in the most reasonable way. Personally I think the most reasonable option would be to run the conversion script once and readily provide the avif files as a separate release. Alternatively the avif files can be kept in a separate subdirectory in the main repository. However this would lead to larger download sizes when cloning the repository due to data duplication.

You should add the speed value and max-threads:

import xml.etree.ElementTree as ET
from pathlib import Path
from datetime import datetime, timedelta
import json
import multiprocessing
import subprocess

d = Path("Dynamic_Wallpapers")

for xmlfile in d.glob("*.xml"):

    f = xmlfile.name
    name = f.rsplit(".")[0]
    tree = ET.parse(d / f)
    root = tree.getroot()

    t = datetime(
        year=int(root.find("starttime").find("year").text),
        month=int(root.find("starttime").find("month").text),
        day=int(root.find("starttime").find("day").text),
        hour=int(root.find("starttime").find("hour").text),
        minute=int(root.find("starttime").find("minute").text),
        second=int(root.find("starttime").find("second").text),
    )

    sequence = []
    for c in root:
        if c.tag == "starttime":
            continue

        crossfade = c.tag == "transition"
        filename = c.find("from").text if crossfade else c.find("file").text
        sequence.append(
            {
                #"SolarAzimuth": "*",
                #"SolarElevation": "*",
                "CrossFade": crossfade,
                "Time": str(t.hour).zfill(2) + ":" + str(t.minute).zfill(2),
                "FileName": str(Path(name) / Path(filename).name)
            }
        )
        dt = timedelta(seconds=float(c.find("duration").text))
        t = t + dt

    manifest_data = {"Type": "solar", "Meta": sequence}
    manifest_file = d / (name + ".json")
    with open(manifest_file, "w") as m:
        json.dump(manifest_data, m, indent=4)

    out_dir = Path("avif")
    if not out_dir.is_dir():
        out_dir.mkdir()
    out_file = out_dir / (name + '.avif')

    cmd = [
        'kdynamicwallpaperbuilder',
        '--codec',
        'aom',
        '--max-threads',
        f'{multiprocessing.cpu_count() - 2}',
        '--speed',
        '6',
        '--output',
        f'./{out_file}',
        f'./{str(manifest_file)}',
    ]

    if not out_file.is_file():
        print("starting subprocess:", cmd)
        subprocess.run(cmd)
    else:
        print("skip:", cmd)