PyVideoKit-GUI 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyvideokit_gui/__init__.py +1 -0
- pyvideokit_gui/_base_panel.py +108 -0
- pyvideokit_gui/_main.py +18 -0
- pyvideokit_gui/_main_window.py +27 -0
- pyvideokit_gui/_worker.py +21 -0
- pyvideokit_gui/concat_panel.py +56 -0
- pyvideokit_gui/convert_panel.py +27 -0
- pyvideokit_gui/extract_audio_panel.py +20 -0
- pyvideokit_gui/fade_panel.py +59 -0
- pyvideokit_gui/trim_panel.py +48 -0
- pyvideokit_gui/vhs_panel.py +20 -0
- pyvideokit_gui/youtube_panel.py +20 -0
- pyvideokit_gui-0.2.0.dist-info/METADATA +689 -0
- pyvideokit_gui-0.2.0.dist-info/RECORD +18 -0
- pyvideokit_gui-0.2.0.dist-info/WHEEL +5 -0
- pyvideokit_gui-0.2.0.dist-info/entry_points.txt +2 -0
- pyvideokit_gui-0.2.0.dist-info/licenses/LICENSE +674 -0
- pyvideokit_gui-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from PySide6.QtCore import Qt
|
|
4
|
+
from PySide6.QtWidgets import (
|
|
5
|
+
QFileDialog,
|
|
6
|
+
QHBoxLayout,
|
|
7
|
+
QLabel,
|
|
8
|
+
QLineEdit,
|
|
9
|
+
QProgressBar,
|
|
10
|
+
QPushButton,
|
|
11
|
+
QVBoxLayout,
|
|
12
|
+
QWidget,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from pyvideokit_gui._worker import Worker
|
|
16
|
+
|
|
17
|
+
_VIDEO_FILTER = "Video files (*.mkv *.mp4 *.mov *.avi *.webm);;All files (*)"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class BasePanel(QWidget):
|
|
21
|
+
def __init__(self, parent=None):
|
|
22
|
+
super().__init__(parent)
|
|
23
|
+
self._worker = None
|
|
24
|
+
root = QVBoxLayout(self)
|
|
25
|
+
root.setAlignment(Qt.AlignTop)
|
|
26
|
+
root.setSpacing(10)
|
|
27
|
+
root.setContentsMargins(20, 20, 20, 20)
|
|
28
|
+
self._build_ui(root)
|
|
29
|
+
root.addStretch()
|
|
30
|
+
self._build_run_section(root)
|
|
31
|
+
|
|
32
|
+
def _build_ui(self, layout: QVBoxLayout):
|
|
33
|
+
raise NotImplementedError
|
|
34
|
+
|
|
35
|
+
def _run(self):
|
|
36
|
+
raise NotImplementedError
|
|
37
|
+
|
|
38
|
+
# ── file picker helpers ───────────────────────────────────────────────
|
|
39
|
+
|
|
40
|
+
def _input_row(self, layout, label="Input file", filter=_VIDEO_FILTER) -> QLineEdit:
|
|
41
|
+
layout.addWidget(QLabel(label))
|
|
42
|
+
row = QHBoxLayout()
|
|
43
|
+
le = QLineEdit()
|
|
44
|
+
le.setPlaceholderText("Select a file…")
|
|
45
|
+
btn = QPushButton("Browse…")
|
|
46
|
+
row.addWidget(le)
|
|
47
|
+
row.addWidget(btn)
|
|
48
|
+
layout.addLayout(row)
|
|
49
|
+
btn.clicked.connect(lambda: self._browse_open(le, label, filter))
|
|
50
|
+
return le
|
|
51
|
+
|
|
52
|
+
def _output_row(self, layout, label="Output (optional)") -> QLineEdit:
|
|
53
|
+
layout.addWidget(QLabel(label))
|
|
54
|
+
row = QHBoxLayout()
|
|
55
|
+
le = QLineEdit()
|
|
56
|
+
le.setPlaceholderText("Leave empty for default…")
|
|
57
|
+
btn = QPushButton("Browse…")
|
|
58
|
+
row.addWidget(le)
|
|
59
|
+
row.addWidget(btn)
|
|
60
|
+
layout.addLayout(row)
|
|
61
|
+
btn.clicked.connect(lambda: self._browse_save(le, label))
|
|
62
|
+
return le
|
|
63
|
+
|
|
64
|
+
def _browse_open(self, le: QLineEdit, title: str, filter: str):
|
|
65
|
+
path, _ = QFileDialog.getOpenFileName(self, title, "", filter)
|
|
66
|
+
if path:
|
|
67
|
+
le.setText(path)
|
|
68
|
+
|
|
69
|
+
def _browse_save(self, le: QLineEdit, title: str):
|
|
70
|
+
path, _ = QFileDialog.getSaveFileName(self, title, "")
|
|
71
|
+
if path:
|
|
72
|
+
le.setText(path)
|
|
73
|
+
|
|
74
|
+
# ── worker ────────────────────────────────────────────────────────────
|
|
75
|
+
|
|
76
|
+
def _start_worker(self, fn, *args, **kwargs):
|
|
77
|
+
self._progress.setValue(0)
|
|
78
|
+
self._status.setText("Running…")
|
|
79
|
+
self._run_btn.setEnabled(False)
|
|
80
|
+
self._worker = Worker(fn, args, kwargs)
|
|
81
|
+
self._worker.progress.connect(lambda pct: self._progress.setValue(int(pct)))
|
|
82
|
+
self._worker.finished.connect(self._on_finished)
|
|
83
|
+
self._worker.error.connect(self._on_error)
|
|
84
|
+
self._worker.start()
|
|
85
|
+
|
|
86
|
+
# ── run section ───────────────────────────────────────────────────────
|
|
87
|
+
|
|
88
|
+
def _build_run_section(self, layout):
|
|
89
|
+
self._run_btn = QPushButton("▶ Run")
|
|
90
|
+
self._run_btn.setFixedHeight(36)
|
|
91
|
+
self._run_btn.clicked.connect(self._run)
|
|
92
|
+
self._progress = QProgressBar()
|
|
93
|
+
self._progress.setRange(0, 100)
|
|
94
|
+
self._progress.setValue(0)
|
|
95
|
+
self._status = QLabel("")
|
|
96
|
+
layout.addWidget(self._run_btn)
|
|
97
|
+
layout.addWidget(self._progress)
|
|
98
|
+
layout.addWidget(self._status)
|
|
99
|
+
|
|
100
|
+
def _on_finished(self, result):
|
|
101
|
+
self._progress.setValue(100)
|
|
102
|
+
self._status.setText(f"✅ Done → {Path(str(result)).name}")
|
|
103
|
+
self._run_btn.setEnabled(True)
|
|
104
|
+
|
|
105
|
+
def _on_error(self, msg):
|
|
106
|
+
self._progress.setValue(0)
|
|
107
|
+
self._status.setText(f"❌ {msg}")
|
|
108
|
+
self._run_btn.setEnabled(True)
|
pyvideokit_gui/_main.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
from PySide6.QtWidgets import QApplication
|
|
4
|
+
|
|
5
|
+
from pyvideokit_gui._main_window import MainWindow
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main():
|
|
9
|
+
app = QApplication(sys.argv)
|
|
10
|
+
app.setApplicationName("PyVideoKit")
|
|
11
|
+
app.setStyle("Fusion")
|
|
12
|
+
window = MainWindow()
|
|
13
|
+
window.show()
|
|
14
|
+
sys.exit(app.exec())
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
if __name__ == "__main__":
|
|
18
|
+
main()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from PySide6.QtWidgets import QMainWindow, QTabWidget
|
|
2
|
+
|
|
3
|
+
from pyvideokit_gui.concat_panel import ConcatPanel
|
|
4
|
+
from pyvideokit_gui.convert_panel import ConvertPanel
|
|
5
|
+
from pyvideokit_gui.extract_audio_panel import ExtractAudioPanel
|
|
6
|
+
from pyvideokit_gui.fade_panel import FadePanel
|
|
7
|
+
from pyvideokit_gui.trim_panel import TrimPanel
|
|
8
|
+
from pyvideokit_gui.vhs_panel import VhsPanel
|
|
9
|
+
from pyvideokit_gui.youtube_panel import YouTubePanel
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MainWindow(QMainWindow):
|
|
13
|
+
def __init__(self):
|
|
14
|
+
super().__init__()
|
|
15
|
+
self.setWindowTitle("PyVideoKit")
|
|
16
|
+
self.setMinimumSize(660, 460)
|
|
17
|
+
|
|
18
|
+
tabs = QTabWidget()
|
|
19
|
+
tabs.addTab(ConvertPanel(), "🎞️ Convert to FFV1")
|
|
20
|
+
tabs.addTab(TrimPanel(), "✂️ Trim")
|
|
21
|
+
tabs.addTab(ConcatPanel(), "🔗 Concat")
|
|
22
|
+
tabs.addTab(FadePanel(), "🎬 Fade")
|
|
23
|
+
tabs.addTab(VhsPanel(), "📼 VHS Effect")
|
|
24
|
+
tabs.addTab(ExtractAudioPanel(), "🔊 Extract Audio")
|
|
25
|
+
tabs.addTab(YouTubePanel(), "📺 YouTube")
|
|
26
|
+
|
|
27
|
+
self.setCentralWidget(tabs)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from PySide6.QtCore import QThread, Signal
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Worker(QThread):
|
|
5
|
+
progress = Signal(float)
|
|
6
|
+
finished = Signal(object)
|
|
7
|
+
error = Signal(str)
|
|
8
|
+
|
|
9
|
+
def __init__(self, fn, args=(), kwargs=None):
|
|
10
|
+
super().__init__()
|
|
11
|
+
self._fn = fn
|
|
12
|
+
self._args = args
|
|
13
|
+
self._kwargs = dict(kwargs or {})
|
|
14
|
+
self._kwargs["on_progress"] = self.progress.emit
|
|
15
|
+
|
|
16
|
+
def run(self):
|
|
17
|
+
try:
|
|
18
|
+
result = self._fn(*self._args, **self._kwargs)
|
|
19
|
+
self.finished.emit(result)
|
|
20
|
+
except Exception as e:
|
|
21
|
+
self.error.emit(str(e))
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from PySide6.QtWidgets import (
|
|
4
|
+
QAbstractItemView,
|
|
5
|
+
QFileDialog,
|
|
6
|
+
QHBoxLayout,
|
|
7
|
+
QLabel,
|
|
8
|
+
QListWidget,
|
|
9
|
+
QPushButton,
|
|
10
|
+
QVBoxLayout,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from pyvideokit_gui._base_panel import BasePanel
|
|
14
|
+
from pyvideokit_libs import join_videos
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ConcatPanel(BasePanel):
|
|
18
|
+
def _build_ui(self, layout: QVBoxLayout):
|
|
19
|
+
layout.addWidget(QLabel("Video files (add at least 2, drag to reorder)"))
|
|
20
|
+
|
|
21
|
+
self._list = QListWidget()
|
|
22
|
+
self._list.setDragDropMode(QAbstractItemView.InternalMove)
|
|
23
|
+
self._list.setMinimumHeight(120)
|
|
24
|
+
layout.addWidget(self._list)
|
|
25
|
+
|
|
26
|
+
btns = QHBoxLayout()
|
|
27
|
+
add_btn = QPushButton("Add files…")
|
|
28
|
+
rm_btn = QPushButton("Remove selected")
|
|
29
|
+
btns.addWidget(add_btn)
|
|
30
|
+
btns.addWidget(rm_btn)
|
|
31
|
+
layout.addLayout(btns)
|
|
32
|
+
|
|
33
|
+
add_btn.clicked.connect(self._add_files)
|
|
34
|
+
rm_btn.clicked.connect(self._remove_selected)
|
|
35
|
+
|
|
36
|
+
self._output = self._output_row(layout, "Output (optional)")
|
|
37
|
+
|
|
38
|
+
def _add_files(self):
|
|
39
|
+
paths, _ = QFileDialog.getOpenFileNames(
|
|
40
|
+
self, "Add video files", "",
|
|
41
|
+
"Video files (*.mkv *.mp4 *.mov *.avi *.webm);;All files (*)",
|
|
42
|
+
)
|
|
43
|
+
for p in paths:
|
|
44
|
+
self._list.addItem(p)
|
|
45
|
+
|
|
46
|
+
def _remove_selected(self):
|
|
47
|
+
for item in self._list.selectedItems():
|
|
48
|
+
self._list.takeItem(self._list.row(item))
|
|
49
|
+
|
|
50
|
+
def _run(self):
|
|
51
|
+
paths = [Path(self._list.item(i).text()) for i in range(self._list.count())]
|
|
52
|
+
if len(paths) < 2:
|
|
53
|
+
self._status.setText("❌ Add at least 2 video files.")
|
|
54
|
+
return
|
|
55
|
+
output = self._output.text().strip() or None
|
|
56
|
+
self._start_worker(join_videos, paths, output=output)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from PySide6.QtWidgets import QLabel, QSpinBox, QVBoxLayout
|
|
4
|
+
|
|
5
|
+
from pyvideokit_gui._base_panel import BasePanel
|
|
6
|
+
from pyvideokit_libs import convert_to_ffv1
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ConvertPanel(BasePanel):
|
|
10
|
+
def _build_ui(self, layout: QVBoxLayout):
|
|
11
|
+
self._input = self._input_row(layout, "Input file")
|
|
12
|
+
|
|
13
|
+
layout.addWidget(QLabel("FPS"))
|
|
14
|
+
self._fps = QSpinBox()
|
|
15
|
+
self._fps.setRange(1, 240)
|
|
16
|
+
self._fps.setValue(60)
|
|
17
|
+
layout.addWidget(self._fps)
|
|
18
|
+
|
|
19
|
+
self._output = self._output_row(layout, "Output MKV (optional)")
|
|
20
|
+
|
|
21
|
+
def _run(self):
|
|
22
|
+
path = self._input.text().strip()
|
|
23
|
+
if not path:
|
|
24
|
+
self._status.setText("❌ Select an input file.")
|
|
25
|
+
return
|
|
26
|
+
output = self._output.text().strip() or None
|
|
27
|
+
self._start_worker(convert_to_ffv1, Path(path), fps=self._fps.value(), output=output)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from PySide6.QtWidgets import QVBoxLayout
|
|
4
|
+
|
|
5
|
+
from pyvideokit_gui._base_panel import BasePanel
|
|
6
|
+
from pyvideokit_libs import extract_audio
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ExtractAudioPanel(BasePanel):
|
|
10
|
+
def _build_ui(self, layout: QVBoxLayout):
|
|
11
|
+
self._input = self._input_row(layout, "Input file")
|
|
12
|
+
self._output = self._output_row(layout, "Output WAV (optional)")
|
|
13
|
+
|
|
14
|
+
def _run(self):
|
|
15
|
+
path = self._input.text().strip()
|
|
16
|
+
if not path:
|
|
17
|
+
self._status.setText("❌ Select an input file.")
|
|
18
|
+
return
|
|
19
|
+
output = self._output.text().strip() or None
|
|
20
|
+
self._start_worker(extract_audio, Path(path), output=output)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from PySide6.QtWidgets import QDoubleSpinBox, QHBoxLayout, QLabel, QSpinBox, QVBoxLayout
|
|
4
|
+
|
|
5
|
+
from pyvideokit_gui._base_panel import BasePanel
|
|
6
|
+
from pyvideokit_libs import fade_video
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FadePanel(BasePanel):
|
|
10
|
+
def _build_ui(self, layout: QVBoxLayout):
|
|
11
|
+
self._input = self._input_row(layout, "Input file (FFV1)")
|
|
12
|
+
|
|
13
|
+
row = QHBoxLayout()
|
|
14
|
+
|
|
15
|
+
fi_col = QVBoxLayout()
|
|
16
|
+
fi_col.addWidget(QLabel("Fade-in (seconds, 0 = disabled)"))
|
|
17
|
+
self._fade_in = QDoubleSpinBox()
|
|
18
|
+
self._fade_in.setRange(0, 60)
|
|
19
|
+
self._fade_in.setDecimals(2)
|
|
20
|
+
fi_col.addWidget(self._fade_in)
|
|
21
|
+
|
|
22
|
+
fo_col = QVBoxLayout()
|
|
23
|
+
fo_col.addWidget(QLabel("Fade-out (seconds, 0 = disabled)"))
|
|
24
|
+
self._fade_out = QDoubleSpinBox()
|
|
25
|
+
self._fade_out.setRange(0, 60)
|
|
26
|
+
self._fade_out.setDecimals(2)
|
|
27
|
+
fo_col.addWidget(self._fade_out)
|
|
28
|
+
|
|
29
|
+
row.addLayout(fi_col)
|
|
30
|
+
row.addLayout(fo_col)
|
|
31
|
+
layout.addLayout(row)
|
|
32
|
+
|
|
33
|
+
layout.addWidget(QLabel("FPS"))
|
|
34
|
+
self._fps = QSpinBox()
|
|
35
|
+
self._fps.setRange(1, 240)
|
|
36
|
+
self._fps.setValue(60)
|
|
37
|
+
layout.addWidget(self._fps)
|
|
38
|
+
|
|
39
|
+
self._output = self._output_row(layout, "Output (optional)")
|
|
40
|
+
|
|
41
|
+
def _run(self):
|
|
42
|
+
path = self._input.text().strip()
|
|
43
|
+
if not path:
|
|
44
|
+
self._status.setText("❌ Select an input file.")
|
|
45
|
+
return
|
|
46
|
+
fi = self._fade_in.value() or None
|
|
47
|
+
fo = self._fade_out.value() or None
|
|
48
|
+
if not fi and not fo:
|
|
49
|
+
self._status.setText("❌ Set at least one fade duration.")
|
|
50
|
+
return
|
|
51
|
+
output = self._output.text().strip() or None
|
|
52
|
+
self._start_worker(
|
|
53
|
+
fade_video,
|
|
54
|
+
Path(path),
|
|
55
|
+
fade_in=fi,
|
|
56
|
+
fade_out=fo,
|
|
57
|
+
fps=self._fps.value(),
|
|
58
|
+
output=output,
|
|
59
|
+
)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from PySide6.QtWidgets import QDoubleSpinBox, QHBoxLayout, QLabel, QVBoxLayout
|
|
4
|
+
|
|
5
|
+
from pyvideokit_gui._base_panel import BasePanel
|
|
6
|
+
from pyvideokit_libs import trim_video
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TrimPanel(BasePanel):
|
|
10
|
+
def _build_ui(self, layout: QVBoxLayout):
|
|
11
|
+
self._input = self._input_row(layout, "Input file")
|
|
12
|
+
|
|
13
|
+
row = QHBoxLayout()
|
|
14
|
+
|
|
15
|
+
start_col = QVBoxLayout()
|
|
16
|
+
start_col.addWidget(QLabel("Start (seconds)"))
|
|
17
|
+
self._start = QDoubleSpinBox()
|
|
18
|
+
self._start.setRange(0, 999999)
|
|
19
|
+
self._start.setDecimals(2)
|
|
20
|
+
start_col.addWidget(self._start)
|
|
21
|
+
|
|
22
|
+
end_col = QVBoxLayout()
|
|
23
|
+
end_col.addWidget(QLabel("End (seconds)"))
|
|
24
|
+
self._end = QDoubleSpinBox()
|
|
25
|
+
self._end.setRange(0, 999999)
|
|
26
|
+
self._end.setDecimals(2)
|
|
27
|
+
self._end.setValue(60)
|
|
28
|
+
end_col.addWidget(self._end)
|
|
29
|
+
|
|
30
|
+
row.addLayout(start_col)
|
|
31
|
+
row.addLayout(end_col)
|
|
32
|
+
layout.addLayout(row)
|
|
33
|
+
|
|
34
|
+
self._output = self._output_row(layout, "Output (optional)")
|
|
35
|
+
|
|
36
|
+
def _run(self):
|
|
37
|
+
path = self._input.text().strip()
|
|
38
|
+
if not path:
|
|
39
|
+
self._status.setText("❌ Select an input file.")
|
|
40
|
+
return
|
|
41
|
+
output = self._output.text().strip() or None
|
|
42
|
+
self._start_worker(
|
|
43
|
+
trim_video,
|
|
44
|
+
Path(path),
|
|
45
|
+
self._start.value(),
|
|
46
|
+
self._end.value(),
|
|
47
|
+
output=output,
|
|
48
|
+
)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from PySide6.QtWidgets import QVBoxLayout
|
|
4
|
+
|
|
5
|
+
from pyvideokit_gui._base_panel import BasePanel
|
|
6
|
+
from pyvideokit_libs import apply_vhs_effect
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class VhsPanel(BasePanel):
|
|
10
|
+
def _build_ui(self, layout: QVBoxLayout):
|
|
11
|
+
self._input = self._input_row(layout, "Input file (must have audio)")
|
|
12
|
+
self._output = self._output_row(layout, "Output MKV (optional)")
|
|
13
|
+
|
|
14
|
+
def _run(self):
|
|
15
|
+
path = self._input.text().strip()
|
|
16
|
+
if not path:
|
|
17
|
+
self._status.setText("❌ Select an input file.")
|
|
18
|
+
return
|
|
19
|
+
output = self._output.text().strip() or None
|
|
20
|
+
self._start_worker(apply_vhs_effect, Path(path), output=output)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from PySide6.QtWidgets import QVBoxLayout
|
|
4
|
+
|
|
5
|
+
from pyvideokit_gui._base_panel import BasePanel
|
|
6
|
+
from pyvideokit_libs import prepare_youtube
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class YouTubePanel(BasePanel):
|
|
10
|
+
def _build_ui(self, layout: QVBoxLayout):
|
|
11
|
+
self._input = self._input_row(layout, "Input file (FFV1)")
|
|
12
|
+
self._output = self._output_row(layout, "Output MOV (optional)")
|
|
13
|
+
|
|
14
|
+
def _run(self):
|
|
15
|
+
path = self._input.text().strip()
|
|
16
|
+
if not path:
|
|
17
|
+
self._status.setText("❌ Select an input file.")
|
|
18
|
+
return
|
|
19
|
+
output = self._output.text().strip() or None
|
|
20
|
+
self._start_worker(prepare_youtube, Path(path), output=output)
|