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

Beta Release 4.2.0b0 #199

Merged
merged 55 commits into from
Feb 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
4728787
Beta Version 4.1.1b0 (#175)
cdgriffith Jan 13, 2021
6215654
version bump
cdgriffith Jan 13, 2021
4af781c
Merge remote-tracking branch 'origin/master' into develop
cdgriffith Jan 13, 2021
6866bc3
* Adding #178 selector for number of autocrop positions throughout vi…
cdgriffith Jan 13, 2021
272f98c
* Fixing #180 Minor UI glitch, custom bitrate retains "k" when edited…
cdgriffith Jan 14, 2021
d444889
* Adding ability to extract HDR10+ metadata
cdgriffith Jan 14, 2021
122d1d7
Merge remote-tracking branch 'origin/develop' into feature/crop-detec…
cdgriffith Jan 15, 2021
f113bd5
* Adding Windows 10 toast style notification for queue complete success
cdgriffith Jan 27, 2021
3152b96
Merge remote-tracking branch 'origin/develop' into feature/crop-detec…
cdgriffith Jan 27, 2021
011e360
* Adding canceled message and cleaning up partial download of FFmpeg …
cdgriffith Jan 27, 2021
6f54210
Starting to add nvenc encoder
cdgriffith Jan 27, 2021
4b0f50e
Cleanup
cdgriffith Jan 27, 2021
625f63a
* Fixing #190 add missing chromaloc parameter for x265 (thanks to Etz)
cdgriffith Jan 27, 2021
0a0d67c
better logic to find hdr10plus_parser and mkvpropedit
cdgriffith Jan 27, 2021
20d0888
* Adding #109 NVENC HEVC support based on FFmpeg
cdgriffith Jan 27, 2021
f3651a8
* Adding NVEenC initial trial for HEVC
cdgriffith Jan 28, 2021
64c7eb0
figuring out start of audio for nvencc
cdgriffith Jan 28, 2021
f0229d9
internal improvements
cdgriffith Jan 28, 2021
8c36fe7
Fixing imports that are windows only
cdgriffith Jan 29, 2021
3b14a78
Fixing imports that are windows only
cdgriffith Jan 29, 2021
2c4c88b
Merge remote-tracking branch 'origin/develop' into feature/file-queue
cdgriffith Jan 30, 2021
c410f66
* Adding #194 fast two pass encoding (thanks to Ugurtan)
cdgriffith Jan 30, 2021
2d3b8ea
even more options for nvencc
cdgriffith Jan 30, 2021
5f654b0
adding warning for nvencc encode settings
cdgriffith Jan 30, 2021
d8cf08a
queue ideas
cdgriffith Jan 30, 2021
6dedb74
some fixes, some queue stuff
cdgriffith Jan 31, 2021
868ede4
some fixes, some queue stuff
cdgriffith Jan 31, 2021
3ff65e5
fixing hdr10 extraction with multiple video tracks (does not work for…
cdgriffith Jan 31, 2021
1d7877f
showing progress for hdr10 extraction. Making sure UPX is not used. S…
cdgriffith Feb 2, 2021
8909bd4
first actual almost working queue as a file
cdgriffith Feb 2, 2021
87bb1d9
adding retry button
cdgriffith Feb 2, 2021
8eb3472
* Fixing HDR10 details to be track specific (thanks to Harybo)
cdgriffith Feb 2, 2021
250a4be
* Fixing HDR10 details to be track specific (thanks to Harybo)
cdgriffith Feb 2, 2021
cc21d73
properly disabling dups for NVEncC
cdgriffith Feb 2, 2021
1deb68c
random updates
cdgriffith Feb 3, 2021
17bf9d7
more language additions
cdgriffith Feb 3, 2021
b521bbf
stuff
cdgriffith Feb 3, 2021
2c39876
more fixes
cdgriffith Feb 3, 2021
8aaba50
* Adding #166 More robust queue that is recoverable
cdgriffith Feb 3, 2021
9d6989f
Adding resets for main page items, slider for picking thumbnail time
cdgriffith Feb 3, 2021
4ae2e50
* Fixing queue up / down buttons
cdgriffith Feb 4, 2021
588702c
Fixing sending back from queue for correct track
cdgriffith Feb 4, 2021
6d9e9a1
lots of small fixes
cdgriffith Feb 5, 2021
ce3a36c
queue stuff totally different
cdgriffith Feb 7, 2021
333fe8f
more queue updates
cdgriffith Feb 7, 2021
d451c8f
fixing profile not setting encoder in drop down
cdgriffith Feb 7, 2021
517db7c
adding language support for missing items
cdgriffith Feb 7, 2021
1b1d780
fixing return to queue mode select
cdgriffith Feb 7, 2021
d87fcf3
Adding NVENCC AVC
cdgriffith Feb 8, 2021
6028ea2
Fix timer signal
cdgriffith Feb 8, 2021
f478705
Safer paths
cdgriffith Feb 10, 2021
9b429b3
rotation fixes for NvencC
cdgriffith Feb 11, 2021
d59111e
* Fixing #171 Be able to select encoder before selecting video
cdgriffith Feb 13, 2021
c3b21e8
adding missing languages
cdgriffith Feb 13, 2021
b605653
Fixing nvenc AVC build command
cdgriffith Feb 14, 2021
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
4 changes: 3 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
## Version 4.2.0

* Adding #109 NVENC HEVC support based on FFmpeg
* Adding NVEenC encoder for HEVC
* Adding NVEenC encoder for HEVC and AVC
* Adding #166 More robust queue that is recoverable
* Adding ability to extract HDR10+ metadata if hdr10plus_parser is detected on path
* Adding #178 selector for number of autocrop positions throughout video (thanks to bmcassagne)
* Adding Windows 10 notification for queue complete success
* Adding #194 fast two pass encoding (thanks to Ugurtan)
* Fixing German translations (thanks to SMESH)
* Fixing #171 Be able to select encoder before selecting video
* Fixing #176 Unable to change queue order or delete task from queue since 4.1.0 (thanks to Etz)
* Fixing #185 need to specify channel layout when downmixing (thanks to Ugurtan)
* Fixing #187 cleaning up partial download of FFmpeg (thanks to Todd Wilkinson)
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ FastFlix (v4.0.2+) passes through HLG color transfer information to everything e

FastFlix does not plan to support Dolby Vision's proprietary format at this time.

# Support FastFlix

Check out the different ways you can help [support FastFlix](https://github.com/cdgriffith/FastFlix/wiki/Support-FastFlix)!

# License

Expand Down
6 changes: 4 additions & 2 deletions fastflix/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def init_encoders(app: FastFlixApp, **_):
from fastflix.encoders.vp9 import main as vp9_plugin
from fastflix.encoders.webp import main as webp_plugin
from fastflix.encoders.nvencc_hevc import main as nvencc_plugin
from fastflix.encoders.nvencc_avc import main as nvencc_avc_plugin

encoders = [
hevc_plugin,
Expand All @@ -72,6 +73,7 @@ def init_encoders(app: FastFlixApp, **_):

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

app.fastflix.encoders = {
encoder.name: encoder
Expand Down Expand Up @@ -100,9 +102,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):
def start_app(worker_queue, status_queue, log_queue, queue_list, queue_lock):
app = create_app()
app.fastflix = FastFlix()
app.fastflix = FastFlix(queue=queue_list, queue_lock=queue_lock)
app.fastflix.log_queue = log_queue
app.fastflix.status_queue = status_queue
app.fastflix.worker_queue = worker_queue
Expand Down
119 changes: 68 additions & 51 deletions fastflix/conversion_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@
from pathlib import Path
from queue import Empty
from typing import Optional
from multiprocessing import Manager, Lock

import reusables
from appdirs import user_data_dir
from box import Box
from pathvalidate import sanitize_filename

from fastflix.command_runner import BackgroundRunner
from fastflix.language import t
from fastflix.shared import file_date
from fastflix.models.queue import get_queue, save_queue
from fastflix.models.video import Video


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

log_path = Path(user_data_dir("FastFlix", appauthor=False, roaming=True)) / "logs"
Expand Down Expand Up @@ -52,22 +55,25 @@ def allow_sleep_mode():
logger.debug("System has been allowed to enter sleep mode again")


def get_next_video() -> Optional[Video]:
queue = get_queue()
for video in queue:
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
):
return video
def get_next_video(queue_list, queue_lock) -> Optional[Video]:
with queue_lock:
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,
completed=None,
current_video: Video,
queue_list,
queue_lock,
complete=None,
success=None,
cancelled=None,
errored=None,
Expand All @@ -77,36 +83,42 @@ def set_status(
):
if not current_video:
return
queue = get_queue()
for video in queue:
if video.uuid == current_video.uuid:
if completed is not None:
video.status.complete = completed
if cancelled is not None:
video.status.cancelled = cancelled
if errored is not None:
video.status.error = errored
if success is not None:
video.status.success = success
if running is not None:
video.status.running = running

if completed or cancelled or errored or success:
video.status.running = False

if next_command:
video.status.current_command += 1
if reset_commands:
video.status.current_command = 0
break
else:
logger.error(f"Could not find video in queue to update status of!\n {current_video}")
return
save_queue(queue)

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):
def queue_worker(gui_proc, worker_queue, status_queue, log_queue, queue_list, queue_lock: Lock):
runner = BackgroundRunner(log_queue=log_queue)

# Command looks like (video_uuid, command_uuid, command, work_dir)
Expand All @@ -119,12 +131,14 @@ def queue_worker(gui_proc, worker_queue, status_queue, log_queue):
def start_command():
nonlocal currently_encoding
log_queue.put(
f"CLEAR_WINDOW:{video.uuid}:{video.video_settings.conversion_commands[video.status.current_command]['uuid']}"
f"CLEAR_WINDOW:{video.uuid}:{video.video_settings.conversion_commands[video.status.current_command].uuid}"
)
reusables.remove_file_handlers(logger)
new_file_handler = reusables.get_file_handler(
log_path
/ f"flix_conversion_{video.video_settings.video_title or video.video_settings.output_path.stem}_{file_date()}.log",
/ sanitize_filename(
f"flix_conversion_{video.video_settings.video_title or video.video_settings.output_path.stem}_{file_date()}.log"
),
level=logging.DEBUG,
log_format="%(asctime)s - %(message)s",
encoding="utf-8",
Expand All @@ -133,10 +147,10 @@ def start_command():
prevent_sleep_mode()
currently_encoding = True
runner.start_exec(
video.video_settings.conversion_commands[video.status.current_command]["command"],
video.video_settings.conversion_commands[video.status.current_command].command,
work_dir=str(video.work_path),
)
set_status(video, running=True)
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()))
Expand All @@ -149,7 +163,7 @@ def start_command():

# Stop working!
currently_encoding = False
set_status(video, errored=True)
set_status(video, queue_list=queue_list, queue_lock=queue_lock, errored=True)
status_queue.put(("error",))
allow_sleep_mode()
if gui_died:
Expand All @@ -159,15 +173,17 @@ def start_command():
# 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, next_command=True)
set_status(video, queue_list=queue_list, queue_lock=queue_lock, next_command=True)
status_queue.put(("queue",))
start_command()
continue
else:
set_status(video, next_command=True, completed=True)
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

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

if video := get_next_video():
if video := get_next_video(queue_list=queue_list, queue_lock=queue_lock):
start_command()
continue
else:
Expand Down Expand Up @@ -218,18 +234,19 @@ 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()
video = get_next_video(queue_list=queue_list, queue_lock=queue_lock)
if video:
start_command()

if request[0] == "cancel":
logger.debug(t("Cancel has been requested, killing encoding"))
runner.kill()
if video:
set_status(video, reset_commands=True, cancelled=True)
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 ""))
log_queue.put("STOP_TIMER")

if request[0] == "pause queue":
logger.debug(t("Command worker received request to pause encoding after the current item completes"))
Expand All @@ -240,7 +257,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()
video = get_next_video(queue_list=queue_list, queue_lock=queue_lock)
start_command()

if request[0] == "set after done":
Expand Down
Loading