Skip to content

Commit

Permalink
feat: Add environment variable support for disabling spinner and logg…
Browse files Browse the repository at this point in the history
…ing interval in rendering processes

- Introduced `DISABLE_SPINNER` and `LOG_INTERVAL` environment variables to control spinner visibility and logging frequency during rendering.
- Updated `receive_stdout` and `render_jobs` methods to utilize these new configurations, enhancing user control over rendering output.
- Improved logging behavior to provide more informative output when the spinner is disabled.
  • Loading branch information
HaiyiMei committed Dec 23, 2024
1 parent 1406e87 commit 394af2a
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 15 deletions.
15 changes: 12 additions & 3 deletions xrfeitoria/renderer/renderer_base.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import os
from abc import ABC, abstractmethod
from functools import wraps
from typing import List

from loguru import logger
from rich import get_console

# Get environment variable for spinner disable, defaulting to False if not set
DISABLE_SPINNER = os.environ.get('XRFEITORIA__DISABLE_SPINNER', '').lower() in ('true', '1', 'yes')


# decorator
def render_status(func):
Expand All @@ -13,10 +17,15 @@ def render_status(func):

@wraps(func)
def wrapper(*args, **kwargs):
with console.status('[bold green]:rocket: Rendering...[/bold green]'):
if DISABLE_SPINNER:
ret = func(*args, **kwargs)
logger.info('[bold green]:white_check_mark: Rendering done![/bold green]')
return ret
logger.info('[bold green]:white_check_mark: Rendering done![/bold green]')
return ret
else:
with console.status('[bold green]:rocket: Rendering...[/bold green]'):
ret = func(*args, **kwargs)
logger.info('[bold green]:white_check_mark: Rendering done![/bold green]')
return ret

return wrapper

Expand Down
69 changes: 57 additions & 12 deletions xrfeitoria/renderer/renderer_blender.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import os
import re
import shutil
import subprocess
Expand All @@ -23,6 +24,9 @@
from ..utils.functions import blender_functions
from .renderer_base import RendererBase, render_status

DISABLE_SPINNER = os.environ.get('XRFEITORIA__DISABLE_SPINNER', '').lower() in ('true', '1', 'yes')
LOG_INTERVAL = int(os.environ.get('XRFEITORIA__LOG_INTERVAL', '10'))

try:
# linting and for engine
from XRFeitoriaBpy.core.factory import XRFeitoriaBlenderFactory # defined in src/XRFeitoriaBpy/core/factory.py
Expand All @@ -37,16 +41,25 @@


def receive_stdout(
process: subprocess.Popen, in_background: bool, frame_range: Tuple[int, int], job_idx: Optional[int] = None
process: subprocess.Popen,
in_background: bool,
frame_range: Tuple[int, int],
job_idx: Optional[int] = None,
refresh_per_second: int = 1,
disable_spinner: bool = DISABLE_SPINNER,
log_interval: int = LOG_INTERVAL,
) -> None:
"""Receive output from the subprocess, and update the spinner.
Args:
process (subprocess.Popen): Subprocess of the blender process.
frame_range (Tuple[int, int]): Frame range of the rendering job.
job_range (Tuple[int, int]): Job range of all jobs in render queue.
disable_spinner (bool, optional): If True, the spinner will be disabled. Defaults to environment variable XRFEITORIA__DISABLE_SPINNER (False).
log_interval (int, optional): Log progress every N frames. Defaults to environment variable XRFEITORIA__LOG_INTERVAL (10).
"""
from rich import get_console
from rich.live import Live
from rich.spinner import Spinner

frame_count = 0
Expand All @@ -55,13 +68,23 @@ def receive_stdout(
job_info = f' {job_idx}' if job_idx else ''

console = get_console()
# TODO: change to progress bar
try:
spinner: Spinner = console._live.renderable
except AttributeError:
status = console.status('[bold green]:rocket: Rendering...[/bold green]')
status.start()
spinner: Spinner = status.renderable
spinner = None
live = None

if not disable_spinner:
# TODO: change to progress bar
try:
spinner: Spinner = console._live.renderable
# Update the refresh rate of existing live display
console._live.refresh_per_second = refresh_per_second
except AttributeError:
# Create new spinner with custom refresh rate
spinner = Spinner('dots', '[bold green]:rocket: Rendering...[/bold green]')
live = Live(spinner, refresh_per_second=refresh_per_second)
live.start()
spinner = live.renderable
else:
logger.warning(f'Spinner disabled, instead logging every {log_interval} frames')

# init
__frame_current__ = frame_current
Expand Down Expand Up @@ -93,8 +116,12 @@ def receive_stdout(
if frame_count > frame_length:
break
text = f'[bold green]:rocket: Rendering Job{job_info}: frame {frame_count}/{frame_length}[/bold green]'
spinner.update(text=text)
logger.debug(f'(XF-Rendering) Job{job_info}: frame {frame_count}/{frame_length}')
if spinner:
spinner.update(text=text)
if disable_spinner and (frame_count % log_interval == 0 or frame_count == frame_length):
logger.info(text)
else:
logger.debug(text)
# reset
first_trigger = second_trigger = False
else:
Expand All @@ -115,8 +142,13 @@ def receive_stdout(
if frame_count > frame_length:
break
text = f'[bold green]:rocket: Rendering Job{job_info}: frame {frame_count}/{frame_length}[/bold green]'
spinner.update(text=text)
if spinner:
spinner.update(text=text)
# Always log debug
logger.debug(f'(XF-Rendering) Job{job_info}: frame {frame_count}/{frame_length}')
# When spinner is disabled, also log info at intervals
if disable_spinner and (frame_count % log_interval == 0 or frame_count == frame_length):
logger.info(f'(XF-Rendering) Job{job_info}: frame {frame_count}/{frame_length}')
# reset
first_trigger = second_trigger = False

Expand Down Expand Up @@ -171,12 +203,23 @@ def add_job(

@classmethod
@render_status
def render_jobs(cls, use_gpu: bool = True) -> None:
def render_jobs(
cls,
use_gpu: bool = True,
disable_spinner: bool = DISABLE_SPINNER,
log_interval: int = LOG_INTERVAL,
) -> None:
"""Render all jobs in the render queue, and this method will clear the render
queue after rendering.
Args:
use_gpu (bool, optional): Use GPU to render. Defaults to True.
disable_spinner (bool, optional): If True, the spinner will be disabled. Defaults to environment variable XRFEITORIA__DISABLE_SPINNER or False.
The Spinner is a progress bar to show the rendering progress in the console.
If you are using a container, you may want to set this to True.
You can also set this via environment variable XRFEITORIA__DISABLE_SPINNER=true.
log_interval (int, optional): Log progress every N frames. Defaults to environment variable XRFEITORIA__LOG_INTERVAL or 10.
You can also set this via environment variable XRFEITORIA__LOG_INTERVAL=20.
"""
if len(cls.render_queue) == 0:
logger.warning(
Expand Down Expand Up @@ -226,6 +269,8 @@ def render_jobs(cls, use_gpu: bool = True) -> None:
'in_background': in_background,
'frame_range': blender_functions.get_frame_range(),
'job_idx': job_idx + 1,
'disable_spinner': disable_spinner,
'log_interval': log_interval,
},
)
output_thread.start()
Expand Down

0 comments on commit 394af2a

Please sign in to comment.