def __init__(self, parent, main): super(AV1, self).__init__(parent) self.main = main grid = QtWidgets.QGridLayout() self.widgets = Box(fps=None, remove_hdr=None, mode=None, segment_size=None) self.mode = 'QP' grid.addLayout(self.init_remove_hdr(), 1, 0, 1, 2) grid.addLayout(self.init_speed(), 0, 0, 1, 2) grid.addLayout(self.init_modes(), 0, 2, 4, 4) grid.addLayout(self.init_segment_size(), 3, 0, 1, 2) grid.addWidget(QtWidgets.QWidget(), 5, 0) grid.setRowStretch(5, 1) guide_label = QtWidgets.QLabel( f"<a href='https://github.com/OpenVisualCloud/SVT-AV1'>SVT-AV1 Github</a>" ) guide_label.setAlignment(QtCore.Qt.AlignBottom) guide_label.setOpenExternalLinks(True) grid.addWidget(guide_label, 9, 0, -1, 1) self.setLayout(grid) self.hide()
def __init__(self, parent, main): super(AV1, self).__init__(parent) self.main = main grid = QtWidgets.QGridLayout() # grid.addWidget(QtWidgets.QLabel("FFMPEG libaom-av1"), 0, 0) self.widgets = Box(fps=None, remove_hdr=None, mode=None) self.mode = 'CRF' grid.addLayout(self.init_remove_hdr(), 0, 0, 1, 2) grid.addLayout(self.init_modes(), 0, 2, 3, 3) grid.addWidget(QtWidgets.QWidget(), 5, 0) grid.setRowStretch(5, 1) guide_label = QtWidgets.QLabel( f"<a href='https://trac.ffmpeg.org/wiki/Encode/AV1'>FFMPEG AV1 Encoding Guide</a>" ) guide_label.setAlignment(QtCore.Qt.AlignBottom) guide_label.setOpenExternalLinks(True) grid.addWidget(guide_label, 9, 0, -1, 1) self.setLayout(grid) self.hide()
def __init__(self, parent, main): super(VP9, self).__init__(parent) self.main = main grid = QtWidgets.QGridLayout() # grid.addWidget(QtWidgets.QLabel("VP9"), 0, 0) self.widgets = Box( fps=None, remove_hdr=None, mode=None) self.mode = 'CRF' grid.addLayout(self.init_remove_hdr(), 2, 0, 1, 2) grid.addLayout(self.init_modes(), 0, 2, 4, 4) grid.addLayout(self.init_quality(), 1, 0, 1, 2) grid.addLayout(self.init_speed(), 0, 0, 1, 2) grid.addLayout(self.init_row_mt(), 4, 0, 1, 2) grid.addLayout(self.init_force_420(), 5, 0, 1, 2) grid.addLayout(self.init_single_pass(), 6, 0, 1, 2) grid.addWidget(QtWidgets.QWidget(), 8, 0) grid.setRowStretch(8, 1) guide_label = QtWidgets.QLabel(f"<a href='https://trac.ffmpeg.org/wiki/Encode/VP9'>FFMPEG VP9 Encoding Guide</a>") guide_label.setAlignment(QtCore.Qt.AlignBottom) guide_label.setOpenExternalLinks(True) grid.addWidget(guide_label, 9, 0, -1, 1) self.setLayout(grid) self.hide()
def init_modes(self): layout = QtWidgets.QGridLayout() crf_group_box = QtWidgets.QGroupBox() crf_group_box.setStyleSheet("QGroupBox{padding-top:5px; margin-top:-18px}") crf_box_layout = QtWidgets.QHBoxLayout() bitrate_group_box = QtWidgets.QGroupBox() bitrate_group_box.setStyleSheet("QGroupBox{padding-top:5px; margin-top:-18px}") bitrate_box_layout = QtWidgets.QHBoxLayout() # rotation_dir = Path(base_path, 'data', 'rotations') # group_box.setStyleSheet("QGroupBox{padding-top:15px; margin-top:-15px; padding-bottom:-5px}") self.widgets.mode = QtWidgets.QButtonGroup() self.widgets.mode.buttonClicked.connect(self.set_mode) bitrate_radio = QtWidgets.QRadioButton("Bitrate") bitrate_radio.setFixedWidth(80) self.widgets.mode.addButton(bitrate_radio) self.widgets.bitrate = QtWidgets.QComboBox() self.widgets.bitrate.setFixedWidth(250) self.widgets.bitrate.addItems(recommended_bitrates) self.widgets.bitrate.currentIndexChanged.connect(lambda: self.main.build_commands()) self.widgets.bitrate.setCurrentIndex(6) self.widgets.custom_bitrate = QtWidgets.QLineEdit("3000") self.widgets.custom_bitrate.setFixedWidth(100) bitrate_box_layout.addWidget(bitrate_radio) bitrate_box_layout.addWidget(self.widgets.bitrate) bitrate_box_layout.addStretch() bitrate_box_layout.addWidget(QtWidgets.QLabel("Custom:")) bitrate_box_layout.addWidget(self.widgets.custom_bitrate) crf_radio = QtWidgets.QRadioButton("CRF") crf_radio.setChecked(True) crf_radio.setFixedWidth(80) self.widgets.mode.addButton(crf_radio) self.widgets.crf = QtWidgets.QComboBox() self.widgets.crf.setFixedWidth(250) self.widgets.crf.addItems(recommended_crfs) self.widgets.crf.setCurrentIndex(4) self.widgets.crf.currentIndexChanged.connect(lambda: self.main.build_commands()) self.widgets.custom_crf = QtWidgets.QLineEdit("30") self.widgets.custom_crf.setFixedWidth(100) crf_box_layout.addWidget(crf_radio) crf_box_layout.addWidget(self.widgets.crf) crf_box_layout.addStretch() crf_box_layout.addWidget(QtWidgets.QLabel("Custom:")) crf_box_layout.addWidget(self.widgets.custom_crf) bitrate_group_box.setLayout(bitrate_box_layout) crf_group_box.setLayout(crf_box_layout) layout.addWidget(crf_group_box, 0, 0) layout.addWidget(bitrate_group_box, 1, 0) return layout
def __init__(self, parent=None): super(About, self).__init__(parent) layout = QtWidgets.QGridLayout() self.setMinimumSize(400, 400) build_file = Path(base_path, 'build_version') label = QtWidgets.QLabel(f"<b>FastFlix</b> v{__version__}<br>" f"{f'Build: {build_file.read_text().strip()}<br>' if build_file.exists() else ''}" f"<br>Author: <a href='https://github.com/cdgriffith'>Chris Griffith</a>" f"<br>License: MIT") label.setFont(QtGui.QFont("Arial", 14)) label.setAlignment(QtCore.Qt.AlignCenter) label.setOpenExternalLinks(True) label.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) supporting_libraries_label = QtWidgets.QLabel( "Supporting libraries<br>" f"<a href='https://www.python.org/'>Python</a> {reusables.version_string} (PSF LICENSE), " f"<a href='https://wiki.qt.io/Qt_for_Python'>PySide2</a> {pyside_version} (LGPLv3)<br>" f"<a href='https://github.com/cdgriffith/Box'>python-box</a> {box_version} (MIT), " f"<a href='https://github.com/cdgriffith/Reusables'>Reusables</a> {reusables.__version__} (MIT)<br>") supporting_libraries_label.setAlignment(QtCore.Qt.AlignCenter) supporting_libraries_label.setOpenExternalLinks(True) layout.addWidget(label) layout.addWidget(supporting_libraries_label) if Path(base_path, 'bundled').exists(): bundle_label = QtWidgets.QLabel( "Bundled with: <a href='https://github.com/OpenVisualCloud/SVT-AV1'>SVT AV1</a> (Modified BSD) and " "<a href='https://www.ffmpeg.org/download.html'>ffmpeg</a> (LGPL)") bundle_label.setAlignment(QtCore.Qt.AlignCenter) bundle_label.setOpenExternalLinks(True) layout.addWidget(bundle_label) if pyinstaller: pyinstaller_label = QtWidgets.QLabel("Packaged with: <a href='https://www.pyinstaller.org/index.html'>" "PyInstaller</a>") pyinstaller_label.setAlignment(QtCore.Qt.AlignCenter) pyinstaller_label.setOpenExternalLinks(True) layout.addWidget(pyinstaller_label) replacer = '\\' license_label = QtWidgets.QLabel( f"<a href='file:///{base_path.replace(replacer, '/')}/docs/build-licenses.txt' download>LICENSES</a>") license_label.setAlignment(QtCore.Qt.AlignCenter) license_label.setOpenExternalLinks(True) layout.addWidget(license_label) self.setLayout(layout) self.show()
def __init__(self, parent, audio, number, enabled=True): super(Subtitle, self).__init__(parent) self.audio = audio self.widget = QtWidgets.QLineEdit() self.widget.setText(audio) self.widget.setDisabled(not enabled) self.setFixedHeight(60) grid = QtWidgets.QGridLayout() grid.addWidget(QtWidgets.QLabel(f"Track {number}"), 0, 0, 1, 2) grid.addWidget(self.widget, 1, 0, 1, 2) self.setLayout(grid)
def __init__(self, parent): super(CommandList, self).__init__(parent) layout = QtWidgets.QGridLayout() layout.addWidget(QtWidgets.QLabel('Commands to execute')) self.inner_widget = QtWidgets.QWidget() self.scroll_area = QtWidgets.QScrollArea(self) self.scroll_area.setMinimumHeight(200) layout.addWidget(self.scroll_area) self.setLayout(layout)
def __init__(self, parent): super(SubtitleList, self).__init__(parent) layout = QtWidgets.QGridLayout() layout.addWidget(QtWidgets.QLabel('Subtitle Tracks')) self.inner_widget = QtWidgets.QWidget() self.scroll_area = QtWidgets.QScrollArea(self) self.scroll_area.setMinimumHeight(200) layout.addWidget(self.scroll_area) self.setLayout(layout)
def __init__(self, parent, command, number, name="", enabled=True): super(Command, self).__init__(parent) self.command = command self.widget = QtWidgets.QLineEdit() self.widget.setReadOnly(True) self.widget.setText(command) self.widget.setDisabled(not enabled) self.setFixedHeight(60) grid = QtWidgets.QGridLayout() grid.addWidget( QtWidgets.QLabel(f"Command {number}" if not name else name), 0, 0, 1, 2) grid.addWidget(self.widget, 1, 0, 1, 2) self.setLayout(grid)
def __init__(self, parent, main): super(GIF, self).__init__(parent) self.main = main grid = QtWidgets.QGridLayout() # grid.addWidget(QtWidgets.QLabel("GIF"), 0, 0) self.widgets = Box(fps=None, remove_hdr=None, dither=None) grid.addLayout(self.init_fps(), 1, 0) grid.addLayout(self.init_remove_hdr(), 2, 0) grid.addLayout(self.init_dither(), 0, 0) grid.addWidget(QtWidgets.QWidget(), 5, 0, 5, 2) self.setLayout(grid)
def __init__(self, parent, available_audio_encoders): super(AudioList, self).__init__(parent) self.main = parent.main self.inner_layout = None self.available_audio_encoders = available_audio_encoders layout = QtWidgets.QGridLayout() layout.addWidget(QtWidgets.QLabel('Audio Tracks')) self.inner_widget = QtWidgets.QWidget() self.scroll_area = QtWidgets.QScrollArea(self) self.scroll_area.setMinimumHeight(200) layout.addWidget(self.scroll_area) self.tracks = [] self.setLayout(layout)
def __init__(self, parent, data_path, ffmpeg, ffprobe, svt_av1, **kwargs): super().__init__(parent) self.container = parent self.initialized = False self.loading_video = True self.scale_updating = False self.path = Box( data= data_path, # Path(user_data_dir("FastFlix", appauthor=False, version=__version__, roaming=True)) ) self.plugins = load_plugins(Path(data_path, 'plugins')) self.ffmpeg = ffmpeg self.ffprobe = ffprobe self.svt_av1 = svt_av1 self.input_defaults = Box(scale=None, crop=None) self.path.ffmpeg = Path(self.path.data, "ffmpeg") self.path.svt_av1 = Path(self.path.data, "svt_av1") for path in self.path.values(): path.mkdir(parents=True, exist_ok=True) self.setAcceptDrops(True) self.input_video = None self.streams, self.format_info = None, None # self.x265 = X265(parent=self, source=source) # self.av1 = AV1(parent=self, source=source) # self.gif = GIF(parent=self, source=source) self.widgets = Box(input_file=None, preview=None, start_time=None, duration=None, video_track=None, convert_to=None, rotate=None, convert_button=None, v_flip=None, h_flip=None, crop=Box(top=None, bottom=None, left=None, right=None), scale=Box(width=None, height=None, keep_aspect_ratio=None)) self.thumb_file = Path(self.path.data, 'thumbnail_preview.png') self.flix = Flix(ffmpeg=self.ffmpeg, ffprobe=self.ffprobe, svt_av1=self.svt_av1) self.video_options = VideoOptions( self, available_audio_encoders=self.flix.get_audio_encoders()) self.completed.connect(self.conversion_complete) self.cancelled.connect(self.conversion_cancelled) self.thumbnail_complete.connect(self.thumbnail_generated) self.encoding_worker = None self.command_runner = None self.converting = False self.video_width = 0 self.video_height = 0 self.default_options = Box() self.output_video = None self.grid = QtWidgets.QGridLayout() self.init_video_area() self.init_scale_and_crop() self.init_preview_image() self.grid.addWidget(self.video_options, 5, 0, 10, 15) self.grid.setSpacing(5) self.setLayout(self.grid) self.show() self.initialized = True
def init_rotate(self): group_box = QtWidgets.QGroupBox() rotation_dir = Path(base_path, 'data', 'rotations') group_box.setStyleSheet( "QGroupBox{padding-top:15px; margin-top:-15px; padding-bottom:-5px}" ) group = QtWidgets.QButtonGroup() v_size = QtCore.QSize(40, 60) h_size = QtCore.QSize(60, 40) rot_none = QtWidgets.QRadioButton("No Rotation") rot_none.setIcon(QtGui.QIcon(str(Path(rotation_dir, 'FastFlix.png')))) rot_none.setIconSize(h_size) rot_none.name = None rot_1 = QtWidgets.QRadioButton("90°") rot_1.setIcon(QtGui.QIcon(str(Path(rotation_dir, 'FastFlix C90.png')))) rot_1.setIconSize(v_size) rot_1.name = 1 rot_2 = QtWidgets.QRadioButton("270°") rot_2.setIcon(QtGui.QIcon(str(Path(rotation_dir, 'FastFlix CC90.png')))) rot_2.setIconSize(v_size) rot_2.name = 2 rot_4 = QtWidgets.QRadioButton("180°") rot_4.setIcon(QtGui.QIcon(str(Path(rotation_dir, 'FastFlix 180.png')))) rot_4.setIconSize(h_size) rot_4.name = 4 self.widgets.v_flip = QtWidgets.QCheckBox("Vertical Flip") self.widgets.v_flip.setIcon( QtGui.QIcon(str(Path(rotation_dir, 'FastFlix VF.png')))) self.widgets.v_flip.setIconSize(h_size) self.widgets.v_flip.toggled.connect(lambda: self.page_update()) self.widgets.h_flip = QtWidgets.QCheckBox("Horizontal Flip") self.widgets.h_flip.setIcon( QtGui.QIcon(str(Path(rotation_dir, 'FastFlix HF.png')))) self.widgets.h_flip.setIconSize(h_size) self.widgets.h_flip.toggled.connect(lambda: self.page_update()) group.addButton(rot_1) group.addButton(rot_2) group.addButton(rot_4) group.addButton(rot_none) layout = QtWidgets.QGridLayout() layout.addWidget(rot_none, 1, 0) layout.addWidget(rot_1, 0, 0) layout.addWidget(rot_2, 0, 2) layout.addWidget(rot_4, 0, 1) layout.addWidget(self.widgets.v_flip, 1, 2) layout.addWidget(self.widgets.h_flip, 1, 1) label = QtWidgets.QLabel("Rotation", alignment=(Qt.AlignBottom | Qt.AlignRight)) label.setStyleSheet("QLabel{color:#777}") layout.addWidget(label, 1, 3) group_box.setLayout(layout) rot_none.setChecked(True) self.widgets.rotate = group self.widgets.rotate.buttonClicked.connect(lambda: self.page_update()) return group_box
def __init__(self, parent, audio, index, codec, available_audio_encoders, outdex=None, enabled=True, original=False, first=False, last=False, codecs=(), channels=2): super(Audio, self).__init__(parent) self.parent = parent self.audio = audio self.setFixedHeight(60) self.original = original self.outdex = index if self.original else outdex self.first = first self.last = last self.index = index self.codec = codec self.codecs = codecs self.channels = channels self.loading = True self.available_audio_encoders = available_audio_encoders self.widgets = Box( track_number=QtWidgets.QLabel( f'{index}:{self.outdex}' if enabled else '❌'), audio_info=QtWidgets.QLineEdit(audio), up_button=QtWidgets.QPushButton("^"), down_button=QtWidgets.QPushButton("v"), enable_check=QtWidgets.QCheckBox("Enabled"), dup_button=QtWidgets.QPushButton("➕"), delete_button=QtWidgets.QPushButton("⛔"), convert_to=None, convert_bitrate=None, ) self.widgets.enable_check.setChecked(enabled) #self.widgets.enable_check.toggled.connect(lambda: self.parent.reorder()) self.widgets.dup_button.clicked.connect(lambda: self.dup_me()) self.widgets.dup_button.setFixedWidth(20) self.widgets.delete_button.clicked.connect(lambda: self.del_me()) self.widgets.delete_button.setFixedWidth(20) self.widgets.track_number.setFixedWidth(20) grid = QtWidgets.QGridLayout() grid.addLayout(self.init_move_buttons(), 0, 0) grid.addWidget(self.widgets.track_number, 0, 1) grid.addWidget(self.widgets.audio_info, 0, 2) grid.addLayout(self.init_conversion(), 0, 3) if not original: grid.addWidget(self.widgets.delete_button, 0, 4) else: grid.addWidget(self.widgets.dup_button, 0, 5) grid.addWidget(self.widgets.enable_check, 0, 4) self.setLayout(grid) self.loading = False