chore: update script to make use of video generation instead of the old python scripts

This commit is contained in:
Almamu 2025-05-10 06:20:13 +02:00
parent cc2ae06f64
commit 3a77e291a2
6 changed files with 33 additions and 199 deletions

View File

@ -276,6 +276,7 @@ CApplicationContext::CApplicationContext (int argc, char* argv []) :
#if DEMOMODE #if DEMOMODE
sLog.error ("WARNING: RUNNING IN DEMO MODE WILL STOP WALLPAPERS AFTER 5 SECONDS SO VIDEO CAN BE RECORDED"); sLog.error ("WARNING: RUNNING IN DEMO MODE WILL STOP WALLPAPERS AFTER 5 SECONDS SO VIDEO CAN BE RECORDED");
// special settings for demomode // special settings for demomode
this->settings.render.maximumFPS = 30;
this->settings.screenshot.take = false; this->settings.screenshot.take = false;
this->settings.render.pauseOnFullscreen = false; this->settings.render.pauseOnFullscreen = false;
#endif /* DEMOMODE */ #endif /* DEMOMODE */

View File

@ -404,8 +404,9 @@ void CWallpaperApplication::show () {
int width = this->m_renderContext->getWallpapers ().begin ()->second->getWidth (); int width = this->m_renderContext->getWallpapers ().begin ()->second->getWidth ();
int height = this->m_renderContext->getWallpapers ().begin ()->second->getHeight (); int height = this->m_renderContext->getWallpapers ().begin ()->second->getHeight ();
std::vector<uint8_t> pixels(width * height * 3); std::vector<uint8_t> pixels(width * height * 3);
init_encoder ("output.webm", width, height); bool initialized = false;
int frame = 0; int frame = 0;
int elapsed_frames = 0;
#endif /* DEMOMODE */ #endif /* DEMOMODE */
while (this->m_context.state.general.keepRunning) { while (this->m_context.state.general.keepRunning) {
@ -431,8 +432,20 @@ void CWallpaperApplication::show () {
} }
#if DEMOMODE #if DEMOMODE
// do not record frames unless a second has passed elapsed_frames ++;
if (g_Time > 1) {
// wait for a full render cycle before actually starting
// this gives some extra time for video and web decoders to set themselves up
// because of size changes
if (elapsed_frames > this->m_context.settings.render.maximumFPS) {
if (!initialized) {
width = this->m_renderContext->getWallpapers ().begin ()->second->getWidth ();
height = this->m_renderContext->getWallpapers ().begin ()->second->getHeight ();
pixels.reserve(width * height * 3);
init_encoder ("output.webm", width, height);
initialized = true;
}
glBindFramebuffer (GL_FRAMEBUFFER, this->m_renderContext->getWallpapers ().begin ()->second->getWallpaperFramebuffer()); glBindFramebuffer (GL_FRAMEBUFFER, this->m_renderContext->getWallpapers ().begin ()->second->getWallpaperFramebuffer());
glPixelStorei (GL_PACK_ALIGNMENT, 1); glPixelStorei (GL_PACK_ALIGNMENT, 1);

View File

@ -20,7 +20,7 @@ extern "C" {
} }
const int FPS = 30; const int FPS = 30;
const int FRAME_COUNT = 150; const int FRAME_COUNT = FPS * 5;
int WIDTH = 0; int WIDTH = 0;
int HEIGHT = 0; int HEIGHT = 0;
int SOURCE_WIDTH = 0; int SOURCE_WIDTH = 0;

View File

@ -3,10 +3,21 @@ if [ $# -eq 0 ]
then then
echo "Please provide the current build's executable path. You might want to run this script off the same folder." echo "Please provide the current build's executable path. You might want to run this script off the same folder."
fi fi
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# ensure the output and images directory exists # ensure the output and images directory exists
[ -d "output" ] || mkdir output [ -d "output" ] || mkdir output
[ -d "images" ] || mkdir images
python ${SCRIPT_DIR}/scripts/run.py $1 ~/.steam/steam/steamapps/workshop/content/431960/ for folder in ~/.steam/steam/steamapps/workshop/content/431960/*; do
python ${SCRIPT_DIR}/scripts/process.py # only directories matter
if [ -d "$folder" ]; then
bgid=$(basename "$folder")
echo "Running wallpaperengine for background $bgid and waiting for it to finish"
# run and wait for it to finish
$1 $bgid
# move output.webm to the output folder with the right name
mv output.webm output/$bgid.webm
# take a screenshot
ffmpeg -ss 00:00:03 -i output/$bgid.webm -frames:v 1 output/$bgid.jpg
fi
done

View File

@ -1,94 +0,0 @@
import os
import re
import base64
import cv2
import numpy as np
from bs4 import BeautifulSoup
def extract_base64_image(html_file):
"""Extracts base64-encoded image data from an HTML file."""
with open(html_file, "r", encoding="utf-8") as f:
soup = BeautifulSoup(f, "html.parser")
img_tag = soup.find("img")
if img_tag and 'src' in img_tag.attrs:
match = re.search(r'data:image/png;base64,(.+)', img_tag['src'])
if match:
return match.group(1)
return None
def resize_image_base64(image_data, width=100):
"""Resizes the image to the specified width while keeping aspect ratio and returns base64."""
img_array = np.frombuffer(base64.b64decode(image_data), dtype=np.uint8)
img = cv2.imdecode(img_array, cv2.IMREAD_UNCHANGED)
if img is None:
return None
h, w = img.shape[:2]
new_height = int((width / w) * h)
resized_img = cv2.resize(img, (width, new_height), interpolation=cv2.INTER_AREA)
_, buffer = cv2.imencode('.png', resized_img)
resized_base64 = base64.b64encode(buffer).decode('utf-8')
return resized_base64
def categorize_image(image_data):
"""Categorizes the image as 'grey', 'no image', or 'content' and returns resized image."""
if not image_data:
return "no_image", None
img_array = np.frombuffer(base64.b64decode(image_data), dtype=np.uint8)
img = cv2.imdecode(img_array, cv2.IMREAD_GRAYSCALE)
if img is None:
return "no_image", None
mean_value = cv2.mean(img)[0]
std_dev = np.std(img)
category = "grey" if mean_value > 200 and std_dev < 10 else "content"
resized_data = resize_image_base64(image_data)
return category, resized_data
def process_html_files(input_folder, output_html="gallery.html"):
"""Processes all HTML files, categorizes them, and generates a gallery."""
categories = {"no_image": [], "grey": [], "content": []}
for file in os.listdir(input_folder):
if file.endswith(".html") and not file.startswith('report'):
file_path = os.path.join(input_folder, file)
image_data = extract_base64_image(file_path)
category, resized_image = categorize_image(image_data)
categories[category].append((file, resized_image))
with open(output_html, "w", encoding="utf-8") as f:
f.write("""
<html>
<head>
<title>Image Gallery</title>
<style>
.gallery { display: flex; flex-wrap: wrap; }
.thumb { margin: 10px; text-align: center; }
img { border: 1px solid black; }
</style>
</head>
<body>
<h1>Image Gallery</h1>
""")
for category, files in categories.items():
f.write(f"<h2>{category.replace('_', ' ').title()}</h2>")
f.write("<div class='gallery'>")
for file_name, img_data in files:
if img_data:
f.write(f"<div class='thumb'><a href='{file_name}'><img src='data:image/png;base64,{img_data}'></a></div>")
else:
f.write(f"<div class='thumb'><a href='{file_name}'>[No Image]</a></div>")
f.write("</div>")
f.write("</body></html>")
print(f"Gallery created at {output_html}")
if __name__ == "__main__":
input_folder = "./output" # Change to your directory
process_html_files(input_folder, "output/gallery.html")

View File

@ -1,97 +0,0 @@
import subprocess
import os
import time
import html
import base64
import argparse
import signal
def run_and_monitor(program, program_args=None, output_file="output.png", wait_time=1, timeout=30, html_report="report.html"):
try:
# Build the full command
full_command = [program] + ([program_args] if program_args else [])
print(f"Running command: {' '.join(full_command)}")
# Start the program with shell=True for better compatibility
process = subprocess.Popen(
f"exec {" ".join(full_command)}", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, preexec_fn=os.setsid
)
stdout_data, stderr_data = "", ""
start_time = time.time()
while time.time() - start_time < timeout:
# wait for the process to die, if it did, stop the waiting already
try:
process.wait(wait_time)
break
except subprocess.TimeoutExpired:
# otherwise check for the file, if it exists stop waiting
print("Polling for file {output_file}".format(output_file=output_file))
# Check if the file is created
if os.path.exists(output_file):
# give the screenshot some time to be written properly, just in case
time.sleep(wait_time)
break
else:
print("Timeout reached. File not found.")
# Capture output
if process.poll() is None:
os.killpg(os.getpgid(process.pid), signal.SIGKILL)
stdout_data, stderr_data = process.communicate()
# Read the created image file as base64
image_base64 = ""
if os.path.exists(output_file):
with open(output_file, "rb") as f:
image_base64 = base64.b64encode(f.read()).decode('utf-8')
# Save results to an HTML file
with open(os.path.join("output", html_report), "w", encoding="utf-8") as report:
report.write("""
<html>
<head><title>Program Output Review</title></head>
<body>
<h1>Generated Image</h1>
<img src='data:image/png;base64,{image_base64}' alt='Generated Image'/>
<h1>Standard Output</h1>
<pre>{stdout_data}</pre>
<h1>Error Output</h1>
<pre>{stderr_data}</pre>
</body>
</html>
""".format(
image_base64=image_base64,
stdout_data=html.escape(stdout_data),
stderr_data=html.escape(stderr_data)
))
print(f"Report saved to {html_report}")
if stderr_data:
print("Error output detected:")
print(stderr_data)
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Run a program, monitor a file, and capture output.")
parser.add_argument("program", help="The program to execute.")
parser.add_argument("directory", help="Directory containing folders to process.")
args = parser.parse_args()
if not os.path.isdir(args.directory):
print("Error: Specified directory does not exist.")
exit(1)
folders = [f for f in os.listdir(args.directory) if os.path.isdir(os.path.join(args.directory, f))]
for folder in folders:
run_and_monitor(
args.program,
program_args="--screenshot {path}/images/{folder}.png --screenshot-delay 420 {folder}".format(path=os.getcwd(), folder=folder),
output_file="{path}/images/{folder}.png".format(path=os.getcwd(), folder=folder),
html_report="{folder}.html".format(folder=folder)
)