Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
.venv/
.ruff_cache/
*.pyc
uv.lock

# Tests
.pytest_cache
.coverage
coverage.*
htmlcov/

# Package
*.egg-info
19 changes: 7 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ build-backend = "setuptools.build_meta"

[project]
name = "subtle"
authors = [
{name = "Veronica Berglyd Olsen", email = "code@vkbo.net"},
]
authors = [{ name = "Veronica Berglyd Olsen", email = "code@vkbo.net" }]
description = "A simple subtitle editor and converter"
readme = {file = "README.md", content-type = "text/markdown"}
license = {text = "GNU General Public License v3"}
readme = { file = "README.md", content-type = "text/markdown" }
license = { text = "GNU General Public License v3" }
classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
Expand All @@ -23,10 +21,7 @@ classifiers = [
"Topic :: Multimedia",
]
requires-python = ">=3.11"
dependencies = [
"pyqt6>=6.4",
"pyenchant>=3.0.0",
]
dependencies = ["pyqt6>=6.4", "pyenchant>=3.0.0"]
dynamic = ["version"]

[project.urls]
Expand All @@ -38,13 +33,13 @@ Issues = "https://github.com/vkbo/subtle/issues"
subtle = "subtle:main"

[tool.setuptools.dynamic]
version = {attr = "subtle.__version__"}
version = { attr = "subtle.__init__.__version__" }

[tool.setuptools.packages.find]
include = ["subtle*"]

[tool.isort]
py_version="311"
py_version = "311"
line_length = 99
wrap_length = 79
multi_line_output = 5
Expand All @@ -56,7 +51,7 @@ forced_separate = ["tests.*", "PyQt6.*"]
line-length = 99

[tool.ruff.lint]
preview = true
preview = false

# Rules: https://docs.astral.sh/ruff/rules
select = [
Expand Down
12 changes: 7 additions & 5 deletions subtle/formats/srtsubs.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ def read(self, path: Path) -> None:
logger.error("Could not read SRT file: %s", self._path, exc_info=exc)
return

def write(self, path: Path | None = None) -> None:
def write(self, path: Path | None = None, offset: float = 0.0) -> None:
"""Writer SRT data to file."""
try:
if path is None:
path = self._path
if path:
self._writeData(path)
self._writeData(path, round(offset*1000.0))
except Exception as exc:
logger.error("Could not write SRT file: %s", self._path, exc_info=exc)
return
Expand All @@ -83,7 +83,7 @@ def _readData(self, path: Path) -> None:
self._parseFrame(block)
return

def _writeData(self, path: Path) -> None:
def _writeData(self, path: Path, offset: int = 0) -> None:
"""Write SRT text to file."""
with open(path, mode="w", encoding="utf-8") as fo:
prev = -1.0
Expand All @@ -92,7 +92,9 @@ def _writeData(self, path: Path) -> None:
for frame in self._frames:
if frame.start > prev and frame.text:
index += 1
fo.write(f"{index}\n{formatTS(frame.start)} --> {formatTS(frame.end)}\n")
start = frame.start + offset
end = frame.end + offset
fo.write(f"{index}\n{formatTS(start)} --> {formatTS(end)}\n")
fo.write("\n".join(frame.text))
fo.write("\n\n")
prev = frame.start
Expand All @@ -102,7 +104,7 @@ def _writeData(self, path: Path) -> None:
skipped += 1
if skipped:
logger.warning("Skipping %d entries with no text", skipped)
logger.info("Saved %d subtitle entries to SRT file.", index)
logger.info("Saved %d subtitle entries to SRT file with %d ms offset.", index, offset)
return

def _parseFrame(self, block: list[str]) -> None:
Expand Down
6 changes: 3 additions & 3 deletions subtle/gui/subsview.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,13 @@ def updateText(self, frame: FrameBase) -> None:
self._updateItemText(item, frame.text)
return

@pyqtSlot(Path)
def writeSrtFile(self, path: Path) -> None:
@pyqtSlot(Path, float)
def writeSrtFile(self, path: Path, offset: float = 0.0) -> None:
"""Save the processed subtitles to an SRT file."""
if SHARED.media.currentTrack:
writer = SRTSubs()
SHARED.media.currentTrack.copyFrames(writer)
writer.write(path)
writer.write(path, offset)
return

@pyqtSlot(Path)
Expand Down
16 changes: 12 additions & 4 deletions subtle/gui/toolspanel.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@

from PyQt6.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt6.QtWidgets import (
QCheckBox, QFormLayout, QGroupBox, QHBoxLayout, QLineEdit, QListWidget,
QListWidgetItem, QPushButton, QVBoxLayout, QWidget
QCheckBox, QDoubleSpinBox, QFormLayout, QGroupBox, QHBoxLayout, QLineEdit,
QListWidget, QListWidgetItem, QPushButton, QVBoxLayout, QWidget
)

logger = logging.getLogger(__name__)
Expand All @@ -40,7 +40,7 @@ class GuiToolsPanel(QWidget):

D_SUBS_PATH = Qt.ItemDataRole.UserRole

requestSrtSave = pyqtSignal(Path)
requestSrtSave = pyqtSignal(Path, float)
requestSubsLoad = pyqtSignal(Path)

def __init__(self, parent: QWidget) -> None:
Expand Down Expand Up @@ -92,6 +92,14 @@ def __init__(self, parent: QWidget) -> None:
self.srtFileName = QLineEdit(self)
self.srtForm.addRow(self.tr("File Name"), self.srtFileName)

self.srtOffset = QDoubleSpinBox(self)
self.srtOffset.setDecimals(3)
self.srtOffset.setSingleStep(0.1)
self.srtOffset.setValue(0.0)
self.srtOffset.setMinimum(-499999.0)
self.srtOffset.setMaximum(499999.0)
self.srtForm.addRow(self.tr("Time Offset"), self.srtOffset)

self.srtSubsDir = QCheckBox(self.tr("Use 'Subs' folder"), self)
self.srtSubsDir.clicked.connect(self._updateTrackInfo)

Expand Down Expand Up @@ -176,7 +184,7 @@ def _clickedSaveSrt(self) -> None:
folder = Path(self.srtSaveDir.text())
folder.mkdir(exist_ok=True)
if name := self.srtFileName.text().strip():
self.requestSrtSave.emit(folder / name)
self.requestSrtSave.emit(folder / name, self.srtOffset.value())
except Exception as exc:
logger.error("Failed to prepare subtitles folder", exc_info=exc)
return
Expand Down