Skip to content

Commit

Permalink
* Fixing #567 Profiles for WebP did not work (nor GIF dither) (thanks…
Browse files Browse the repository at this point in the history
… to jpert)

* Fixing #582 BT.2020-10 Color transfer not maintained #582 (thanks to Ryushin)
  • Loading branch information
cdgriffith committed Aug 7, 2024
1 parent c884dfd commit bd14e52
Show file tree
Hide file tree
Showing 26 changed files with 261 additions and 186 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
* Fixing #185 audio channels not being set properly and resetting on encoder change (thanks to Tupsi)
* Fixing #522 add file fails - fixed as of 5.7.0 (thanks to pcl5x2008)
* Fixing #531 list limitation in readme that FFmpeg must support the software encoders listed (thanks to brunoais)
* Fixing #567 Profiles for WebP did not work (nor GIF dither) (thanks to jpert)
* Fixing #582 BT.2020-10 Color transfer not maintained #582 (thanks to Ryushin)
* Fixing #585 error when trying to return a video from queue that has the video track after audio or subtitiles (thanks to Hankuu)
* Fixing #586 audio channels being set incorrectly (thanks to Hankuu)
* Fixing #588 audio and subtitle dispositions were not set from source (thanks to GeZorTenPlotZ)
Expand Down
45 changes: 0 additions & 45 deletions fastflix/data/languages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8696,51 +8696,6 @@ Bitrate Mode:
ukr: Режим бітрейту
kor: 비트레이트 모드
ron: Mod Bitrate
VCEEncC AV1 Encoder is untested!:
eng: VCEEncC AV1 Encoder is untested!
deu: VCEEncC AV1 Encoder ist ungetestet!
fra: VCEEncC AV1 Encoder n'est pas testé !
ita: VCEEncC AV1 Encoder non è stato testato!
spa: El codificador VCEEncC AV1 no ha sido probado.
chs: VCEEncC AV1编码器未经测试!
jpn: VCEEncC AV1エンコーダは未検証です!
rus: VCEEncC AV1 Encoder не тестировался!
por: O codificador VCEEncC AV1 não foi testado!
swe: VCEEncC AV1 Encoder är otestad!
pol: VCEEncC AV1 Encoder nie jest testowany!
ukr: Кодер VCEEncC AV1 неперевірений!
kor: VCEEncC AV1 인코더는 테스트되지 않았습니다!
ron: VCEEncC AV1 Encoder nu a fost testat!
QSVEncC AV1 Encoder is untested!:
eng: QSVEncC AV1 Encoder is untested!
deu: QSVEncC AV1 Encoder ist ungetestet!
fra: QSVEncC AV1 Encoder n'est pas testé !
ita: Il codificatore QSVEncC AV1 non è stato testato!
spa: El codificador QSVEncC AV1 no ha sido probado.
chs: QSVEncC AV1编码器未经测试!
jpn: QSVEncC AV1 Encoderは未検証です。
rus: Кодировщик QSVEncC AV1 не тестировался!
por: O codificador QSVEncC AV1 não foi testado!
swe: QSVEncC AV1 Encoder är otestad!
pol: QSVEncC AV1 Encoder nie jest testowany!
ukr: Кодер QSVEncC AV1 неперевірений!
kor: QSVEncC AV1 인코더는 테스트되지 않았습니다!
ron: QSVEncC AV1 Encoder nu a fost testat!
NVEncC AV1 Encoder is untested!:
eng: NVEncC AV1 Encoder is untested!
deu: NVEncC AV1 Encoder ist ungetestet!
fra: L'encodeur NVEncC AV1 n'est pas testé !
ita: Il codificatore NVEncC AV1 non è stato testato!
spa: El codificador NVEncC AV1 no ha sido probado.
chs: NVEncC AV1编码器未经测试!
jpn: NVEncC AV1 Encoderは未検証です。
rus: NVEncC AV1 Encoder не тестировался!
por: O codificador NVEncC AV1 não foi testado!
swe: NVEncC AV1 Encoder är otestad!
pol: NVEncC AV1 Encoder nie jest testowany!
ukr: Кодер NVEncC AV1 неперевірений!
kor: NVEncC AV1 인코더는 테스트되지 않았습니다!
ron: NVEncC AV1 Encoder nu este testat!
Load Directory:
eng: Load Directory
deu: Verzeichnis laden
Expand Down
8 changes: 4 additions & 4 deletions fastflix/encoders/common/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ def generate_all(

filters = None
if not disable_filters:
filter_details = fastflix.current_video.video_settings.dict().copy()
filter_details = fastflix.current_video.video_settings.model_dump().copy()
filter_details.update(filters_extra)
filters = generate_filters(
source=fastflix.current_video.source,
Expand All @@ -287,7 +287,7 @@ def generate_all(
cover=attachments,
output_video=fastflix.current_video.video_settings.output_path,
disable_rotate_metadata=encoder == "copy",
**fastflix.current_video.video_settings.dict(),
**fastflix.current_video.video_settings.model_dump(),
)

beginning = generate_ffmpeg_start(
Expand All @@ -299,8 +299,8 @@ def generate_all(
enable_opencl=enable_opencl,
ffmpeg_version=fastflix.ffmpeg_version,
start_extra=start_extra,
**fastflix.current_video.video_settings.dict(),
**settings.dict(),
**fastflix.current_video.video_settings.model_dump(),
**settings.model_dump(),
)

return beginning, ending, output_fps
Expand Down
122 changes: 68 additions & 54 deletions fastflix/encoders/common/setting_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
from pathlib import Path

from box import Box
from PySide6 import QtGui, QtWidgets, QtCore
from PySide6 import QtGui, QtWidgets

from fastflix.exceptions import FastFlixInternalException
from fastflix.language import t
from fastflix.models.fastflix_app import FastFlixApp
from fastflix.widgets.background_tasks import ExtractHDR10
from fastflix.resources import group_box_style, get_icon
from fastflix.shared import clear_list


logger = logging.getLogger("fastflix")

Expand Down Expand Up @@ -96,7 +96,7 @@ def translate_tip(tooltip):
def determine_default(self, widget_name, opt, items: List, raise_error: bool = False):
if widget_name == "pix_fmt":
items = [x.split(":")[1].strip() for x in items]
elif widget_name in ("crf", "qp"):
elif widget_name in ("crf", "qp", "qscale"):
if not opt:
return 6
opt = str(opt)
Expand Down Expand Up @@ -152,6 +152,8 @@ def _add_combo_box(
widget_name, self.app.fastflix.config.encoder_opt(self.profile_name, opt), options
)
self.opts[widget_name] = opt
else:
logger.warning("No opt provided for widget %s %s", self.__class__.__name__, widget_name)
self.widgets[widget_name].setCurrentIndex(default or 0)
self.widgets[widget_name].setDisabled(not enabled)
new_width = self.widgets[widget_name].minimumSizeHint().width() + 20
Expand Down Expand Up @@ -203,6 +205,9 @@ def _add_text_box(
if opt:
default = str(self.app.fastflix.config.encoder_opt(self.profile_name, opt)) or default
self.opts[widget_name] = opt
else:
logger.warning("No opt provided for widget %s %s", self.__class__.__name__, widget_name)

self.widgets[widget_name].setText(default)
self.widgets[widget_name].setDisabled(not enabled)
if tooltip:
Expand Down Expand Up @@ -340,6 +345,7 @@ def _add_modes(
add_qp=True,
disable_custom_qp=False,
show_bitrate_passes=False,
disable_bitrate=False,
):
self.recommended_bitrates = recommended_bitrates
self.recommended_qps = recommended_qps
Expand All @@ -353,54 +359,55 @@ def _add_modes(
bitrate_box_layout = QtWidgets.QHBoxLayout()
self.widgets.mode = QtWidgets.QButtonGroup()
self.widgets.mode.buttonClicked.connect(self.set_mode)

self.bitrate_radio = QtWidgets.QRadioButton("Bitrate")
self.bitrate_radio.setFixedWidth(80)
self.widgets.mode.addButton(self.bitrate_radio)
self.widgets.bitrate = QtWidgets.QComboBox()
# self.widgets.bitrate.setFixedWidth(250)
self.widgets.bitrate.addItems(recommended_bitrates)
self.widgets.bitrate_passes = QtWidgets.QComboBox()
self.widgets.bitrate_passes.addItems(["1", "2"])
self.widgets.bitrate_passes.setCurrentIndex(1)
self.widgets.bitrate_passes.currentIndexChanged.connect(lambda: self.mode_update())
config_opt = self.app.fastflix.config.encoder_opt(self.profile_name, "bitrate")
custom_bitrate = False
try:
default_bitrate_index = self.determine_default(
"bitrate", config_opt, recommended_bitrates, raise_error=True
)
except FastFlixInternalException:
custom_bitrate = True
self.widgets.bitrate.setCurrentText("Custom")
else:
self.widgets.bitrate.setCurrentIndex(default_bitrate_index)
self.widgets.bitrate.currentIndexChanged.connect(lambda: self.mode_update())
self.widgets.custom_bitrate = QtWidgets.QLineEdit("3000" if not custom_bitrate else config_opt)
self.widgets.custom_bitrate.setFixedWidth(100)
self.widgets.custom_bitrate.setEnabled(custom_bitrate)
self.widgets.custom_bitrate.textChanged.connect(lambda: self.main.build_commands())
self.widgets.custom_bitrate.setValidator(self.only_int)
bitrate_box_layout.addWidget(self.bitrate_radio)
bitrate_box_layout.addWidget(self.widgets.bitrate, 1)
bitrate_box_layout.addStretch(1)
if show_bitrate_passes:
bitrate_box_layout.addWidget(QtWidgets.QLabel(t("Passes") + ":"))
bitrate_box_layout.addWidget(self.widgets.bitrate_passes)
bitrate_box_layout.addStretch(1)
bitrate_box_layout.addWidget(QtWidgets.QLabel(t("Custom") + ":"))
bitrate_box_layout.addWidget(self.widgets.custom_bitrate)
bitrate_box_layout.addWidget(QtWidgets.QLabel("k"))

qp_help = (
f"{qp_name.upper()} {t('is extremely source dependant')},\n"
f"{t('the resolution-to-')}{qp_name.upper()}{t('are mere suggestions!')}"
)
self.qp_radio = QtWidgets.QRadioButton(qp_name.upper())
self.qp_radio.setChecked(True)
self.qp_radio.setFixedWidth(80)
self.qp_radio.setToolTip(qp_help)
self.widgets.mode.addButton(self.qp_radio)
config_opt = None
if not disable_bitrate:
self.bitrate_radio = QtWidgets.QRadioButton("Bitrate")
self.bitrate_radio.setFixedWidth(80)
self.widgets.mode.addButton(self.bitrate_radio)
self.widgets.bitrate = QtWidgets.QComboBox()
self.widgets.bitrate.addItems(recommended_bitrates)
self.widgets.bitrate_passes = QtWidgets.QComboBox()
self.widgets.bitrate_passes.addItems(["1", "2"])
self.widgets.bitrate_passes.setCurrentIndex(1)
self.widgets.bitrate_passes.currentIndexChanged.connect(lambda: self.mode_update())
config_opt = self.app.fastflix.config.encoder_opt(self.profile_name, "bitrate")
custom_bitrate = False
try:
default_bitrate_index = self.determine_default(
"bitrate", config_opt, recommended_bitrates, raise_error=True
)
except FastFlixInternalException:
custom_bitrate = True
self.widgets.bitrate.setCurrentText("Custom")
else:
self.widgets.bitrate.setCurrentIndex(default_bitrate_index)
self.widgets.bitrate.currentIndexChanged.connect(lambda: self.mode_update())
self.widgets.custom_bitrate = QtWidgets.QLineEdit("3000" if not custom_bitrate else config_opt)
self.widgets.custom_bitrate.setValidator(QtGui.QDoubleValidator())
self.widgets.custom_bitrate.setFixedWidth(100)
self.widgets.custom_bitrate.setEnabled(custom_bitrate)
self.widgets.custom_bitrate.textChanged.connect(lambda: self.main.build_commands())
self.widgets.custom_bitrate.setValidator(self.only_int)
bitrate_box_layout.addWidget(self.bitrate_radio)
bitrate_box_layout.addWidget(self.widgets.bitrate, 1)
bitrate_box_layout.addStretch(1)
if show_bitrate_passes:
bitrate_box_layout.addWidget(QtWidgets.QLabel(t("Passes") + ":"))
bitrate_box_layout.addWidget(self.widgets.bitrate_passes)
bitrate_box_layout.addStretch(1)
bitrate_box_layout.addWidget(QtWidgets.QLabel(t("Custom") + ":"))
bitrate_box_layout.addWidget(self.widgets.custom_bitrate)
bitrate_box_layout.addWidget(QtWidgets.QLabel("k"))

self.qp_radio = QtWidgets.QRadioButton(qp_name.upper())
self.qp_radio.setChecked(True)
self.qp_radio.setFixedWidth(80)
self.qp_radio.setToolTip(qp_help)
self.widgets.mode.addButton(self.qp_radio)

self.widgets[qp_name] = QtWidgets.QComboBox()
self.widgets[qp_name].setToolTip(qp_help)
Expand All @@ -421,14 +428,16 @@ def _add_modes(
if not disable_custom_qp:
self.widgets[f"custom_{qp_name}"] = QtWidgets.QLineEdit("30" if not custom_qp else str(qp_value))
self.widgets[f"custom_{qp_name}"].setFixedWidth(100)
self.widgets[f"custom_{qp_name}"].setValidator(QtGui.QDoubleValidator())
self.widgets[f"custom_{qp_name}"].setEnabled(custom_qp)
self.widgets[f"custom_{qp_name}"].textChanged.connect(lambda: self.main.build_commands())

if config_opt:
if not disable_bitrate and config_opt:
self.mode = "Bitrate"
self.qp_radio.setChecked(False)
self.bitrate_radio.setChecked(True)
qp_box_layout.addWidget(self.qp_radio)
if not disable_bitrate:
qp_box_layout.addWidget(self.qp_radio)
qp_box_layout.addWidget(self.widgets[qp_name], 1)
qp_box_layout.addStretch(1)
qp_box_layout.addStretch(1)
Expand All @@ -439,11 +448,13 @@ def _add_modes(
qp_box_layout.addWidget(self.widgets[f"custom_{qp_name}"])
qp_box_layout.addWidget(QtWidgets.QLabel(" "))

bitrate_group_box.setLayout(bitrate_box_layout)
if not disable_bitrate:
bitrate_group_box.setLayout(bitrate_box_layout)
qp_group_box.setLayout(qp_box_layout)

layout.addWidget(qp_group_box, 0, 0)
layout.addWidget(bitrate_group_box, 1, 0)
if not disable_bitrate:
layout.addWidget(bitrate_group_box, 1, 0)

if not add_qp:
qp_group_box.hide()
Expand Down Expand Up @@ -550,7 +561,7 @@ def reload(self):
if widget_name in ("x265_params", "svtav1_params", "vvc_params"):
data = ":".join(data)
self.widgets[widget_name].setText(str(data) or "")
if getattr(self, "qp_radio", None):
if getattr(self, "mode", None):
bitrate = getattr(self.app.fastflix.current_video.video_settings.video_encoder_settings, "bitrate", None)
if bitrate:
self.mode = "Bitrate"
Expand All @@ -565,8 +576,11 @@ def reload(self):
self.widgets.custom_bitrate.setText(bitrate.rstrip("k"))
else:
self.mode = self.qp_name
self.qp_radio.setChecked(True)
self.bitrate_radio.setChecked(False)
try:
self.qp_radio.setChecked(True)
self.bitrate_radio.setChecked(False)
except Exception:
pass
qp = str(getattr(self.app.fastflix.current_video.video_settings.video_encoder_settings, self.qp_name))
for i, rec in enumerate(self.recommended_qps):
if rec.startswith(qp):
Expand Down
6 changes: 3 additions & 3 deletions fastflix/encoders/gif/command_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ def build(fastflix: FastFlix):
args += f":max_colors={settings.max_colors}"

palletgen_filters = generate_filters(
custom_filters=f"palettegen{args}", **fastflix.current_video.video_settings.dict()
custom_filters=f"palettegen{args}", **fastflix.current_video.video_settings.model_dump()
)

filters = generate_filters(
custom_filters=f"fps={settings.fps:.2f}", raw_filters=True, **fastflix.current_video.video_settings.dict()
custom_filters=f"fps={settings.fps}", raw_filters=True, **fastflix.current_video.video_settings.model_dump()
)

output_video = clean_file_string(fastflix.current_video.video_settings.output_path)
Expand All @@ -41,7 +41,7 @@ def build(fastflix: FastFlix):
f'{beginning} {palletgen_filters} {settings.extra if settings.extra_both_passes else ""} -y "{temp_palette}"'
)

gif_filters = f"fps={settings.fps:.2f}"
gif_filters = f"fps={settings.fps}"
if filters:
gif_filters += f",{filters}"

Expand Down
5 changes: 2 additions & 3 deletions fastflix/encoders/gif/settings_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def init_dither(self):
return self._add_combo_box(
label="Dither",
widget_name="dither",
opt="dither",
tooltip=(
"Dither is an intentionally applied form of noise used to randomize quantization error,\n"
"preventing large-scale patterns such as color banding in images."
Expand Down Expand Up @@ -77,7 +78,7 @@ def init_statistics_mode(self):

def update_video_encoder_settings(self):
self.app.fastflix.current_video.video_settings.video_encoder_settings = GIFSettings(
fps=int(self.widgets.fps.currentText()),
fps=self.widgets.fps.currentText(),
dither=self.widgets.dither.currentText(),
extra=self.ffmpeg_extras,
pix_fmt="yuv420p", # hack for thumbnails to show properly
Expand All @@ -88,5 +89,3 @@ def update_video_encoder_settings(self):

def new_source(self):
super().new_source()
self.widgets.fps.setCurrentIndex(14)
self.widgets.dither.setCurrentIndex(0)
1 change: 0 additions & 1 deletion fastflix/encoders/nvencc_av1/settings_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ def __init__(self, parent, main, app: FastFlixApp):
guide_label.setOpenExternalLinks(True)
grid.addWidget(guide_label, 11, 0, 1, 4)
grid.addWidget(warning_label, 11, 4, 1, 1, alignment=QtCore.Qt.AlignRight)
grid.addWidget(QtWidgets.QLabel(t("NVEncC AV1 Encoder is untested!")), 11, 5, 1, 1)

self.setLayout(grid)
self.hide()
Expand Down
1 change: 0 additions & 1 deletion fastflix/encoders/qsvencc_av1/settings_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ def __init__(self, parent, main, app: FastFlixApp):
guide_label.setOpenExternalLinks(True)
grid.addWidget(guide_label, 11, 0, 1, 4)
grid.addWidget(warning_label, 11, 4, 1, 1, alignment=QtCore.Qt.AlignRight)
grid.addWidget(QtWidgets.QLabel(t("QSVEncC AV1 Encoder is untested!")), 11, 5, 1, 1)

self.setLayout(grid)
self.hide()
Expand Down
1 change: 0 additions & 1 deletion fastflix/encoders/vceencc_av1/settings_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ def __init__(self, parent, main, app: FastFlixApp):
guide_label.setOpenExternalLinks(True)
grid.addWidget(guide_label, 12, 0, 1, 4)
grid.addWidget(warning_label, 12, 4, 1, 1, alignment=QtCore.Qt.AlignRight)
grid.addWidget(QtWidgets.QLabel(t("VCEEncC AV1 Encoder is untested!")), 12, 5, 1, 1)

self.setLayout(grid)
self.hide()
Expand Down
3 changes: 2 additions & 1 deletion fastflix/encoders/webp/command_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ def build(fastflix: FastFlix):

return [
Command(
command=f"{beginning} -lossless {settings.lossless} -compression_level {settings.compression} "
command=f"{beginning} -lossless {'1' if settings.lossless.lower() in ('1', 'yes') else '0'} "
f"-compression_level {settings.compression} "
f"-qscale {settings.qscale} -preset {settings.preset} {settings.extra} {ending}",
name="WebP",
exe="ffmpeg",
Expand Down
Loading

0 comments on commit bd14e52

Please sign in to comment.