Skip to content

Commit

Permalink
* Adding #323 ignore errors option for queue (thanks to Don Gafford)
Browse files Browse the repository at this point in the history
  • Loading branch information
cdgriffith committed Apr 14, 2022
1 parent 7217e08 commit d8a14e1
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 91 deletions.
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Version 4.9.0

* Adding #196 Support for HEVC Apple Silicon M1 encoder (thanks to Kay Singh)
* Adding #323 ignore errors options options for queue (thanks to Don Gafford)

## Version 4.8.1

Expand Down
4 changes: 2 additions & 2 deletions fastflix/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ def register_app():
logger.exception("Could not set application ID for Windows, please raise issue in github with above error")


def start_app(worker_queue, status_queue, log_queue, queue_list, queue_lock):
def start_app(worker_queue, status_queue, log_queue, queue_lock):
app = create_app()
app.fastflix = FastFlix(queue=queue_list, queue_lock=queue_lock)
app.fastflix = FastFlix(queue_lock=queue_lock)
app.fastflix.log_queue = log_queue
app.fastflix.status_queue = status_queue
app.fastflix.worker_queue = worker_queue
Expand Down
59 changes: 39 additions & 20 deletions fastflix/conversion_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from fastflix.language import t
from fastflix.shared import file_date
from fastflix.models.video import Video
from fastflix.ff_queue import save_queue, get_queue


logger = logging.getLogger("fastflix-core")
Expand Down Expand Up @@ -53,9 +54,11 @@ def allow_sleep_mode():
logger.debug("System has been allowed to enter sleep mode again")


def get_next_video(queue_list, queue_lock) -> Optional[Video]:
def get_next_video(queue_lock) -> Optional[Video]:
with queue_lock:
logger.debug(f"Retrieving next video from {queue_list}")
logger.debug(f"Retrieving next video from {queue_path}")
queue_list = get_queue(queue_file=queue_path)

