Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 4.9.0 #328

Merged
merged 47 commits into from
Apr 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
b898b05
* Fixing #272 Codec drop down size fix (thanks to kachijs)
cdgriffith Jan 9, 2022
e5ac3a6
Updating encoder icons to be square to fill in drop down better
cdgriffith Jan 10, 2022
e48bdd0
* Fixing #278 FastFlix occasionally getting stuck on a single video i…
cdgriffith Jan 19, 2022
c7e2572
Fix parsing of output with -psnr on and add 640k audio bitrate (#287)
ObviousInRetrospect Jan 20, 2022
1ae176f
* Adding Japanese, Portuguese, Russian, Swedish, and Polish translations
cdgriffith Jan 23, 2022
2aa3492
Fix pyinstaller inclusion of Cython files
cdgriffith Jan 23, 2022
d6af244
Merge remote-tracking branch 'origin/master' into develop
cdgriffith Feb 1, 2022
aab595a
* Fixing concat builder behavior to work smoother
cdgriffith Feb 3, 2022
7ad424a
Audio profile select (#298)
cdgriffith Mar 5, 2022
a7996a5
Adding new options to svtav1
cdgriffith Mar 7, 2022
f9f0743
Adding HDR10 support for svtav1
cdgriffith Mar 8, 2022
d707bf8
Adding OpenCL support for Remove HDR to speed it up
cdgriffith Mar 9, 2022
6fe53be
Fixing default audio profile select if no filters provided
cdgriffith Mar 9, 2022
da99e61
Fixing profile audio for sane selection and proper downmix
cdgriffith Mar 10, 2022
1ac4d35
Fixing SVT AV1 check for color space in command builder
cdgriffith Mar 10, 2022
d17d1cb
* Adding #294 NVEncC 10-bit encoding mode for 8-bit source (thanks to…
cdgriffith Mar 11, 2022
40c25c1
Merge remote-tracking branch 'origin/master' into develop
cdgriffith Mar 11, 2022
ae11015
* Fixing #304 New profile Audio conversion downmix and bitrate issues…
cdgriffith Mar 11, 2022
aca421d
Increasing profile window size and adding missing translations
cdgriffith Mar 11, 2022
9ca1f02
Merge remote-tracking branch 'origin/master' into develop
cdgriffith Mar 11, 2022
4af69e4
* Fixing that force 10-bit encoding for NVEencC was not set from prof…
cdgriffith Mar 11, 2022
ffbbc0e
* Adding #313 basic vsync support for hardware encoders (thanks to Wo…
cdgriffith Mar 26, 2022
9a2e67a
* Changing #292 back to PySide2 to be compatible with Windows 7 and 8…
cdgriffith Mar 26, 2022
2576252
Add logging for when we cant run ffmpeg
cdgriffith Mar 26, 2022
7930afc
Change all references of pyside6 to pyside2
cdgriffith Mar 26, 2022
6d04877
* Fixing #315 HDR10 info not parsed from subsequent video tracks than…
cdgriffith Mar 27, 2022
530d94c
* Adding #312 additional pixel formats for most encoders (thanks to O…
cdgriffith Mar 27, 2022
d9dfd07
Don't force use of 8-bit with x265 and remove HDR. Fix that "cfr" != …
cdgriffith Mar 27, 2022
4bca875
* Fixing #310 QT was complaining about some PNG formats (thanks to Do…
cdgriffith Mar 27, 2022
3380a86
Merge remote-tracking branch 'origin/master' into develop
cdgriffith Mar 27, 2022
3a5688c
* Fixing #315 HDR10 info not parsed from subsequent video tracks than…
cdgriffith Mar 28, 2022
0da60fc
Merge remote-tracking branch 'origin/master' into develop
cdgriffith Apr 1, 2022
65c146b
* Adding #196 Support for HEVC Apple Silicon M1 encoder (thanks to Ka…
cdgriffith Apr 2, 2022
46b2513
Adding support for h264 videotoolbox
cdgriffith Apr 13, 2022
fa0ff6e
Fix lint and test workflow
cdgriffith Apr 13, 2022
7217e08
Update formatting
cdgriffith Apr 13, 2022
d8a14e1
* Adding #323 ignore errors option for queue (thanks to Don Gafford)
cdgriffith Apr 13, 2022
f135e45
* Fixing #321 dhdr10_opt not added for x265 commands (thanks to Gizmo…
cdgriffith Apr 14, 2022
85ac417
* Fixing #324 NVEncC wrong Interlace Value set by FastFlix (thanks to…
cdgriffith Apr 14, 2022
60ff8d2
* Adding #109 Support for HEVC QSV encoding with rigaya's QSVEncC (th…
cdgriffith Apr 16, 2022
7aad67d
Small fixes and sanity runs done for QSVEncC
cdgriffith Apr 16, 2022
efea50a
* Adding support for intel AVC encoding
cdgriffith Apr 16, 2022
2c1c933
Trying out odd context manager
cdgriffith Apr 17, 2022
d4ce80c
Working new queue style
cdgriffith Apr 23, 2022
4a530ef
Adding manually save and load queue
cdgriffith Apr 24, 2022
ce69aec
* Fixing #330 "Remove Metadata" only removes video metadata for Rigay…
cdgriffith Apr 24, 2022
ee2e78b
* Adding #331 NVEncC API v10 Quality presets: P1 to P7 (thanks to Won…
cdgriffith Apr 24, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
path: ${{ env.pythonLocation }}
key: ${{ env.pythonLocation }}-black

- run: pip install black==21.8b0
- run: pip install black==22.3.0
- run: python -m black --check .

test:
Expand Down
9 changes: 3 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,12 @@ repos:
- id: check-toml
- id: detect-private-key
- id: end-of-file-fixer
# - repo: https://github.com/PyCQA/isort
# rev: master
# hooks:
# - id: isort
- repo: https://github.com/psf/black
rev: 21.8b0
rev: 22.3.0
hooks:
- id: black
# - repo: https://github.com/pre-commit/mirrors-mypy
# rev: 'v0.780'
# rev: 'v0.942'
# hooks:
# - id: mypy
# additional_dependencies: [types-pkg-resources, types-requests]
13 changes: 13 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## Version 4.9.0

* Adding #109 Support for AVC and HEVC QSV encoding with rigaya's QSVEncC (thanks to msaintauret)
* Adding #196 Support for AVC and HEVC Apple Videotoolbox encoder (thanks to Kay Singh)
* Adding #323 ignore errors options options for queue (thanks to Don Gafford)
* Adding #331 NVEncC API v10 Quality presets: P1 to P7 (thanks to Wontell)
* Fixing #321 dhdr10_opt not added for x265 commands (thanks to GizmoDudex)
* Fixing #327 FastFlix Duplicates encoding task and encodes same movie to infinity (thanks to Wontell)
* Fixing #324 NVEncC wrong Interlace Value set by FastFlix (thanks to Wontell)
* Fixing #278 FastFlix occasionally getting stuck on a single video in a queue (thanks to kamild1996)
* Fixing #330 "Remove Metadata" only removes video metadata for Rigaya's hardware encoders (thanks to wynterca)
* Fixing level was not being passed to hardware encoders

## Version 4.8.1

* Fixing #315 HDR10 info not parsed from subsequent video tracks than the first, again (thanks to msaintauret)
Expand Down
12 changes: 11 additions & 1 deletion fastflix/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,20 @@ def init_encoders(app: FastFlixApp, **_):
from fastflix.encoders.svt_av1 import main as svt_av1_plugin
from fastflix.encoders.vp9 import main as vp9_plugin
from fastflix.encoders.webp import main as webp_plugin
from fastflix.encoders.qsvencc_hevc import main as qsvencc_plugin
from fastflix.encoders.qsvencc_avc import main as qsvencc_avc_plugin
from fastflix.encoders.nvencc_hevc import main as nvencc_plugin
from fastflix.encoders.nvencc_avc import main as nvencc_avc_plugin
from fastflix.encoders.vceencc_hevc import main as vceencc_hevc_plugin
from fastflix.encoders.vceencc_avc import main as vceencc_avc_plugin
from fastflix.encoders.hevc_videotoolbox import main as hevc_videotoolbox_plugin
from fastflix.encoders.h264_videotoolbox import main as h264_videotoolbox_plugin

encoders = [
hevc_plugin,
nvenc_plugin,
hevc_videotoolbox_plugin,
h264_videotoolbox_plugin,
av1_plugin,
rav1e_plugin,
svt_av1_plugin,
Expand All @@ -78,9 +84,13 @@ def init_encoders(app: FastFlixApp, **_):
copy_plugin,
]

if app.fastflix.config.qsvencc:
encoders.insert(1, qsvencc_plugin)
encoders.insert(8, qsvencc_avc_plugin)

if app.fastflix.config.nvencc:
encoders.insert(1, nvencc_plugin)
encoders.insert(7, nvencc_avc_plugin)
encoders.insert(8, nvencc_avc_plugin)

if app.fastflix.config.vceencc:
if reusables.win_based:
Expand Down
186 changes: 29 additions & 157 deletions fastflix/conversion_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,14 @@
from fastflix.language import t
from fastflix.shared import file_date
from fastflix.models.video import Video
from fastflix.ff_queue import save_queue


logger = logging.getLogger("fastflix-core")

log_path = Path(user_data_dir("FastFlix", appauthor=False, roaming=True)) / "logs"
after_done_path = Path(user_data_dir("FastFlix", appauthor=False, roaming=True)) / "after_done_logs"

queue_path = Path(user_data_dir("FastFlix", appauthor=False, roaming=True)) / "queue.yaml"
queue_lock_file = Path(user_data_dir("FastFlix", appauthor=False, roaming=True)) / "queue.lock"


CONTINUOUS = 0x80000000
SYSTEM_REQUIRED = 0x00000001

Expand Down Expand Up @@ -53,91 +50,24 @@ 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]:
with queue_lock:
logger.debug(f"Retrieving next video from {queue_list}")
for video in queue_list:
if (
not video.status.complete
and not video.status.success
and not video.status.cancelled
and not video.status.error
and not video.status.running
):
logger.debug(f"Next video is {video.uuid} - {video.status}")
return video.copy()


def set_status(
current_video: Video,
queue_list,
queue_lock,
complete=None,
success=None,
cancelled=None,
errored=None,
running=None,
next_command=False,
reset_commands=False,
):
if not current_video:
return

with queue_lock:
for i, video in enumerate(queue_list):
if video.uuid == current_video.uuid:
video_pos = i
break
else:
logger.error(f"Can't find video {current_video.uuid} in queue to update its status: {queue_list}")
return

video_copy = queue_list.pop(video_pos)

if complete is not None:
video_copy.status.complete = complete
if cancelled is not None:
video_copy.status.cancelled = cancelled
if errored is not None:
video_copy.status.error = errored
if success is not None:
video_copy.status.success = success
if running is not None:
video_copy.status.running = running

if complete or cancelled or errored or success:
video_copy.status.running = False

if next_command:
video_copy.status.current_command += 1
if reset_commands:
video_copy.status.current_command = 0

queue_list.insert(video_pos, video_copy)


@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):
runner = BackgroundRunner(log_queue=log_queue)

