fix: third-pass review bugs
- Switch DELETE /export to query param (path param strips leading /) - Add CropKeyframe Pydantic model for typed keyframe validation - Convert keyframes to tuples before passing to apply_keyframes_to_jobs - Remove dead QFrame import from main.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
from PyQt6.QtWidgets import (
|
from PyQt6.QtWidgets import (
|
||||||
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||||||
QLabel, QPushButton, QLineEdit, QFileDialog, QFrame,
|
QLabel, QPushButton, QLineEdit, QFileDialog,
|
||||||
QListWidget, QListWidgetItem, QAbstractItemView, QSplitter, QToolTip,
|
QListWidget, QListWidgetItem, QAbstractItemView, QSplitter, QToolTip,
|
||||||
QComboBox, QCheckBox, QSpinBox, QDoubleSpinBox,
|
QComboBox, QCheckBox, QSpinBox, QDoubleSpinBox,
|
||||||
QMessageBox, QInputDialog,
|
QMessageBox, QInputDialog,
|
||||||
|
|||||||
+17
-5
@@ -3,7 +3,7 @@ import re
|
|||||||
import shutil
|
import shutil
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from fastapi import APIRouter, HTTPException
|
from fastapi import APIRouter, HTTPException, Query
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from core.export import ExportRunner
|
from core.export import ExportRunner
|
||||||
@@ -19,6 +19,14 @@ _jobs: dict[str, dict] = {}
|
|||||||
_VALID_ENCODERS = {"libx264", "h264_nvenc", "h264_vaapi", "h264_qsv", "h264_amf", "h264_videotoolbox"}
|
_VALID_ENCODERS = {"libx264", "h264_nvenc", "h264_vaapi", "h264_qsv", "h264_amf", "h264_videotoolbox"}
|
||||||
|
|
||||||
|
|
||||||
|
class CropKeyframe(BaseModel):
|
||||||
|
time: float
|
||||||
|
center: float
|
||||||
|
ratio: str | None = None
|
||||||
|
rand_portrait: bool = False
|
||||||
|
rand_square: bool = False
|
||||||
|
|
||||||
|
|
||||||
class ExportRequest(BaseModel):
|
class ExportRequest(BaseModel):
|
||||||
input_path: str
|
input_path: str
|
||||||
cursor: float
|
cursor: float
|
||||||
@@ -33,7 +41,7 @@ class ExportRequest(BaseModel):
|
|||||||
category: str = ""
|
category: str = ""
|
||||||
profile: str = "default"
|
profile: str = "default"
|
||||||
folder_suffix: str = ""
|
folder_suffix: str = ""
|
||||||
crop_keyframes: list | None = None
|
crop_keyframes: list[CropKeyframe] | None = None
|
||||||
rand_portrait: bool = False
|
rand_portrait: bool = False
|
||||||
rand_square: bool = False
|
rand_square: bool = False
|
||||||
encoder: str = "libx264"
|
encoder: str = "libx264"
|
||||||
@@ -101,8 +109,12 @@ def start_export(req: ExportRequest):
|
|||||||
|
|
||||||
# Apply keyframes if provided — returns 6-tuples, strip back to 4
|
# Apply keyframes if provided — returns 6-tuples, strip back to 4
|
||||||
if req.crop_keyframes:
|
if req.crop_keyframes:
|
||||||
|
kf_tuples = [
|
||||||
|
(kf.time, kf.center, kf.ratio, kf.rand_portrait, kf.rand_square)
|
||||||
|
for kf in req.crop_keyframes
|
||||||
|
]
|
||||||
widened = apply_keyframes_to_jobs(
|
widened = apply_keyframes_to_jobs(
|
||||||
jobs, req.crop_keyframes,
|
jobs, kf_tuples,
|
||||||
req.crop_center, req.portrait_ratio,
|
req.crop_center, req.portrait_ratio,
|
||||||
req.rand_portrait, req.rand_square,
|
req.rand_portrait, req.rand_square,
|
||||||
)
|
)
|
||||||
@@ -176,8 +188,8 @@ def get_export_status(job_id: str):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/export/{output_path:path}")
|
@router.delete("/export")
|
||||||
def delete_export(output_path: str):
|
def delete_export(output_path: str = Query(...)):
|
||||||
from ..app import db
|
from ..app import db
|
||||||
# Validate path is under EXPORT_DIR
|
# Validate path is under EXPORT_DIR
|
||||||
real = os.path.realpath(output_path)
|
real = os.path.realpath(output_path)
|
||||||
|
|||||||
Reference in New Issue
Block a user