for video in queue_list:
if (
not video.status.complete
Expand All @@ -70,7 +73,6 @@ def get_next_video(queue_list, queue_lock) -> Optional[Video]:

def set_status(
current_video: Video,
queue_list,
queue_lock,
complete=None,
success=None,
Expand All @@ -84,6 +86,7 @@ def set_status(
return

with queue_lock:
queue_list = get_queue(queue_file=queue_path)
for i, video in enumerate(queue_list):
if video.uuid == current_video.uuid:
video_pos = i
Expand Down Expand Up @@ -113,11 +116,14 @@ def set_status(
if reset_commands:
video_copy.status.current_command = 0

logger.debug(f"Set status of {current_video.uuid} to {video_copy.status}")
queue_list.insert(video_pos, video_copy)

save_queue(queue_list, queue_path)


@reusables.log_exception(log="fastflix-core")
def queue_worker(gui_proc, worker_queue, status_queue, log_queue, queue_list, queue_lock: Lock):
def queue_worker(gui_proc, worker_queue, status_queue, log_queue, queue_lock: Lock):
runner = BackgroundRunner(log_queue=log_queue)

# Command looks like (video_uuid, command_uuid, command, work_dir)
Expand All @@ -126,6 +132,7 @@ def queue_worker(gui_proc, worker_queue, status_queue, log_queue, queue_list, qu
currently_encoding = False
paused = False
video: Optional[Video] = None
ignore_errors = False

def start_command():
nonlocal currently_encoding
Expand All @@ -149,40 +156,45 @@ def start_command():
video.video_settings.conversion_commands[video.status.current_command].command,
work_dir=str(video.work_path),
)
set_status(video, queue_list=queue_list, queue_lock=queue_lock, running=True)
set_status(video, queue_lock=queue_lock, running=True)
status_queue.put(("queue",))

# status_queue.put(("running", commands_to_run[0][0], commands_to_run[0][1], runner.started_at.isoformat()))

while True:
if currently_encoding and not runner.is_alive():
reusables.remove_file_handlers(logger)
log_queue.put("STOP_TIMER")
skip_commands = False

if runner.error_detected:
logger.info(t("Error detected while converting"))

# Stop working!
currently_encoding = False
set_status(video, queue_list=queue_list, queue_lock=queue_lock, errored=True)
status_queue.put(("error",))
allow_sleep_mode()
if gui_died:
return
continue
set_status(video, queue_lock=queue_lock, errored=True)
if ignore_errors:
skip_commands = True
else:
# Stop working!
status_queue.put(("error",))
allow_sleep_mode()
if gui_died:
return
continue

# Successfully encoded, do next one if it exists
# First check if the current video has more commands
video.status.current_command += 1
log_queue.put("STOP_TIMER")

if len(video.video_settings.conversion_commands) > video.status.current_command:
if not skip_commands and len(video.video_settings.conversion_commands) > video.status.current_command:
logger.debug("About to run next command for this video")
set_status(video, queue_list=queue_list, queue_lock=queue_lock, next_command=True)
set_status(video, queue_lock=queue_lock, next_command=True)
status_queue.put(("queue",))
start_command()
continue
else:
logger.debug(f"{video.uuid} has been completed")
set_status(video, queue_list=queue_list, queue_lock=queue_lock, next_command=True, complete=True)
set_status(video, queue_lock=queue_lock, next_command=True, complete=True)
status_queue.put(("queue",))
video = None

Expand All @@ -192,7 +204,7 @@ def start_command():
logger.debug(t("Queue has been paused"))
continue

if video := get_next_video(queue_list=queue_list, queue_lock=queue_lock):
if video := get_next_video(queue_lock=queue_lock):
start_command()
continue
else:
Expand Down Expand Up @@ -233,15 +245,22 @@ def start_command():
# Request looks like (queue command, log_dir, (commands))
log_path = Path(request[1])
if not currently_encoding and not paused:
video = get_next_video(queue_list=queue_list, queue_lock=queue_lock)
video = get_next_video(queue_lock=queue_lock)
if video:
start_command()

if request[0] == "ignore error":
logger.info("Have been told to ignore errors")
ignore_errors = True
if request[0] == "stop on error":
logger.info("Have been told to stop on errors")
ignore_errors = False

if request[0] == "cancel":
logger.debug(t("Cancel has been requested, killing encoding"))
runner.kill()
if video:
set_status(video, queue_list=queue_list, queue_lock=queue_lock, reset_commands=True, cancelled=True)
set_status(video, queue_lock=queue_lock, reset_commands=True, cancelled=True)
currently_encoding = False
allow_sleep_mode()
status_queue.put(("cancelled", video.uuid if video else ""))
Expand All @@ -257,7 +276,7 @@ def start_command():
logger.debug(t("Command worker received request to resume encoding"))
if not currently_encoding:
if not video:
video = get_next_video(queue_list=queue_list, queue_lock=queue_lock)
video = get_next_video(queue_lock=queue_lock)
if video:
start_command()

Expand Down
12 changes: 12 additions & 0 deletions fastflix/data/languages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6262,3 +6262,15 @@ HEVC coding profile - must match bit depth:
por: Perfil de codificação HEVC - deve corresponder à profundidade do bit
swe: HEVC-kodningsprofil - måste matcha bitdjupet
pol: Profil kodowania HEVC - musi być zgodny z głębią bitową
Ignore Errors:
eng: Ignore Errors
deu: Fehler ignorieren
fra: Ignorer les erreurs
ita: Ignorare gli errori
spa: Ignorar errores
zho: 忽略错误
jpn: エラーを無視する
rus: Игнорировать ошибки
por: Ignorar erros
swe: Ignorera fel
pol: Ignoruj błędy
8 changes: 4 additions & 4 deletions fastflix/entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@
sys.exit(1)


def separate_app_process(worker_queue, status_queue, log_queue, queue_list, queue_lock):
def separate_app_process(worker_queue, status_queue, log_queue, queue_lock):
"""This prevents any QT components being imported in the main process"""
from fastflix.application import start_app

freeze_support()
try:
start_app(worker_queue, status_queue, log_queue, queue_list, queue_lock)
start_app(worker_queue, status_queue, log_queue, queue_lock)
except Exception as err:
print(f"Could not start GUI process - Error: {err}", file=sys.stderr)
raise err
Expand Down Expand Up @@ -128,15 +128,15 @@ def main():
try:
gui_proc = Process(
target=separate_app_process,
args=(worker_queue, status_queue, log_queue, queue_list, queue_lock),
args=(worker_queue, status_queue, log_queue, queue_lock),
)
gui_proc.start()
except Exception:
logger.exception("Could not create GUI Process, please report this error!")
return exit_status

try:
queue_worker(gui_proc, worker_queue, status_queue, log_queue, queue_list, queue_lock)
queue_worker(gui_proc, worker_queue, status_queue, log_queue, queue_lock)
exit_status = 0
except Exception:
logger.exception("Exception occurred while running FastFlix core")
Expand Down
60 changes: 33 additions & 27 deletions fastflix/ff_queue.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from typing import List
from typing import List, Optional
import os
from pathlib import Path
import logging
Expand All @@ -17,7 +17,7 @@
logger = logging.getLogger("fastflix")


def get_queue(queue_file: Path, config: Config) -> List[Video]:
def get_queue(queue_file: Path) -> List[Video]:
if not queue_file.exists():
return []

Expand Down Expand Up @@ -68,12 +68,17 @@ def get_queue(queue_file: Path, config: Config) -> List[Video]:
return queue


def save_queue(queue: List[Video], queue_file: Path, config: Config):
def save_queue(queue: List[Video], queue_file: Path, config: Optional[Config] = None):
items = []
queue_covers = config.work_path / "covers"
queue_covers.mkdir(parents=True, exist_ok=True)
queue_data = config.work_path / "queue_extras"
queue_data.mkdir(parents=True, exist_ok=True)

if config is not None:
queue_covers = config.work_path / "covers"
queue_covers.mkdir(parents=True, exist_ok=True)
queue_data = config.work_path / "queue_extras"
queue_data.mkdir(parents=True, exist_ok=True)
else:
queue_data = Path()
queue_covers = Path()

def update_conversion_command(vid, old_path: str, new_path: str):
for command in vid["video_settings"]["conversion_commands"]:
Expand All @@ -87,28 +92,29 @@ def update_conversion_command(vid, old_path: str, new_path: str):
video["source"] = os.fspath(video["source"])
video["work_path"] = os.fspath(video["work_path"])
video["video_settings"]["output_path"] = os.fspath(video["video_settings"]["output_path"])
if metadata := video["video_settings"]["video_encoder_settings"].get("hdr10plus_metadata"):
new_metadata_file = queue_data / f"{uuid.uuid4().hex}_metadata.json"
try:
shutil.copy(metadata, new_metadata_file)
except OSError:
logger.exception("Could not save HDR10+ metadata file to queue recovery location, removing HDR10+")

update_conversion_command(
video,
str(metadata),
str(new_metadata_file),
)
video["video_settings"]["video_encoder_settings"]["hdr10plus_metadata"] = str(new_metadata_file)
for track in video["video_settings"]["attachment_tracks"]:
if track.get("file_path"):
new_file = queue_covers / f'{uuid.uuid4().hex}_{track["file_path"].name}'
if config:
if metadata := video["video_settings"]["video_encoder_settings"].get("hdr10plus_metadata"):
new_metadata_file = queue_data / f"{uuid.uuid4().hex}_metadata.json"
try:
shutil.copy(track["file_path"], new_file)
shutil.copy(metadata, new_metadata_file)
except OSError:
logger.exception("Could not save cover to queue recovery location, removing cover")
update_conversion_command(video, str(track["file_path"]), str(new_file))
track["file_path"] = str(new_file)
logger.exception("Could not save HDR10+ metadata file to queue recovery location, removing HDR10+")

update_conversion_command(
video,
str(metadata),
str(new_metadata_file),
)
video["video_settings"]["video_encoder_settings"]["hdr10plus_metadata"] = str(new_metadata_file)
for track in video["video_settings"]["attachment_tracks"]:
if track.get("file_path"):
new_file = queue_covers / f'{uuid.uuid4().hex}_{track["file_path"].name}'
try:
shutil.copy(track["file_path"], new_file)
except OSError:
logger.exception("Could not save cover to queue recovery location, removing cover")
update_conversion_command(video, str(track["file_path"]), str(new_file))
track["file_path"] = str(new_file)

items.append(video)
try:
Expand Down
1 change: 0 additions & 1 deletion fastflix/models/fastflix.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,4 @@ class FastFlix(BaseModel):
log_queue: Any = None

current_video: Optional[Video] = None
queue: Any = None
queue_lock: Any = None
Loading

0 comments on commit d8a14e1

Please sign in to comment.