# Command looks like (video_uuid, command_uuid, command, work_dir)
after_done_command = ""
gui_died = False
currently_encoding = False
paused = False
video: Optional[Video] = None
video_uuid = None
command_uuid = None
command = None
work_dir = None
log_name = ""

def start_command():
nonlocal currently_encoding
log_queue.put(
f"CLEAR_WINDOW:{video.uuid}:{video.video_settings.conversion_commands[video.status.current_command].uuid}"
)
log_queue.put(f"CLEAR_WINDOW:{video_uuid}:{command_uuid}")
reusables.remove_file_handlers(logger)
new_file_handler = reusables.get_file_handler(
log_path
/ sanitize_filename(
f"flix_conversion_{video.video_settings.video_title or video.video_settings.output_path.stem}_{file_date()}.log"
),
log_path / sanitize_filename(f"flix_conversion_{log_name}_{file_date()}.log"),
level=logging.DEBUG,
log_format="%(asctime)s - %(message)s",
encoding="utf-8",
Expand All @@ -146,67 +76,33 @@ def start_command():
prevent_sleep_mode()
currently_encoding = True
runner.start_exec(
video.video_settings.conversion_commands[video.status.current_command].command,
work_dir=str(video.work_path),
command,
work_dir=work_dir,
)
set_status(video, queue_list=queue_list, 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")
allow_sleep_mode()
currently_encoding = 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()
status_queue.put(("error", video_uuid, command_uuid))
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:
logger.debug("About to run next command for this video")
set_status(video, queue_list=queue_list, 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)
status_queue.put(("queue",))
video = None

if paused:
currently_encoding = False
allow_sleep_mode()
logger.debug(t("Queue has been paused"))
continue

if video := get_next_video(queue_list=queue_list, queue_lock=queue_lock):
start_command()
continue
else:
currently_encoding = False
allow_sleep_mode()
logger.info(t("all conversions complete"))
status_queue.put(("complete",))
if after_done_command:
logger.info(f"{t('Running after done command:')} {after_done_command}")
try:
runner.start_exec(after_done_command, str(after_done_path))
except Exception:
logger.exception("Error occurred while running after done command")
continue
status_queue.put(("complete", video_uuid, command_uuid))
if after_done_command:
logger.info(f"{t('Running after done command:')} {after_done_command}")
try:
runner.start_exec(after_done_command, str(after_done_path))
except Exception:
logger.exception("Error occurred while running after done command")
continue
if gui_died:
return

Expand All @@ -218,7 +114,6 @@ def start_command():
else:
logger.debug(t("Conversion worker shutting down"))
return

try:
request = worker_queue.get(block=True, timeout=0.05)
except Empty:
Expand All @@ -228,39 +123,19 @@ def start_command():
allow_sleep_mode()
return
else:
if request[0] == "add_items":

# 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)
if video:
start_command()
if request[0] == "execute":
_, video_uuid, command_uuid, command, work_dir, log_name = request
start_command()

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)
currently_encoding = False
allow_sleep_mode()
status_queue.put(("cancelled", video.uuid if video else ""))
status_queue.put(("cancelled", video_uuid, command_uuid))
log_queue.put("STOP_TIMER")
video = None

if request[0] == "pause queue":
logger.debug(t("Command worker received request to pause encoding after the current item completes"))
paused = True

if request[0] == "resume queue":
paused = False
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)
if video:
start_command()

if request[0] == "set after done":
after_done_command = request[1]
if after_done_command:
Expand All @@ -274,13 +149,10 @@ def start_command():
runner.pause()
except Exception:
logger.exception("Could not pause command")
else:
status_queue.put(("paused encode",))

if request[0] == "resume encode":
logger.debug(t("Command worker received request to resume paused encode"))
try:
runner.resume()
except Exception:
logger.exception("Could not resume command")
else:
status_queue.put(("resumed encode",))
Binary file added fastflix/data/encoders/icon_h264_toolbox.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fastflix/data/encoders/icon_hevc_toolbox.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fastflix/data/encoders/icon_qsvencc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading